kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit 5090ebea20215fe14b5d5250eba6b7b9ddd13b8a
parent 2821eccdfa009ffcf2ede1c9f2aec1c85d69782d
Author: Joris Vink <joris@coders.se>
Date:   Wed,  2 Jul 2014 12:16:31 +0200

Move contrib/modules to contrib/examples

Diffstat:
contrib/examples/generic/build.sh | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
contrib/examples/generic/media/index.html | 15+++++++++++++++
contrib/examples/generic/media/intro.jpg | 0
contrib/examples/generic/media/params.html | 33+++++++++++++++++++++++++++++++++
contrib/examples/generic/media/private.html | 16++++++++++++++++
contrib/examples/generic/media/private_test.html | 15+++++++++++++++
contrib/examples/generic/media/style.css | 16++++++++++++++++
contrib/examples/generic/media/upload.html | 22++++++++++++++++++++++
contrib/examples/generic/module.conf | 193+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
contrib/examples/generic/src/example.c | 361+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
contrib/examples/generic/tools/inject.c | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
contrib/examples/pgsql_test/build.sh | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
contrib/examples/pgsql_test/module.conf | 20++++++++++++++++++++
contrib/examples/pgsql_test/src/pgsql_test.c | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
contrib/examples/pgsql_test/tools/inject.c | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
contrib/examples/skeleton/build.sh | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
contrib/examples/skeleton/media/.gitignore | 0
contrib/examples/skeleton/src/.gitignore | 0
contrib/examples/skeleton/tools/inject.c | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
contrib/examples/task_curl/build.sh | 48++++++++++++++++++++++++++++++++++++++++++++++++
contrib/examples/task_curl/example.c | 217+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
contrib/examples/task_curl/module.conf | 31+++++++++++++++++++++++++++++++
contrib/modules/example/build.sh | 82-------------------------------------------------------------------------------
contrib/modules/example/media/index.html | 15---------------
contrib/modules/example/media/intro.jpg | 0
contrib/modules/example/media/params.html | 33---------------------------------
contrib/modules/example/media/private.html | 16----------------
contrib/modules/example/media/private_test.html | 15---------------
contrib/modules/example/media/style.css | 16----------------
contrib/modules/example/media/upload.html | 22----------------------
contrib/modules/example/module.conf | 193-------------------------------------------------------------------------------
contrib/modules/example/src/example.c | 361-------------------------------------------------------------------------------
contrib/modules/example/tools/inject.c | 119-------------------------------------------------------------------------------
contrib/modules/pgsql_test/build.sh | 71-----------------------------------------------------------------------
contrib/modules/pgsql_test/module.conf | 20--------------------
contrib/modules/pgsql_test/src/pgsql_test.c | 75---------------------------------------------------------------------------
contrib/modules/pgsql_test/tools/inject.c | 119-------------------------------------------------------------------------------
contrib/modules/skeleton/build.sh | 86-------------------------------------------------------------------------------
contrib/modules/skeleton/media/.gitignore | 0
contrib/modules/skeleton/src/.gitignore | 0
contrib/modules/skeleton/tools/inject.c | 119-------------------------------------------------------------------------------
contrib/modules/task_curl/build.sh | 48------------------------------------------------
contrib/modules/task_curl/example.c | 217-------------------------------------------------------------------------------
contrib/modules/task_curl/module.conf | 31-------------------------------
44 files changed, 1658 insertions(+), 1658 deletions(-)

diff --git a/contrib/examples/generic/build.sh b/contrib/examples/generic/build.sh @@ -0,0 +1,82 @@ +#!/bin/sh +# +# Copyright (c) 2013 Joris Vink <joris@coders.se> +# +# Kore module build script, use this as a base for building +# your own modules for kore. + +# The name of the module you will be building +MODULE=example.module + +# The directory containing all your media files (HTML, CSS, ...). +# These files will be compiled into the module and symbols will +# be exported for you to use in your code. +MEDIA_DIR=media + +# The directory containing your module source. +SOURCE_DIR=src + +# The directory containing the Kore source code. +KORE_DIR=../../../ + +# Compiler settings. +CC=gcc +CFLAGS="-I. -I${KORE_DIR}/includes -Wall -Wstrict-prototypes \ + -Wmissing-prototypes -Wmissing-declarations -Wshadow \ + -Wpointer-arith -Wcast-qual -Wsign-compare -g" + +OSNAME=$(uname -s | sed -e 's/[-_].*//g' | tr A-Z a-z) +if [ "${OSNAME}" = "darwin" ]; then + LDFLAGS="-dynamiclib -undefined suppress -flat_namespace" +else + LDFLAGS="-shared" +fi + +MODULE_BUILD_DATE=$(date +"%Y-%m-%d %H:%M:%S") + +### Begin building #### +echo "Building module ${MODULE}..." +rm -f ${MODULE} + +${CC} ${CFLAGS} tools/inject.c -o tools/inject + +if [ ! -d ${SOURCE_DIR}/${MEDIA_DIR} ]; then + mkdir ${SOURCE_DIR}/${MEDIA_DIR}; +fi +rm -f ${SOURCE_DIR}/${MEDIA_DIR}/* + +if [ ! -d .objs ]; then + mkdir .objs; +fi +rm -f .objs/* + +rm -f static.h + +for file in `find ${MEDIA_DIR} -type f \( ! -name \*.swp \)`; do + echo "Injecting $file"; + base=`basename $file`; + ./tools/inject $file $base > ${SOURCE_DIR}/${MEDIA_DIR}/${base}.c; + if [ $? -ne 0 ]; then + echo "Injection error, check above messages for clues."; + exit 1; + fi +done + +echo "#define MODULE_BUILD_DATE \"${MODULE_BUILD_DATE}\"" >> static.h + +for src in `find ${SOURCE_DIR} -type f -name \*.c`; do + base=`basename $src`; + ${CC} ${CFLAGS} -fPIC -c $src -o .objs/${base}.o + if [ $? -ne 0 ]; then + echo "Build error, check above messages for clues."; + exit 1; + fi +done + +${CC} ${LDFLAGS} `find .objs -name \*.o -type f` -o ${MODULE} +echo "Building completed!" + +rm -rf ${SOURCE_DIR}/${MEDIA_DIR} +rm -rf .objs +rm -f tools/inject +rm -f static.h diff --git a/contrib/examples/generic/media/index.html b/contrib/examples/generic/media/index.html @@ -0,0 +1,15 @@ +<!DOCTYPE> +<html> +<head> + <link rel="stylesheet" href="/css/style.css" type="text/css"> + <title>Your KORE module worked!</title> +</head> + +<body> + +<div class="content"> + <p>Your first Kore module worked.</p> +</div> + +</body> +</html> diff --git a/contrib/examples/generic/media/intro.jpg b/contrib/examples/generic/media/intro.jpg Binary files differ. diff --git a/contrib/examples/generic/media/params.html b/contrib/examples/generic/media/params.html @@ -0,0 +1,33 @@ +<!DOCTYPE> +<html> +<head> + <link rel="stylesheet" href="/css/style.css" type="text/css"> + <title>Kore params test</title> +</head> + +<body style="overflow: auto"> + +<div class="content" style="font-size: 12px; font-weight: normal"> + <p>You can pass one GET parameter (arg1), any other GET parameter will + be filtered out</p> + <p>Only two out of the three input fields will be visible to Kore.</p> + <p>The first field accepts the input "test"</p> + <p>The second field accepts anything like /test/[a-z]*</p> + <p>The third field will be removed by Kore, as it is not in the params + block configured for this page.</p> + <form method="POST"> + <input type="input" name="test1" value="$test1$"> + <input type="input" name="test2" value="$test2$"> + <input type="input" name="test3" value="$test3$"> + <input type="submit"> + </form> + + <p style="font-size: 12px; font-weight: normal">GET param arg1: $arg1$</p> + <p style="font-size: 12px; font-weight: normal">GET param arg2: $arg2$</p> + <p style="font-size: 12px; font-weight: normal">test1: $test1$</p> + <p style="font-size: 12px; font-weight: normal">test2: $test2$</p> + <p style="font-size: 12px; font-weight: normal">test3: $test3$</p> +</div> + +</body> +</html> diff --git a/contrib/examples/generic/media/private.html b/contrib/examples/generic/media/private.html @@ -0,0 +1,16 @@ +<!DOCTYPE> +<html> +<head> + <link rel="stylesheet" href="/css/style.css" type="text/css"> + <title>Kore Authentication tests</title> +</head> + +<body> + +<div class="content"> + <p style="font-size: small">The cookie session_id should now be set.</p> + <p style="font-size: small">You can continue to <a href="/private/test">view page handler in auth block</a></p> +</div> + +</body> +</html> diff --git a/contrib/examples/generic/media/private_test.html b/contrib/examples/generic/media/private_test.html @@ -0,0 +1,15 @@ +<!DOCTYPE> +<html> +<head> + <link rel="stylesheet" href="/css/style.css" type="text/css"> + <title>Kore Authentication tests</title> +</head> + +<body> + +<div class="content"> + <p style="font-size: small">If you see this, the authentication worked. This page should redirect back to /private once you remove your session_id cookie.</p> +</div> + +</body> +</html> diff --git a/contrib/examples/generic/media/style.css b/contrib/examples/generic/media/style.css @@ -0,0 +1,16 @@ +body { + width: 100%; + margin: 0px; + color: #000; + overflow: hidden; + background-color: #fff; +} + +.content { + width: 800px; + margin-left: auto; + margin-right: auto; + margin-top: 100px; + font-size: 60px; + text-align: center; +} diff --git a/contrib/examples/generic/media/upload.html b/contrib/examples/generic/media/upload.html @@ -0,0 +1,22 @@ +<!DOCTYPE> +<html> +<head> + <link rel="stylesheet" href="/css/style.css" type="text/css"> + <title>Kore upload test</title> +</head> + +<body style="overflow: auto"> + +<div class="content"> + <form method="POST" enctype="multipart/form-data"> + <input type="input" name="firstname"> + <input type="file" name="file"> + <input type="submit" value="upload"> + </form> + + <p style="font-size: 12px; font-weight: normal">$upload$</p> + <p style="font-size: 12px; font-weight: normal">$firstname$</p> +</div> + +</body> +</html> diff --git a/contrib/examples/generic/module.conf b/contrib/examples/generic/module.conf @@ -0,0 +1,193 @@ +# Example Kore configuration + +# Server configuration. +bind 127.0.0.1 443 + +# The path worker processes will chroot into after starting. +chroot /home/joris/src/kore + +# Worker processes will run as the specified user. +runas joris + +# Set workers to the amount of CPU's available in your system, +# kore will automatically distribute all workers on them. +workers 4 + +# The number of active connections each worker can handle. +# You might have to tweak this number based on your hardware. +#worker_max_connections 250 + +# Store the main process its pid in this file. +#pidfile /var/run/kore.pid + +# You can define a callback Kore calls from its parent process or +# workers everytime the kore_cb_interval timer (in milliseconds) is reached. +# +# NOTE: Remember that the parent process runs as root and is not chroot(). +# NOTE: If you want the cb to run on a worker, be sure to set kore_cb_worker. +#kore_cb my_callback +#kore_cb_interval 1000 +#kore_cb_worker 3 + +# HTTP specific settings. +# http_header_max Maximum size of HTTP headers (in bytes). +# +# http_postbody_max Maximum size of an HTTP POST body (in bytes). +# +# http_keepalive_time Maximum seconds an HTTP connection can be +# kept alive by the browser. +# (Set to 0 to disable keepalive completely). +# +# http_hsts_enable Send Strict Transport Security header in +# all responses. Parameter is the age. +# (Set to 0 to disable sending this header). +#http_header_max 4096 +#http_postbody_max 10240000 +#http_keepalive_time 0 +#http_hsts_enable 31536000 + +# Load modules (you can load multiple at the same time). +# An additional parameter can be specified as the "onload" function +# which Kore will call when the module is loaded/reloaded. +load contrib/modules/example/example.module example_load + +# Validators +# validator name type regex|function +# +validator v_example function v_example_func +validator v_regex regex ^/test/[a-z]*$ +validator v_number regex ^[0-9]*$ +validator v_session function v_session_validate + +# Specify the SSL ciphers that will be used. +#ssl_cipher ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK + +# If you wish to use EDH / ECDH specify a file containing +# a generated DH key (See OpenSSL dhparam). +#ssl_dhparam dh2048.pem + +# Set this if you want to disable SSL zlib compression. +ssl_no_compression + +# Specify the amount of seconds a SPDY connection is kept open. +# You can keep it open indefinately by setting this to 0. +#spdy_idle_time 120 + +# Authentication configuration +# +# Using authentication blocks you can define a standard way for +# Kore to validate your users. In the example below we create +# a authentication block called auth_example, which requires +# a cookie (session_id) to be set. +# +# If no cookie is present or the cookie is not valid according +# to the set validator, Kore will redirect the browser to the +# URI set in authentication_uri. +# +# Page handlers can be bound to authentication by specifying +# authentication block at the end of the page directive (see below). +authentication auth_example { + # The authentication type denotes the way the user should + # be authenticated. + # + # Allow values: + # - cookie (checks for the cookie presence + pass to validator) + # - header (checks for header presence + pass to validator) + # - requuest (passes the http_request to the validator) + # + # Use cases for request could for example be IP based ACLs or + # any other criteria that can be extracted from a http_request. + # + # The request type does not need an authentication_validator. + # + authentication_type cookie + + # The name of whatever we are looking for. + authentication_value session_id + + # The validator that will be called to verify the cookie. + # Note this is YOUR validator, Kore does not have built-in + # session support. You must add this manually using your + # preferred method (Storing it in postgres, redis, ...) + authentication_validator v_session + + # The URI Kore will redirect to if a authentication fails. + # If this is not set, Kore will return a simple 403. + authentication_uri /private +} + +# Domain configuration +# +# Each domain configuration starts with listing what domain +# the directives that follow are to be applied upon. +# +# Additionally you can specify the following in a domain configuration: +# +# accesslog +# - File where all requests are logged. +# require_client_cert +# - Asks the client to present a certificate +# matching the CA given to require_client_cert +# +# Handlers +# +# Handlers are either static (for fixed paths) or dynamic. +# Dynamic handlers take a POSIX regular expression as its path. +# +# Syntax: +# handler path module_callback [auth block] +# +# Note that the auth block is optional and if set will force Kore to +# authenticate the user according to the authentication block its settings +# before allowing access to the page. + +# Example domain that responds to localhost. +domain localhost { + certfile cert/server.crt + certkey cert/server.key + accesslog /var/log/kore_access.log + + # Page handlers with no authentication required. + static /css/style.css serve_style_css + static / serve_index + static /intro.jpg serve_intro + static /b64test serve_b64test + static /spdy-reset serve_spdyreset + static /upload serve_file_upload + static /lock-test serve_lock_test + static /validator serve_validator + static /params-test serve_params_test + static /private serve_private + + # Page handlers with authentication. + static /private/test serve_private_test auth_example + + # Configure /params-test POST to only accept the following parameters. + # They are automatically tested against the validator listed. + # If the validator would fail Kore will automatically remove the + # failing parameter, indicating something was wrong with it. + # Any parameters not present in the params block are also filtered out. + params post /params-test { + validate test1 v_example + validate test2 v_regex + } + + # Configure a GET parameter that /params-test can received. As before + # this is validated against the validator and removed if validation + # fails. All extra parameters in the GET query are filtered out. + params get /params-test { + validate arg1 v_example + validate id v_number + } +} + +#domain domain.com { +# certfile cert/other/server.crt +# certkey cert/other/server.key +# accesslog /var/log/other_kore_access.log +# require_client_cert cert/other/ca.crt + +# static /css/style.css serve_style_css +# static / serve_index +# dynamic ^/[a-z0-9_]*$ serve_profile +#} diff --git a/contrib/examples/generic/src/example.c b/contrib/examples/generic/src/example.c @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2013 Joris Vink <joris@coders.se> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "kore.h" +#include "http.h" + +#include "static.h" + +void example_load(int); + +int serve_style_css(struct http_request *); +int serve_index(struct http_request *); +int serve_intro(struct http_request *); +int serve_b64test(struct http_request *); +int serve_spdyreset(struct http_request *); +int serve_file_upload(struct http_request *); +int serve_lock_test(struct http_request *); +int serve_validator(struct http_request *); +int serve_params_test(struct http_request *); +int serve_private(struct http_request *); +int serve_private_test(struct http_request *); + +void my_callback(void); +int v_example_func(struct http_request *, char *); +int v_session_validate(struct http_request *, char *); +void test_base64(u_int8_t *, u_int32_t, struct kore_buf *); + +char *b64tests[] = { + "1234567890", + "One two three four five", + "Man", + "any carnal pleasure.", + "any carnal pleasure", + "any carnal pleas", + "I am a nobody, nobody is perfect, therefor I am.", + NULL +}; + +void +example_load(int state) +{ + switch (state) { + case KORE_MODULE_LOAD: + kore_log(LOG_NOTICE, "module loading"); + break; + case KORE_MODULE_UNLOAD: + kore_log(LOG_NOTICE, "module unloading"); + break; + default: + kore_log(LOG_NOTICE, "state %d unknown!", state); + break; + } +} + +int +serve_style_css(struct http_request *req) +{ + char *date; + time_t tstamp; + + tstamp = 0; + if (http_request_header_get(req, "if-modified-since", &date)) { + tstamp = kore_date_to_time(date); + kore_mem_free(date); + + kore_debug("header was present with %ld", tstamp); + } + + if (tstamp != 0 && tstamp <= static_mtime_css_style) { + http_response(req, 304, NULL, 0); + } else { + date = kore_time_to_date(static_mtime_css_style); + if (date != NULL) + http_response_header_add(req, "last-modified", date); + + http_response_header_add(req, "content-type", "text/css"); + http_response(req, 200, static_css_style, static_len_css_style); + } + + return (KORE_RESULT_OK); +} + +int +serve_index(struct http_request *req) +{ + http_response_header_add(req, "content-type", "text/html"); + http_response(req, 200, static_html_index, static_len_html_index); + + return (KORE_RESULT_OK); +} + +int +serve_intro(struct http_request *req) +{ + http_response_header_add(req, "content-type", "image/jpg"); + http_response(req, 200, static_jpg_intro, static_len_jpg_intro); + + return (KORE_RESULT_OK); +} + +int +serve_b64test(struct http_request *req) +{ + int i; + u_int32_t len; + struct kore_buf *res; + u_int8_t *data; + + res = kore_buf_create(1024); + for (i = 0; b64tests[i] != NULL; i++) + test_base64((u_int8_t *)b64tests[i], strlen(b64tests[i]), res); + + data = kore_buf_release(res, &len); + + http_response_header_add(req, "content-type", "text/plain"); + http_response(req, 200, data, len); + kore_mem_free(data); + + return (KORE_RESULT_OK); +} + +int +serve_spdyreset(struct http_request *req) +{ + spdy_session_teardown(req->owner, SPDY_SESSION_ERROR_OK); + return (KORE_RESULT_OK); +} + +int +serve_file_upload(struct http_request *req) +{ + int r; + u_int8_t *d; + struct kore_buf *b; + u_int32_t len; + char *name, buf[BUFSIZ]; + + b = kore_buf_create(static_len_html_upload); + kore_buf_append(b, static_html_upload, static_len_html_upload); + + if (req->method == HTTP_METHOD_POST) { + http_populate_multipart_form(req, &r); + if (http_argument_get_string("firstname", &name, &len)) { + kore_buf_replace_string(b, "$firstname$", name, len); + } else { + kore_buf_replace_string(b, "$firstname$", NULL, 0); + } + + if (http_file_lookup(req, "file", &name, &d, &len)) { + snprintf(buf, sizeof(buf), "%s is %d bytes", name, len); + kore_buf_replace_string(b, + "$upload$", buf, strlen(buf)); + } else { + kore_buf_replace_string(b, "$upload$", NULL, 0); + } + } else { + kore_buf_replace_string(b, "$upload$", NULL, 0); + kore_buf_replace_string(b, "$firstname$", NULL, 0); + } + + d = kore_buf_release(b, &len); + + http_response_header_add(req, "content-type", "text/html"); + http_response(req, 200, d, len); + kore_mem_free(d); + + return (KORE_RESULT_OK); +} + +int +serve_lock_test(struct http_request *req) +{ + kore_log(LOG_NOTICE, "lock-test called on worker %d", worker->id); + kore_worker_acceptlock_release(); + + http_response(req, 200, "OK", 2); + return (KORE_RESULT_OK); +} + +void +test_base64(u_int8_t *src, u_int32_t slen, struct kore_buf *res) +{ + char *in; + u_int32_t len; + u_int8_t *out; + + kore_buf_appendf(res, "test '%s'\n", src); + + if (!kore_base64_encode(src, slen, &in)) { + kore_buf_appendf(res, "encoding '%s' failed\n", src); + } else { + kore_buf_appendf(res, "encoded: '%s'\n", in); + + if (!kore_base64_decode(in, &out, &len)) { + kore_buf_appendf(res, "decoding failed\n"); + } else { + kore_buf_appendf(res, "decoded: "); + kore_buf_append(res, out, len); + kore_buf_appendf(res, "\n"); + kore_mem_free(out); + } + + kore_mem_free(in); + } + + kore_buf_appendf(res, "\n"); +} + +int +serve_validator(struct http_request *req) +{ + if (kore_validator_run(NULL, "v_example", "test")) + kore_log(LOG_NOTICE, "v_example ok (expected)"); + else + kore_log(LOG_NOTICE, "v_example failed"); + + if (kore_validator_run(NULL, "v_regex", "/test/123")) + kore_log(LOG_NOTICE, "regex #1 ok"); + else + kore_log(LOG_NOTICE, "regex #1 failed (expected)"); + + if (kore_validator_run(NULL, "v_regex", "/test/joris")) + kore_log(LOG_NOTICE, "regex #2 ok (expected)"); + else + kore_log(LOG_NOTICE, "regex #2 failed"); + + http_response(req, 200, "OK", 2); + + return (KORE_RESULT_OK); +} + +int +serve_params_test(struct http_request *req) +{ + struct kore_buf *b; + u_int8_t *d; + u_int32_t len; + int r, i; + char *test, name[10]; + + http_populate_arguments(req); + + b = kore_buf_create(static_len_html_params); + kore_buf_append(b, static_html_params, static_len_html_params); + + /* + * The GET parameters will be filtered out on POST. + */ + if (http_argument_get_string("arg1", &test, &len)) { + kore_buf_replace_string(b, "$arg1$", test, len); + } else { + kore_buf_replace_string(b, "$arg1$", NULL, 0); + } + + if (http_argument_get_string("arg2", &test, &len)) { + kore_buf_replace_string(b, "$arg2$", test, len); + } else { + kore_buf_replace_string(b, "$arg2$", NULL, 0); + } + + if (req->method == HTTP_METHOD_GET) { + kore_buf_replace_string(b, "$test1$", NULL, 0); + kore_buf_replace_string(b, "$test2$", NULL, 0); + kore_buf_replace_string(b, "$test3$", NULL, 0); + + if (http_argument_get_uint16("id", &r)) + kore_log(LOG_NOTICE, "id: %d", r); + else + kore_log(LOG_NOTICE, "No id set"); + + http_response_header_add(req, "content-type", "text/html"); + d = kore_buf_release(b, &len); + http_response(req, 200, d, len); + kore_mem_free(d); + + return (KORE_RESULT_OK); + } + + for (i = 1; i < 4; i++) { + snprintf(name, sizeof(name), "test%d", i); + if (http_argument_get_string(name, &test, &len)) { + snprintf(name, sizeof(name), "$test%d$", i); + kore_buf_replace_string(b, name, test, len); + } else { + snprintf(name, sizeof(name), "$test%d$", i); + kore_buf_replace_string(b, name, NULL, 0); + } + } + + http_response_header_add(req, "content-type", "text/html"); + d = kore_buf_release(b, &len); + http_response(req, 200, d, len); + kore_mem_free(d); + + return (KORE_RESULT_OK); +} + +int +serve_private(struct http_request *req) +{ + http_response_header_add(req, "content-type", "text/html"); + http_response_header_add(req, "set-cookie", "session_id=test123"); + http_response(req, 200, static_html_private, static_len_html_private); + + return (KORE_RESULT_OK); +} + +int +serve_private_test(struct http_request *req) +{ + http_response_header_add(req, "content-type", "text/html"); + + http_response(req, 200, static_html_private_test, + static_len_html_private_test); + + return (KORE_RESULT_OK); +} + +void +my_callback(void) +{ + if (worker != NULL) + kore_log(LOG_NOTICE, "running on worker %d", worker->id); + else + kore_log(LOG_NOTICE, "running from parent"); +} + +int +v_example_func(struct http_request *req, char *data) +{ + kore_log(LOG_NOTICE, "v_example_func called"); + + if (!strcmp(data, "test")) + return (KORE_RESULT_OK); + + return (KORE_RESULT_ERROR); +} + +int +v_session_validate(struct http_request *req, char *data) +{ + kore_log(LOG_NOTICE, "v_session_validate: %s", data); + + if (!strcmp(data, "test123")) + return (KORE_RESULT_OK); + + return (KORE_RESULT_ERROR); +} diff --git a/contrib/examples/generic/tools/inject.c b/contrib/examples/generic/tools/inject.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2013 Joris Vink <joris@coders.se> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/stat.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <inttypes.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#if defined(OpenBSD) +#define PRI_TIME_T "d" +#endif + +#if defined(linux) +#if defined(__x86_64__) +#define PRI_TIME_T PRIu64 +#else +#define PRI_TIME_T "ld" +#endif +#endif + +#if defined(__MACH__) +#define PRI_TIME_T "ld" +#endif + +int +main(int argc, char *argv[]) +{ + struct stat st; + ssize_t len; + FILE *hdr; + char *ext; + unsigned char c[1]; + int fd, newline, count; + + if (argc != 3) + exit(1); + + if ((fd = open(argv[1], O_RDONLY)) == -1) + err(1, "open() %d", errno); + if ((hdr = fopen("static.h", "a+")) == NULL) + err(1, "fopen() %d", errno); + if ((ext = strchr(argv[2], '.')) != NULL) + *(ext)++ = '\0'; + else + ext = ""; + + if (stat(argv[1], &st) == -1) { + printf("stat(%s) failed: %d\n", argv[1], errno); + exit(1); + } + + printf("/**** AUTO GENERATED BY MAKEFILE - DO NOT TOUCH ****/\n"); + printf("#include <sys/param.h>\n\n"); + printf("u_int8_t static_%s_%s[] = {", ext, argv[2]); + + len = 0; + count = 0; + newline = 1; + for (;;) { + if (newline) { + printf("\n\t"); + count = 0; + newline = 0; + } + + len = read(fd, c, 1); + if (len == 0) + break; + + if (len == -1) { + printf("read(): %d\n", errno); + exit(1); + } + + if (len != 1) + exit(1); + + printf("0x%02x, ", c[0]); + if (count++ == 10) + newline = 1; + } + + close(fd); + + printf("};\n\n"); + printf("u_int32_t static_len_%s_%s = %" PRIu32 ";\n", + ext, argv[2], (u_int32_t)st.st_size); + + printf("time_t static_mtime_%s_%s = %" PRI_TIME_T ";\n", + ext, argv[2], st.st_mtime); + + fprintf(hdr, "extern u_int8_t static_%s_%s[];\n", ext, argv[2]); + fprintf(hdr, "extern u_int32_t static_len_%s_%s;\n", ext, argv[2]); + fprintf(hdr, "extern time_t static_mtime_%s_%s;\n", ext, argv[2]); + fclose(hdr); + + return (0); +} diff --git a/contrib/examples/pgsql_test/build.sh b/contrib/examples/pgsql_test/build.sh @@ -0,0 +1,71 @@ +#!/bin/sh +# +# Kore pgsql test module build directives. +# + +MODULE=pgsql_test.module +MEDIA_DIR=media +SOURCE_DIR=src +KORE_DIR=../../.. +PGDIR=$(pg_config --includedir) +CC=gcc +CFLAGS="-I. -I${KORE_DIR}/includes -I${PGDIR} \ + -Wall -Wstrict-prototypes -Wmissing-prototypes \ + -Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual \ + -Wsign-compare -g" + +OSNAME=$(uname -s | sed -e 's/[-_].*//g' | tr A-Z a-z) +if [ "${OSNAME}" = "darwin" ]; then + LDFLAGS="-dynamiclib -undefined suppress -flat_namespace" +else + LDFLAGS="-shared" +fi + +MODULE_BUILD_DATE=$(date +"%Y-%m-%d %H:%M:%S") + +### Begin building #### +echo "Building module ${MODULE}..." +rm -f ${MODULE} + +${CC} ${CFLAGS} tools/inject.c -o tools/inject + +if [ ! -d ${SOURCE_DIR}/${MEDIA_DIR} ]; then + mkdir ${SOURCE_DIR}/${MEDIA_DIR}; +fi +rm -f ${SOURCE_DIR}/${MEDIA_DIR}/* + +if [ ! -d .objs ]; then + mkdir .objs; +fi +rm -f .objs/* + +rm -f static.h + +for file in `find ${MEDIA_DIR} -type f \( ! -name \*.swp \)`; do + echo "Injecting $file"; + base=`basename $file`; + ./tools/inject $file $base > ${SOURCE_DIR}/${MEDIA_DIR}/${base}.c; + if [ $? -ne 0 ]; then + echo "Injection error, check above messages for clues."; + exit 1; + fi +done + +echo "#define MODULE_BUILD_DATE \"${MODULE_BUILD_DATE}\"" >> static.h + +for src in `find ${SOURCE_DIR} -type f -name \*.c`; do + base=`basename $src`; + ${CC} ${CFLAGS} -fPIC -c $src -o .objs/${base}.o + if [ $? -ne 0 ]; then + echo "Build error, check above messages for clues."; + exit 1; + fi +done + +${CC} ${LDFLAGS} `find .objs -name \*.o -type f` -o ${MODULE} +echo "Building completed!" + +rm -rf ${SOURCE_DIR}/${MEDIA_DIR} +rm -rf .objs +rm -f tools/inject +rm -f static.h diff --git a/contrib/examples/pgsql_test/module.conf b/contrib/examples/pgsql_test/module.conf @@ -0,0 +1,20 @@ +# Kore pgsql_test configuration +# see modules/examples/module.conf for a better overview +# of what a configuration file has to offer and what different +# settings mean and do. + +bind 127.0.0.1 8080 +chroot /home/joris/src/kore +runas joris +workers 4 +pidfile kore.pid +load contrib/modules/pgsql_test/pgsql_test.module pgsql_load +ssl_no_compression + +domain localhost { + certfile cert/server.crt + certkey cert/server.key + accesslog kore_pgsql.log + + static / serve_pgsql_test +} diff --git a/contrib/examples/pgsql_test/src/pgsql_test.c b/contrib/examples/pgsql_test/src/pgsql_test.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2014 Joris Vink <joris@coders.se> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "kore.h" +#include "http.h" +#include "kore_pgsql.h" + +#include "static.h" + +void pgsql_load(int); +int serve_pgsql_test(struct http_request *); + +void +pgsql_load(int state) +{ + switch (state) { + case KORE_MODULE_LOAD: + pgsql_conn_string = "Your connection string"; + break; + default: + break; + } +} + +int +serve_pgsql_test(struct http_request *req) +{ + int r, i; + char *col1, *col2; + + KORE_PGSQL(req, "SELECT * FROM test", 0, { + if (req->pgsql[0]->state == KORE_PGSQL_STATE_ERROR) { + kore_pgsql_logerror(req->pgsql[0]); + http_response(req, 500, "fail\n", 5); + return (KORE_RESULT_OK); + } + + r = kore_pgsql_ntuples(req->pgsql[0]); + for (i = 0; i < r; i++) { + col1 = kore_pgsql_getvalue(req->pgsql[0], i, 0); + col2 = kore_pgsql_getvalue(req->pgsql[0], i, 1); + + kore_log(LOG_NOTICE, "%s and %s", col1, col2); + } + }); + + KORE_PGSQL(req, "SELECT * FROM foobar", 1, { + if (req->pgsql[1]->state != KORE_PGSQL_STATE_ERROR) { + kore_log(LOG_NOTICE, "expected error, got %d", + req->pgsql[1]->state); + http_response(req, 500, "fail2\n", 6); + return (KORE_RESULT_OK); + } else { + kore_pgsql_logerror(req->pgsql[1]); + } + }); + + /* Query successfully completed */ + http_response(req, 200, "ok\n", 3); + + return (KORE_RESULT_OK); +} diff --git a/contrib/examples/pgsql_test/tools/inject.c b/contrib/examples/pgsql_test/tools/inject.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2013 Joris Vink <joris@coders.se> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/stat.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <inttypes.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#if defined(OpenBSD) +#define PRI_TIME_T "d" +#endif + +#if defined(linux) +#if defined(__x86_64__) +#define PRI_TIME_T PRIu64 +#else +#define PRI_TIME_T "ld" +#endif +#endif + +#if defined(__MACH__) +#define PRI_TIME_T "ld" +#endif + +int +main(int argc, char *argv[]) +{ + struct stat st; + ssize_t len; + FILE *hdr; + char *ext; + unsigned char c[1]; + int fd, newline, count; + + if (argc != 3) + exit(1); + + if ((fd = open(argv[1], O_RDONLY)) == -1) + err(1, "open() %d", errno); + if ((hdr = fopen("static.h", "a+")) == NULL) + err(1, "fopen() %d", errno); + if ((ext = strchr(argv[2], '.')) != NULL) + *(ext)++ = '\0'; + else + ext = ""; + + if (stat(argv[1], &st) == -1) { + printf("stat(%s) failed: %d\n", argv[1], errno); + exit(1); + } + + printf("/**** AUTO GENERATED BY MAKEFILE - DO NOT TOUCH ****/\n"); + printf("#include <sys/param.h>\n\n"); + printf("u_int8_t static_%s_%s[] = {", ext, argv[2]); + + len = 0; + count = 0; + newline = 1; + for (;;) { + if (newline) { + printf("\n\t"); + count = 0; + newline = 0; + } + + len = read(fd, c, 1); + if (len == 0) + break; + + if (len == -1) { + printf("read(): %d\n", errno); + exit(1); + } + + if (len != 1) + exit(1); + + printf("0x%02x, ", c[0]); + if (count++ == 10) + newline = 1; + } + + close(fd); + + printf("};\n\n"); + printf("u_int32_t static_len_%s_%s = %" PRIu32 ";\n", + ext, argv[2], (u_int32_t)st.st_size); + + printf("time_t static_mtime_%s_%s = %" PRI_TIME_T ";\n", + ext, argv[2], st.st_mtime); + + fprintf(hdr, "extern u_int8_t static_%s_%s[];\n", ext, argv[2]); + fprintf(hdr, "extern u_int32_t static_len_%s_%s;\n", ext, argv[2]); + fprintf(hdr, "extern time_t static_mtime_%s_%s;\n", ext, argv[2]); + fclose(hdr); + + return (0); +} diff --git a/contrib/examples/skeleton/build.sh b/contrib/examples/skeleton/build.sh @@ -0,0 +1,86 @@ +#!/bin/sh +# +# Copyright (c) 2013 Joris Vink <joris@coders.se> +# +# Kore module build script, use this as a base for building +# your own modules for kore. + +# The name of the module you will be building +MODULE=site.module + +# The directory containing all your media files (HTML, CSS, ...). +# These files will be compiled into the module and symbols will +# be exported for you to use in your code. +MEDIA_DIR=media + +# The directory containing your module source. +SOURCE_DIR=src + +# The directory containing the Kore source code. +KORE_DIR="notset" +if [ ${KORE_DIR} = "notset" ]; then + echo "Please edit build.sh and set KORE_DIR properly"; + exit; +fi + +# Compiler settings. +CC=gcc +CFLAGS="-I. -I${KORE_DIR}/includes -Wall -Wstrict-prototypes \ + -Wmissing-prototypes -Wmissing-declarations -Wshadow \ + -Wpointer-arith -Wcast-qual -Wsign-compare -g" + +OSNAME=$(uname -s | sed -e 's/[-_].*//g' | tr A-Z a-z) +if [ "${OSNAME}" = "darwin" ]; then + LDFLAGS="-dynamiclib -undefined suppress -flat_namespace" +else + LDFLAGS="-shared" +fi + +MODULE_BUILD_DATE=$(date +"%Y-%m-%d %H:%M:%S") + +### Begin building #### +echo "Building module ${MODULE}..." +rm -f ${MODULE} + +${CC} ${CFLAGS} tools/inject.c -o tools/inject + +if [ ! -d ${SOURCE_DIR}/${MEDIA_DIR} ]; then + mkdir ${SOURCE_DIR}/${MEDIA_DIR}; +fi +rm -f ${SOURCE_DIR}/${MEDIA_DIR}/* + +if [ ! -d .objs ]; then + mkdir .objs; +fi +rm -f .objs/* + +rm -f static.h + +for file in `find ${MEDIA_DIR} -type f \( ! -name \*.swp \)`; do + echo "Injecting $file"; + base=`basename $file`; + ./tools/inject $file $base > ${SOURCE_DIR}/${MEDIA_DIR}/${base}.c; + if [ $? -ne 0 ]; then + echo "Injection error, check above messages for clues."; + exit 1; + fi +done + +echo "#define MODULE_BUILD_DATE \"${MODULE_BUILD_DATE}\"" >> static.h + +for src in `find ${SOURCE_DIR} -type f -name \*.c`; do + base=`basename $src`; + ${CC} ${CFLAGS} -fPIC -c $src -o .objs/${base}.o + if [ $? -ne 0 ]; then + echo "Build error, check above messages for clues."; + exit 1; + fi +done + +${CC} ${LDFLAGS} `find .objs -name \*.o -type f` -o ${MODULE} +echo "Building completed!" + +rm -rf ${SOURCE_DIR}/${MEDIA_DIR} +rm -rf .objs +rm -f tools/inject +rm -f static.h diff --git a/contrib/examples/skeleton/media/.gitignore b/contrib/examples/skeleton/media/.gitignore diff --git a/contrib/examples/skeleton/src/.gitignore b/contrib/examples/skeleton/src/.gitignore diff --git a/contrib/examples/skeleton/tools/inject.c b/contrib/examples/skeleton/tools/inject.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2013 Joris Vink <joris@coders.se> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/stat.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <inttypes.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#if defined(OpenBSD) +#define PRI_TIME_T "d" +#endif + +#if defined(linux) +#if defined(__x86_64__) +#define PRI_TIME_T PRIu64 +#else +#define PRI_TIME_T "ld" +#endif +#endif + +#if defined(__MACH__) +#define PRI_TIME_T "ld" +#endif + +int +main(int argc, char *argv[]) +{ + struct stat st; + ssize_t len; + FILE *hdr; + char *ext; + unsigned char c[1]; + int fd, newline, count; + + if (argc != 3) + exit(1); + + if ((fd = open(argv[1], O_RDONLY)) == -1) + err(1, "open() %d", errno); + if ((hdr = fopen("static.h", "a+")) == NULL) + err(1, "fopen() %d", errno); + if ((ext = strchr(argv[2], '.')) != NULL) + *(ext)++ = '\0'; + else + ext = ""; + + if (stat(argv[1], &st) == -1) { + printf("stat(%s) failed: %d\n", argv[1], errno); + exit(1); + } + + printf("/**** AUTO GENERATED BY MAKEFILE - DO NOT TOUCH ****/\n"); + printf("#include <sys/param.h>\n\n"); + printf("u_int8_t static_%s_%s[] = {", ext, argv[2]); + + len = 0; + count = 0; + newline = 1; + for (;;) { + if (newline) { + printf("\n\t"); + count = 0; + newline = 0; + } + + len = read(fd, c, 1); + if (len == 0) + break; + + if (len == -1) { + printf("read(): %d\n", errno); + exit(1); + } + + if (len != 1) + exit(1); + + printf("0x%02x, ", c[0]); + if (count++ == 10) + newline = 1; + } + + close(fd); + + printf("};\n\n"); + printf("u_int32_t static_len_%s_%s = %" PRIu32 ";\n", + ext, argv[2], (u_int32_t)st.st_size); + + printf("time_t static_mtime_%s_%s = %" PRI_TIME_T ";\n", + ext, argv[2], st.st_mtime); + + fprintf(hdr, "extern u_int8_t static_%s_%s[];\n", ext, argv[2]); + fprintf(hdr, "extern u_int32_t static_len_%s_%s;\n", ext, argv[2]); + fprintf(hdr, "extern time_t static_mtime_%s_%s;\n", ext, argv[2]); + fclose(hdr); + + return (0); +} diff --git a/contrib/examples/task_curl/build.sh b/contrib/examples/task_curl/build.sh @@ -0,0 +1,48 @@ +#!/bin/sh +# +# Copyright (c) 2013 Joris Vink <joris@coders.se> +# +# Kore module build script, use this as a base for building +# your own modules for kore. + +# The name of the module you will be building +MODULE=task_curl.so + +# The directory containing your module source. +SOURCE_DIR=. + +# The directory containing the Kore source code. +KORE_DIR=../../../ + +# Compiler settings. +CC=gcc +CFLAGS="-I. -I${KORE_DIR}/includes -Wall -Wstrict-prototypes \ + -Wmissing-prototypes -Wmissing-declarations -Wshadow \ + -Wpointer-arith -Wcast-qual -Wsign-compare -g" + +LDFLAGS="-shared -lcurl" + +MODULE_BUILD_DATE=$(date +"%Y-%m-%d %H:%M:%S") + +### Begin building #### +echo "Building module ${MODULE}..." +rm -f ${MODULE} + +if [ ! -d .objs ]; then + mkdir .objs; +fi +rm -f .objs/* + +for src in `find ${SOURCE_DIR} -type f -name \*.c`; do + base=`basename $src`; + ${CC} ${CFLAGS} -fPIC -c $src -o .objs/${base}.o + if [ $? -ne 0 ]; then + echo "Build error, check above messages for clues."; + exit 1; + fi +done + +${CC} ${LDFLAGS} `find .objs -name \*.o -type f` -o ${MODULE} +echo "Building completed!" + +rm -rf .objs diff --git a/contrib/examples/task_curl/example.c b/contrib/examples/task_curl/example.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2014 Joris Vink <joris@coders.se> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * In this example, we use the background tasks available in Kore + * to fire off a POST to our /post_back page handler containing + * the user argument that was passed to us in our GET request to /. + * + * This illustrates how Kore its background tasks in effect work and + * how to operate on the channel in order to pass data back and forth. + * + * The page_handler() page handler is not called until the background + * task it fired off has completed. + * + * You need libcurl installed for this to build (including headers) + * + * Compile using build.sh, afterwards start using: + * # kore -nc module.conf (depending on where kore is installed) + * + * Test using: + * # curl -k https://127.0.0.1:4443/?user=foobar + * + * If the result echo'd back matches what you specified, its all green. + */ + +#include <curl/curl.h> + +#include "kore.h" +#include "http.h" +#include "kore_tasks.h" + +int run_curl(struct kore_task *); +int post_back(struct http_request *); +int page_handler(struct http_request *); +size_t curl_write_cb(char *, size_t, size_t, void *); + +int +page_handler(struct http_request *req) +{ + u_int32_t len; + char *user, result[64]; + + /* + * Lets check if a task has been created yet, this is important + * as we only want to fire this off once and we will be called + * again once it has been created. + */ + if (req->task == NULL) { + /* Grab the user argument */ + http_populate_arguments(req); + if (!http_argument_get_string("user", &user, &len)) { + http_response(req, 500, "ERROR\n", 6); + return (KORE_RESULT_OK); + } + + /* + * Create a new task that will execute the run_curl() + * function and bind it to our request. + * + * Binding a task to a request means Kore will reschedule + * the page handler for that request to refire after the + * task has completed. + */ + kore_task_create(&req->task, run_curl); + kore_task_bind_request(req->task, req); + + /* + * Start the task and write the user we received in our + * GET request to its channel. + */ + kore_task_run(req->task); + kore_task_channel_write(req->task, user, len); + + /* + * Tell Kore to retry us later. + */ + return (KORE_RESULT_RETRY); + } + + /* + * When we come back here, our background task is finished + * and we can check its result. + */ + if (req->task->result != KORE_RESULT_OK) { + kore_task_destroy(req->task); + http_response(req, 500, NULL, 0); + return (KORE_RESULT_OK); + } + + /* + * Lets read what our task has written to the channel. + * + * kore_task_channel_read() will return the amount of bytes + * that it received for that read. If the returned bytes is + * larger then the buffer you passed this is a sign of truncation + * and should be treated carefully. + */ + len = kore_task_channel_read(req->task, result, sizeof(result)); + if (len >= sizeof(result)) { + http_response(req, 500, NULL, 0); + } else { + http_response(req, 200, result, len); + } + + /* We good, destroy the task. */ + kore_task_destroy(req->task); + + return (KORE_RESULT_OK); +} + +int +post_back(struct http_request *req) +{ + u_int32_t len; + char *user; + + if (req->method != HTTP_METHOD_POST) { + http_response(req, 500, NULL, 0); + return (KORE_RESULT_OK); + } + + http_populate_arguments(req); + if (!http_argument_get_string("user", &user, &len)) { + http_response(req, 500, NULL, 0); + return (KORE_RESULT_OK); + } + + /* Simply echo the supplied user argument back. */ + http_response(req, 200, user, len); + + return (KORE_RESULT_OK); +} + +/* + * This is the function that is executed by our task which is created + * in the page_handler() callback. + * + * It sets up a CURL POST request to /post_back passing along the + * user argument which it receives from its channel from page_handler(). + */ +int +run_curl(struct kore_task *t) +{ + int l; + struct kore_buf *b; + u_int32_t len; + CURLcode res; + u_int8_t *data; + CURL *curl; + char user[64], fields[128]; + + /* + * Read the channel in order to obtain the user argument + * that was written to it by page_handler(). + */ + len = kore_task_channel_read(t, user, sizeof(user)); + if (len >= sizeof(user)) + return (KORE_RESULT_ERROR); + + l = snprintf(fields, sizeof(fields), "user=%.*s", len, user); + if (l == -1 || (size_t)l >= sizeof(fields)) + return (KORE_RESULT_ERROR); + + if ((curl = curl_easy_init()) == NULL) + return (KORE_RESULT_ERROR); + + b = kore_buf_create(128); + + /* Do CURL magic. */ + curl_easy_setopt(curl, CURLOPT_POST, 1); + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, b); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, fields); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb); + curl_easy_setopt(curl, CURLOPT_URL, "https://127.0.0.1:4443/post_back"); + + res = curl_easy_perform(curl); + if (res != CURLE_OK) { + kore_buf_free(b); + curl_easy_cleanup(curl); + return (KORE_RESULT_ERROR); + } + + /* + * Grab the response from the CURL request and write the + * result back to the task channel. + */ + data = kore_buf_release(b, &len); + kore_task_channel_write(t, data, len); + kore_mem_free(data); + + return (KORE_RESULT_OK); +} + +size_t +curl_write_cb(char *ptr, size_t size, size_t nmemb, void *udata) +{ + struct kore_buf *b = udata; + + kore_buf_append(b, ptr, size * nmemb); + return (size * nmemb); +} diff --git a/contrib/examples/task_curl/module.conf b/contrib/examples/task_curl/module.conf @@ -0,0 +1,31 @@ +# Configuration for the contrib/modules/task_curl example. + +bind 127.0.0.1 4443 +chroot # configure this (ex: /home/joris/src/kore) +runas # configure this (ex: joris) + +workers 1 +pidfile kore.pid + +load ./task_curl.so + +ssl_no_compression + +validator v_user regex ^[a-z]*$ + +domain 127.0.0.1 { + certfile # configure this (ex: cert/server.crt) + certkey # configure this (ex: cert/server.key) + accesslog kore_access.log + + static / page_handler + static /post_back post_back + + params get / { + validate user v_user + } + + params post /post_back { + validate user v_user + } +} diff --git a/contrib/modules/example/build.sh b/contrib/modules/example/build.sh @@ -1,82 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2013 Joris Vink <joris@coders.se> -# -# Kore module build script, use this as a base for building -# your own modules for kore. - -# The name of the module you will be building -MODULE=example.module - -# The directory containing all your media files (HTML, CSS, ...). -# These files will be compiled into the module and symbols will -# be exported for you to use in your code. -MEDIA_DIR=media - -# The directory containing your module source. -SOURCE_DIR=src - -# The directory containing the Kore source code. -KORE_DIR=../../../ - -# Compiler settings. -CC=gcc -CFLAGS="-I. -I${KORE_DIR}/includes -Wall -Wstrict-prototypes \ - -Wmissing-prototypes -Wmissing-declarations -Wshadow \ - -Wpointer-arith -Wcast-qual -Wsign-compare -g" - -OSNAME=$(uname -s | sed -e 's/[-_].*//g' | tr A-Z a-z) -if [ "${OSNAME}" = "darwin" ]; then - LDFLAGS="-dynamiclib -undefined suppress -flat_namespace" -else - LDFLAGS="-shared" -fi - -MODULE_BUILD_DATE=$(date +"%Y-%m-%d %H:%M:%S") - -### Begin building #### -echo "Building module ${MODULE}..." -rm -f ${MODULE} - -${CC} ${CFLAGS} tools/inject.c -o tools/inject - -if [ ! -d ${SOURCE_DIR}/${MEDIA_DIR} ]; then - mkdir ${SOURCE_DIR}/${MEDIA_DIR}; -fi -rm -f ${SOURCE_DIR}/${MEDIA_DIR}/* - -if [ ! -d .objs ]; then - mkdir .objs; -fi -rm -f .objs/* - -rm -f static.h - -for file in `find ${MEDIA_DIR} -type f \( ! -name \*.swp \)`; do - echo "Injecting $file"; - base=`basename $file`; - ./tools/inject $file $base > ${SOURCE_DIR}/${MEDIA_DIR}/${base}.c; - if [ $? -ne 0 ]; then - echo "Injection error, check above messages for clues."; - exit 1; - fi -done - -echo "#define MODULE_BUILD_DATE \"${MODULE_BUILD_DATE}\"" >> static.h - -for src in `find ${SOURCE_DIR} -type f -name \*.c`; do - base=`basename $src`; - ${CC} ${CFLAGS} -fPIC -c $src -o .objs/${base}.o - if [ $? -ne 0 ]; then - echo "Build error, check above messages for clues."; - exit 1; - fi -done - -${CC} ${LDFLAGS} `find .objs -name \*.o -type f` -o ${MODULE} -echo "Building completed!" - -rm -rf ${SOURCE_DIR}/${MEDIA_DIR} -rm -rf .objs -rm -f tools/inject -rm -f static.h diff --git a/contrib/modules/example/media/index.html b/contrib/modules/example/media/index.html @@ -1,15 +0,0 @@ -<!DOCTYPE> -<html> -<head> - <link rel="stylesheet" href="/css/style.css" type="text/css"> - <title>Your KORE module worked!</title> -</head> - -<body> - -<div class="content"> - <p>Your first Kore module worked.</p> -</div> - -</body> -</html> diff --git a/contrib/modules/example/media/intro.jpg b/contrib/modules/example/media/intro.jpg Binary files differ. diff --git a/contrib/modules/example/media/params.html b/contrib/modules/example/media/params.html @@ -1,33 +0,0 @@ -<!DOCTYPE> -<html> -<head> - <link rel="stylesheet" href="/css/style.css" type="text/css"> - <title>Kore params test</title> -</head> - -<body style="overflow: auto"> - -<div class="content" style="font-size: 12px; font-weight: normal"> - <p>You can pass one GET parameter (arg1), any other GET parameter will - be filtered out</p> - <p>Only two out of the three input fields will be visible to Kore.</p> - <p>The first field accepts the input "test"</p> - <p>The second field accepts anything like /test/[a-z]*</p> - <p>The third field will be removed by Kore, as it is not in the params - block configured for this page.</p> - <form method="POST"> - <input type="input" name="test1" value="$test1$"> - <input type="input" name="test2" value="$test2$"> - <input type="input" name="test3" value="$test3$"> - <input type="submit"> - </form> - - <p style="font-size: 12px; font-weight: normal">GET param arg1: $arg1$</p> - <p style="font-size: 12px; font-weight: normal">GET param arg2: $arg2$</p> - <p style="font-size: 12px; font-weight: normal">test1: $test1$</p> - <p style="font-size: 12px; font-weight: normal">test2: $test2$</p> - <p style="font-size: 12px; font-weight: normal">test3: $test3$</p> -</div> - -</body> -</html> diff --git a/contrib/modules/example/media/private.html b/contrib/modules/example/media/private.html @@ -1,16 +0,0 @@ -<!DOCTYPE> -<html> -<head> - <link rel="stylesheet" href="/css/style.css" type="text/css"> - <title>Kore Authentication tests</title> -</head> - -<body> - -<div class="content"> - <p style="font-size: small">The cookie session_id should now be set.</p> - <p style="font-size: small">You can continue to <a href="/private/test">view page handler in auth block</a></p> -</div> - -</body> -</html> diff --git a/contrib/modules/example/media/private_test.html b/contrib/modules/example/media/private_test.html @@ -1,15 +0,0 @@ -<!DOCTYPE> -<html> -<head> - <link rel="stylesheet" href="/css/style.css" type="text/css"> - <title>Kore Authentication tests</title> -</head> - -<body> - -<div class="content"> - <p style="font-size: small">If you see this, the authentication worked. This page should redirect back to /private once you remove your session_id cookie.</p> -</div> - -</body> -</html> diff --git a/contrib/modules/example/media/style.css b/contrib/modules/example/media/style.css @@ -1,16 +0,0 @@ -body { - width: 100%; - margin: 0px; - color: #000; - overflow: hidden; - background-color: #fff; -} - -.content { - width: 800px; - margin-left: auto; - margin-right: auto; - margin-top: 100px; - font-size: 60px; - text-align: center; -} diff --git a/contrib/modules/example/media/upload.html b/contrib/modules/example/media/upload.html @@ -1,22 +0,0 @@ -<!DOCTYPE> -<html> -<head> - <link rel="stylesheet" href="/css/style.css" type="text/css"> - <title>Kore upload test</title> -</head> - -<body style="overflow: auto"> - -<div class="content"> - <form method="POST" enctype="multipart/form-data"> - <input type="input" name="firstname"> - <input type="file" name="file"> - <input type="submit" value="upload"> - </form> - - <p style="font-size: 12px; font-weight: normal">$upload$</p> - <p style="font-size: 12px; font-weight: normal">$firstname$</p> -</div> - -</body> -</html> diff --git a/contrib/modules/example/module.conf b/contrib/modules/example/module.conf @@ -1,193 +0,0 @@ -# Example Kore configuration - -# Server configuration. -bind 127.0.0.1 443 - -# The path worker processes will chroot into after starting. -chroot /home/joris/src/kore - -# Worker processes will run as the specified user. -runas joris - -# Set workers to the amount of CPU's available in your system, -# kore will automatically distribute all workers on them. -workers 4 - -# The number of active connections each worker can handle. -# You might have to tweak this number based on your hardware. -#worker_max_connections 250 - -# Store the main process its pid in this file. -#pidfile /var/run/kore.pid - -# You can define a callback Kore calls from its parent process or -# workers everytime the kore_cb_interval timer (in milliseconds) is reached. -# -# NOTE: Remember that the parent process runs as root and is not chroot(). -# NOTE: If you want the cb to run on a worker, be sure to set kore_cb_worker. -#kore_cb my_callback -#kore_cb_interval 1000 -#kore_cb_worker 3 - -# HTTP specific settings. -# http_header_max Maximum size of HTTP headers (in bytes). -# -# http_postbody_max Maximum size of an HTTP POST body (in bytes). -# -# http_keepalive_time Maximum seconds an HTTP connection can be -# kept alive by the browser. -# (Set to 0 to disable keepalive completely). -# -# http_hsts_enable Send Strict Transport Security header in -# all responses. Parameter is the age. -# (Set to 0 to disable sending this header). -#http_header_max 4096 -#http_postbody_max 10240000 -#http_keepalive_time 0 -#http_hsts_enable 31536000 - -# Load modules (you can load multiple at the same time). -# An additional parameter can be specified as the "onload" function -# which Kore will call when the module is loaded/reloaded. -load contrib/modules/example/example.module example_load - -# Validators -# validator name type regex|function -# -validator v_example function v_example_func -validator v_regex regex ^/test/[a-z]*$ -validator v_number regex ^[0-9]*$ -validator v_session function v_session_validate - -# Specify the SSL ciphers that will be used. -#ssl_cipher ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK - -# If you wish to use EDH / ECDH specify a file containing -# a generated DH key (See OpenSSL dhparam). -#ssl_dhparam dh2048.pem - -# Set this if you want to disable SSL zlib compression. -ssl_no_compression - -# Specify the amount of seconds a SPDY connection is kept open. -# You can keep it open indefinately by setting this to 0. -#spdy_idle_time 120 - -# Authentication configuration -# -# Using authentication blocks you can define a standard way for -# Kore to validate your users. In the example below we create -# a authentication block called auth_example, which requires -# a cookie (session_id) to be set. -# -# If no cookie is present or the cookie is not valid according -# to the set validator, Kore will redirect the browser to the -# URI set in authentication_uri. -# -# Page handlers can be bound to authentication by specifying -# authentication block at the end of the page directive (see below). -authentication auth_example { - # The authentication type denotes the way the user should - # be authenticated. - # - # Allow values: - # - cookie (checks for the cookie presence + pass to validator) - # - header (checks for header presence + pass to validator) - # - requuest (passes the http_request to the validator) - # - # Use cases for request could for example be IP based ACLs or - # any other criteria that can be extracted from a http_request. - # - # The request type does not need an authentication_validator. - # - authentication_type cookie - - # The name of whatever we are looking for. - authentication_value session_id - - # The validator that will be called to verify the cookie. - # Note this is YOUR validator, Kore does not have built-in - # session support. You must add this manually using your - # preferred method (Storing it in postgres, redis, ...) - authentication_validator v_session - - # The URI Kore will redirect to if a authentication fails. - # If this is not set, Kore will return a simple 403. - authentication_uri /private -} - -# Domain configuration -# -# Each domain configuration starts with listing what domain -# the directives that follow are to be applied upon. -# -# Additionally you can specify the following in a domain configuration: -# -# accesslog -# - File where all requests are logged. -# require_client_cert -# - Asks the client to present a certificate -# matching the CA given to require_client_cert -# -# Handlers -# -# Handlers are either static (for fixed paths) or dynamic. -# Dynamic handlers take a POSIX regular expression as its path. -# -# Syntax: -# handler path module_callback [auth block] -# -# Note that the auth block is optional and if set will force Kore to -# authenticate the user according to the authentication block its settings -# before allowing access to the page. - -# Example domain that responds to localhost. -domain localhost { - certfile cert/server.crt - certkey cert/server.key - accesslog /var/log/kore_access.log - - # Page handlers with no authentication required. - static /css/style.css serve_style_css - static / serve_index - static /intro.jpg serve_intro - static /b64test serve_b64test - static /spdy-reset serve_spdyreset - static /upload serve_file_upload - static /lock-test serve_lock_test - static /validator serve_validator - static /params-test serve_params_test - static /private serve_private - - # Page handlers with authentication. - static /private/test serve_private_test auth_example - - # Configure /params-test POST to only accept the following parameters. - # They are automatically tested against the validator listed. - # If the validator would fail Kore will automatically remove the - # failing parameter, indicating something was wrong with it. - # Any parameters not present in the params block are also filtered out. - params post /params-test { - validate test1 v_example - validate test2 v_regex - } - - # Configure a GET parameter that /params-test can received. As before - # this is validated against the validator and removed if validation - # fails. All extra parameters in the GET query are filtered out. - params get /params-test { - validate arg1 v_example - validate id v_number - } -} - -#domain domain.com { -# certfile cert/other/server.crt -# certkey cert/other/server.key -# accesslog /var/log/other_kore_access.log -# require_client_cert cert/other/ca.crt - -# static /css/style.css serve_style_css -# static / serve_index -# dynamic ^/[a-z0-9_]*$ serve_profile -#} diff --git a/contrib/modules/example/src/example.c b/contrib/modules/example/src/example.c @@ -1,361 +0,0 @@ -/* - * Copyright (c) 2013 Joris Vink <joris@coders.se> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "kore.h" -#include "http.h" - -#include "static.h" - -void example_load(int); - -int serve_style_css(struct http_request *); -int serve_index(struct http_request *); -int serve_intro(struct http_request *); -int serve_b64test(struct http_request *); -int serve_spdyreset(struct http_request *); -int serve_file_upload(struct http_request *); -int serve_lock_test(struct http_request *); -int serve_validator(struct http_request *); -int serve_params_test(struct http_request *); -int serve_private(struct http_request *); -int serve_private_test(struct http_request *); - -void my_callback(void); -int v_example_func(struct http_request *, char *); -int v_session_validate(struct http_request *, char *); -void test_base64(u_int8_t *, u_int32_t, struct kore_buf *); - -char *b64tests[] = { - "1234567890", - "One two three four five", - "Man", - "any carnal pleasure.", - "any carnal pleasure", - "any carnal pleas", - "I am a nobody, nobody is perfect, therefor I am.", - NULL -}; - -void -example_load(int state) -{ - switch (state) { - case KORE_MODULE_LOAD: - kore_log(LOG_NOTICE, "module loading"); - break; - case KORE_MODULE_UNLOAD: - kore_log(LOG_NOTICE, "module unloading"); - break; - default: - kore_log(LOG_NOTICE, "state %d unknown!", state); - break; - } -} - -int -serve_style_css(struct http_request *req) -{ - char *date; - time_t tstamp; - - tstamp = 0; - if (http_request_header_get(req, "if-modified-since", &date)) { - tstamp = kore_date_to_time(date); - kore_mem_free(date); - - kore_debug("header was present with %ld", tstamp); - } - - if (tstamp != 0 && tstamp <= static_mtime_css_style) { - http_response(req, 304, NULL, 0); - } else { - date = kore_time_to_date(static_mtime_css_style); - if (date != NULL) - http_response_header_add(req, "last-modified", date); - - http_response_header_add(req, "content-type", "text/css"); - http_response(req, 200, static_css_style, static_len_css_style); - } - - return (KORE_RESULT_OK); -} - -int -serve_index(struct http_request *req) -{ - http_response_header_add(req, "content-type", "text/html"); - http_response(req, 200, static_html_index, static_len_html_index); - - return (KORE_RESULT_OK); -} - -int -serve_intro(struct http_request *req) -{ - http_response_header_add(req, "content-type", "image/jpg"); - http_response(req, 200, static_jpg_intro, static_len_jpg_intro); - - return (KORE_RESULT_OK); -} - -int -serve_b64test(struct http_request *req) -{ - int i; - u_int32_t len; - struct kore_buf *res; - u_int8_t *data; - - res = kore_buf_create(1024); - for (i = 0; b64tests[i] != NULL; i++) - test_base64((u_int8_t *)b64tests[i], strlen(b64tests[i]), res); - - data = kore_buf_release(res, &len); - - http_response_header_add(req, "content-type", "text/plain"); - http_response(req, 200, data, len); - kore_mem_free(data); - - return (KORE_RESULT_OK); -} - -int -serve_spdyreset(struct http_request *req) -{ - spdy_session_teardown(req->owner, SPDY_SESSION_ERROR_OK); - return (KORE_RESULT_OK); -} - -int -serve_file_upload(struct http_request *req) -{ - int r; - u_int8_t *d; - struct kore_buf *b; - u_int32_t len; - char *name, buf[BUFSIZ]; - - b = kore_buf_create(static_len_html_upload); - kore_buf_append(b, static_html_upload, static_len_html_upload); - - if (req->method == HTTP_METHOD_POST) { - http_populate_multipart_form(req, &r); - if (http_argument_get_string("firstname", &name, &len)) { - kore_buf_replace_string(b, "$firstname$", name, len); - } else { - kore_buf_replace_string(b, "$firstname$", NULL, 0); - } - - if (http_file_lookup(req, "file", &name, &d, &len)) { - snprintf(buf, sizeof(buf), "%s is %d bytes", name, len); - kore_buf_replace_string(b, - "$upload$", buf, strlen(buf)); - } else { - kore_buf_replace_string(b, "$upload$", NULL, 0); - } - } else { - kore_buf_replace_string(b, "$upload$", NULL, 0); - kore_buf_replace_string(b, "$firstname$", NULL, 0); - } - - d = kore_buf_release(b, &len); - - http_response_header_add(req, "content-type", "text/html"); - http_response(req, 200, d, len); - kore_mem_free(d); - - return (KORE_RESULT_OK); -} - -int -serve_lock_test(struct http_request *req) -{ - kore_log(LOG_NOTICE, "lock-test called on worker %d", worker->id); - kore_worker_acceptlock_release(); - - http_response(req, 200, "OK", 2); - return (KORE_RESULT_OK); -} - -void -test_base64(u_int8_t *src, u_int32_t slen, struct kore_buf *res) -{ - char *in; - u_int32_t len; - u_int8_t *out; - - kore_buf_appendf(res, "test '%s'\n", src); - - if (!kore_base64_encode(src, slen, &in)) { - kore_buf_appendf(res, "encoding '%s' failed\n", src); - } else { - kore_buf_appendf(res, "encoded: '%s'\n", in); - - if (!kore_base64_decode(in, &out, &len)) { - kore_buf_appendf(res, "decoding failed\n"); - } else { - kore_buf_appendf(res, "decoded: "); - kore_buf_append(res, out, len); - kore_buf_appendf(res, "\n"); - kore_mem_free(out); - } - - kore_mem_free(in); - } - - kore_buf_appendf(res, "\n"); -} - -int -serve_validator(struct http_request *req) -{ - if (kore_validator_run(NULL, "v_example", "test")) - kore_log(LOG_NOTICE, "v_example ok (expected)"); - else - kore_log(LOG_NOTICE, "v_example failed"); - - if (kore_validator_run(NULL, "v_regex", "/test/123")) - kore_log(LOG_NOTICE, "regex #1 ok"); - else - kore_log(LOG_NOTICE, "regex #1 failed (expected)"); - - if (kore_validator_run(NULL, "v_regex", "/test/joris")) - kore_log(LOG_NOTICE, "regex #2 ok (expected)"); - else - kore_log(LOG_NOTICE, "regex #2 failed"); - - http_response(req, 200, "OK", 2); - - return (KORE_RESULT_OK); -} - -int -serve_params_test(struct http_request *req) -{ - struct kore_buf *b; - u_int8_t *d; - u_int32_t len; - int r, i; - char *test, name[10]; - - http_populate_arguments(req); - - b = kore_buf_create(static_len_html_params); - kore_buf_append(b, static_html_params, static_len_html_params); - - /* - * The GET parameters will be filtered out on POST. - */ - if (http_argument_get_string("arg1", &test, &len)) { - kore_buf_replace_string(b, "$arg1$", test, len); - } else { - kore_buf_replace_string(b, "$arg1$", NULL, 0); - } - - if (http_argument_get_string("arg2", &test, &len)) { - kore_buf_replace_string(b, "$arg2$", test, len); - } else { - kore_buf_replace_string(b, "$arg2$", NULL, 0); - } - - if (req->method == HTTP_METHOD_GET) { - kore_buf_replace_string(b, "$test1$", NULL, 0); - kore_buf_replace_string(b, "$test2$", NULL, 0); - kore_buf_replace_string(b, "$test3$", NULL, 0); - - if (http_argument_get_uint16("id", &r)) - kore_log(LOG_NOTICE, "id: %d", r); - else - kore_log(LOG_NOTICE, "No id set"); - - http_response_header_add(req, "content-type", "text/html"); - d = kore_buf_release(b, &len); - http_response(req, 200, d, len); - kore_mem_free(d); - - return (KORE_RESULT_OK); - } - - for (i = 1; i < 4; i++) { - snprintf(name, sizeof(name), "test%d", i); - if (http_argument_get_string(name, &test, &len)) { - snprintf(name, sizeof(name), "$test%d$", i); - kore_buf_replace_string(b, name, test, len); - } else { - snprintf(name, sizeof(name), "$test%d$", i); - kore_buf_replace_string(b, name, NULL, 0); - } - } - - http_response_header_add(req, "content-type", "text/html"); - d = kore_buf_release(b, &len); - http_response(req, 200, d, len); - kore_mem_free(d); - - return (KORE_RESULT_OK); -} - -int -serve_private(struct http_request *req) -{ - http_response_header_add(req, "content-type", "text/html"); - http_response_header_add(req, "set-cookie", "session_id=test123"); - http_response(req, 200, static_html_private, static_len_html_private); - - return (KORE_RESULT_OK); -} - -int -serve_private_test(struct http_request *req) -{ - http_response_header_add(req, "content-type", "text/html"); - - http_response(req, 200, static_html_private_test, - static_len_html_private_test); - - return (KORE_RESULT_OK); -} - -void -my_callback(void) -{ - if (worker != NULL) - kore_log(LOG_NOTICE, "running on worker %d", worker->id); - else - kore_log(LOG_NOTICE, "running from parent"); -} - -int -v_example_func(struct http_request *req, char *data) -{ - kore_log(LOG_NOTICE, "v_example_func called"); - - if (!strcmp(data, "test")) - return (KORE_RESULT_OK); - - return (KORE_RESULT_ERROR); -} - -int -v_session_validate(struct http_request *req, char *data) -{ - kore_log(LOG_NOTICE, "v_session_validate: %s", data); - - if (!strcmp(data, "test123")) - return (KORE_RESULT_OK); - - return (KORE_RESULT_ERROR); -} diff --git a/contrib/modules/example/tools/inject.c b/contrib/modules/example/tools/inject.c @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2013 Joris Vink <joris@coders.se> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/param.h> -#include <sys/stat.h> - -#include <ctype.h> -#include <err.h> -#include <errno.h> -#include <inttypes.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#if defined(OpenBSD) -#define PRI_TIME_T "d" -#endif - -#if defined(linux) -#if defined(__x86_64__) -#define PRI_TIME_T PRIu64 -#else -#define PRI_TIME_T "ld" -#endif -#endif - -#if defined(__MACH__) -#define PRI_TIME_T "ld" -#endif - -int -main(int argc, char *argv[]) -{ - struct stat st; - ssize_t len; - FILE *hdr; - char *ext; - unsigned char c[1]; - int fd, newline, count; - - if (argc != 3) - exit(1); - - if ((fd = open(argv[1], O_RDONLY)) == -1) - err(1, "open() %d", errno); - if ((hdr = fopen("static.h", "a+")) == NULL) - err(1, "fopen() %d", errno); - if ((ext = strchr(argv[2], '.')) != NULL) - *(ext)++ = '\0'; - else - ext = ""; - - if (stat(argv[1], &st) == -1) { - printf("stat(%s) failed: %d\n", argv[1], errno); - exit(1); - } - - printf("/**** AUTO GENERATED BY MAKEFILE - DO NOT TOUCH ****/\n"); - printf("#include <sys/param.h>\n\n"); - printf("u_int8_t static_%s_%s[] = {", ext, argv[2]); - - len = 0; - count = 0; - newline = 1; - for (;;) { - if (newline) { - printf("\n\t"); - count = 0; - newline = 0; - } - - len = read(fd, c, 1); - if (len == 0) - break; - - if (len == -1) { - printf("read(): %d\n", errno); - exit(1); - } - - if (len != 1) - exit(1); - - printf("0x%02x, ", c[0]); - if (count++ == 10) - newline = 1; - } - - close(fd); - - printf("};\n\n"); - printf("u_int32_t static_len_%s_%s = %" PRIu32 ";\n", - ext, argv[2], (u_int32_t)st.st_size); - - printf("time_t static_mtime_%s_%s = %" PRI_TIME_T ";\n", - ext, argv[2], st.st_mtime); - - fprintf(hdr, "extern u_int8_t static_%s_%s[];\n", ext, argv[2]); - fprintf(hdr, "extern u_int32_t static_len_%s_%s;\n", ext, argv[2]); - fprintf(hdr, "extern time_t static_mtime_%s_%s;\n", ext, argv[2]); - fclose(hdr); - - return (0); -} diff --git a/contrib/modules/pgsql_test/build.sh b/contrib/modules/pgsql_test/build.sh @@ -1,71 +0,0 @@ -#!/bin/sh -# -# Kore pgsql test module build directives. -# - -MODULE=pgsql_test.module -MEDIA_DIR=media -SOURCE_DIR=src -KORE_DIR=../../.. -PGDIR=$(pg_config --includedir) -CC=gcc -CFLAGS="-I. -I${KORE_DIR}/includes -I${PGDIR} \ - -Wall -Wstrict-prototypes -Wmissing-prototypes \ - -Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual \ - -Wsign-compare -g" - -OSNAME=$(uname -s | sed -e 's/[-_].*//g' | tr A-Z a-z) -if [ "${OSNAME}" = "darwin" ]; then - LDFLAGS="-dynamiclib -undefined suppress -flat_namespace" -else - LDFLAGS="-shared" -fi - -MODULE_BUILD_DATE=$(date +"%Y-%m-%d %H:%M:%S") - -### Begin building #### -echo "Building module ${MODULE}..." -rm -f ${MODULE} - -${CC} ${CFLAGS} tools/inject.c -o tools/inject - -if [ ! -d ${SOURCE_DIR}/${MEDIA_DIR} ]; then - mkdir ${SOURCE_DIR}/${MEDIA_DIR}; -fi -rm -f ${SOURCE_DIR}/${MEDIA_DIR}/* - -if [ ! -d .objs ]; then - mkdir .objs; -fi -rm -f .objs/* - -rm -f static.h - -for file in `find ${MEDIA_DIR} -type f \( ! -name \*.swp \)`; do - echo "Injecting $file"; - base=`basename $file`; - ./tools/inject $file $base > ${SOURCE_DIR}/${MEDIA_DIR}/${base}.c; - if [ $? -ne 0 ]; then - echo "Injection error, check above messages for clues."; - exit 1; - fi -done - -echo "#define MODULE_BUILD_DATE \"${MODULE_BUILD_DATE}\"" >> static.h - -for src in `find ${SOURCE_DIR} -type f -name \*.c`; do - base=`basename $src`; - ${CC} ${CFLAGS} -fPIC -c $src -o .objs/${base}.o - if [ $? -ne 0 ]; then - echo "Build error, check above messages for clues."; - exit 1; - fi -done - -${CC} ${LDFLAGS} `find .objs -name \*.o -type f` -o ${MODULE} -echo "Building completed!" - -rm -rf ${SOURCE_DIR}/${MEDIA_DIR} -rm -rf .objs -rm -f tools/inject -rm -f static.h diff --git a/contrib/modules/pgsql_test/module.conf b/contrib/modules/pgsql_test/module.conf @@ -1,20 +0,0 @@ -# Kore pgsql_test configuration -# see modules/examples/module.conf for a better overview -# of what a configuration file has to offer and what different -# settings mean and do. - -bind 127.0.0.1 8080 -chroot /home/joris/src/kore -runas joris -workers 4 -pidfile kore.pid -load contrib/modules/pgsql_test/pgsql_test.module pgsql_load -ssl_no_compression - -domain localhost { - certfile cert/server.crt - certkey cert/server.key - accesslog kore_pgsql.log - - static / serve_pgsql_test -} diff --git a/contrib/modules/pgsql_test/src/pgsql_test.c b/contrib/modules/pgsql_test/src/pgsql_test.c @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2014 Joris Vink <joris@coders.se> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "kore.h" -#include "http.h" -#include "kore_pgsql.h" - -#include "static.h" - -void pgsql_load(int); -int serve_pgsql_test(struct http_request *); - -void -pgsql_load(int state) -{ - switch (state) { - case KORE_MODULE_LOAD: - pgsql_conn_string = "Your connection string"; - break; - default: - break; - } -} - -int -serve_pgsql_test(struct http_request *req) -{ - int r, i; - char *col1, *col2; - - KORE_PGSQL(req, "SELECT * FROM test", 0, { - if (req->pgsql[0]->state == KORE_PGSQL_STATE_ERROR) { - kore_pgsql_logerror(req->pgsql[0]); - http_response(req, 500, "fail\n", 5); - return (KORE_RESULT_OK); - } - - r = kore_pgsql_ntuples(req->pgsql[0]); - for (i = 0; i < r; i++) { - col1 = kore_pgsql_getvalue(req->pgsql[0], i, 0); - col2 = kore_pgsql_getvalue(req->pgsql[0], i, 1); - - kore_log(LOG_NOTICE, "%s and %s", col1, col2); - } - }); - - KORE_PGSQL(req, "SELECT * FROM foobar", 1, { - if (req->pgsql[1]->state != KORE_PGSQL_STATE_ERROR) { - kore_log(LOG_NOTICE, "expected error, got %d", - req->pgsql[1]->state); - http_response(req, 500, "fail2\n", 6); - return (KORE_RESULT_OK); - } else { - kore_pgsql_logerror(req->pgsql[1]); - } - }); - - /* Query successfully completed */ - http_response(req, 200, "ok\n", 3); - - return (KORE_RESULT_OK); -} diff --git a/contrib/modules/pgsql_test/tools/inject.c b/contrib/modules/pgsql_test/tools/inject.c @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2013 Joris Vink <joris@coders.se> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/param.h> -#include <sys/stat.h> - -#include <ctype.h> -#include <err.h> -#include <errno.h> -#include <inttypes.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#if defined(OpenBSD) -#define PRI_TIME_T "d" -#endif - -#if defined(linux) -#if defined(__x86_64__) -#define PRI_TIME_T PRIu64 -#else -#define PRI_TIME_T "ld" -#endif -#endif - -#if defined(__MACH__) -#define PRI_TIME_T "ld" -#endif - -int -main(int argc, char *argv[]) -{ - struct stat st; - ssize_t len; - FILE *hdr; - char *ext; - unsigned char c[1]; - int fd, newline, count; - - if (argc != 3) - exit(1); - - if ((fd = open(argv[1], O_RDONLY)) == -1) - err(1, "open() %d", errno); - if ((hdr = fopen("static.h", "a+")) == NULL) - err(1, "fopen() %d", errno); - if ((ext = strchr(argv[2], '.')) != NULL) - *(ext)++ = '\0'; - else - ext = ""; - - if (stat(argv[1], &st) == -1) { - printf("stat(%s) failed: %d\n", argv[1], errno); - exit(1); - } - - printf("/**** AUTO GENERATED BY MAKEFILE - DO NOT TOUCH ****/\n"); - printf("#include <sys/param.h>\n\n"); - printf("u_int8_t static_%s_%s[] = {", ext, argv[2]); - - len = 0; - count = 0; - newline = 1; - for (;;) { - if (newline) { - printf("\n\t"); - count = 0; - newline = 0; - } - - len = read(fd, c, 1); - if (len == 0) - break; - - if (len == -1) { - printf("read(): %d\n", errno); - exit(1); - } - - if (len != 1) - exit(1); - - printf("0x%02x, ", c[0]); - if (count++ == 10) - newline = 1; - } - - close(fd); - - printf("};\n\n"); - printf("u_int32_t static_len_%s_%s = %" PRIu32 ";\n", - ext, argv[2], (u_int32_t)st.st_size); - - printf("time_t static_mtime_%s_%s = %" PRI_TIME_T ";\n", - ext, argv[2], st.st_mtime); - - fprintf(hdr, "extern u_int8_t static_%s_%s[];\n", ext, argv[2]); - fprintf(hdr, "extern u_int32_t static_len_%s_%s;\n", ext, argv[2]); - fprintf(hdr, "extern time_t static_mtime_%s_%s;\n", ext, argv[2]); - fclose(hdr); - - return (0); -} diff --git a/contrib/modules/skeleton/build.sh b/contrib/modules/skeleton/build.sh @@ -1,86 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2013 Joris Vink <joris@coders.se> -# -# Kore module build script, use this as a base for building -# your own modules for kore. - -# The name of the module you will be building -MODULE=site.module - -# The directory containing all your media files (HTML, CSS, ...). -# These files will be compiled into the module and symbols will -# be exported for you to use in your code. -MEDIA_DIR=media - -# The directory containing your module source. -SOURCE_DIR=src - -# The directory containing the Kore source code. -KORE_DIR="notset" -if [ ${KORE_DIR} = "notset" ]; then - echo "Please edit build.sh and set KORE_DIR properly"; - exit; -fi - -# Compiler settings. -CC=gcc -CFLAGS="-I. -I${KORE_DIR}/includes -Wall -Wstrict-prototypes \ - -Wmissing-prototypes -Wmissing-declarations -Wshadow \ - -Wpointer-arith -Wcast-qual -Wsign-compare -g" - -OSNAME=$(uname -s | sed -e 's/[-_].*//g' | tr A-Z a-z) -if [ "${OSNAME}" = "darwin" ]; then - LDFLAGS="-dynamiclib -undefined suppress -flat_namespace" -else - LDFLAGS="-shared" -fi - -MODULE_BUILD_DATE=$(date +"%Y-%m-%d %H:%M:%S") - -### Begin building #### -echo "Building module ${MODULE}..." -rm -f ${MODULE} - -${CC} ${CFLAGS} tools/inject.c -o tools/inject - -if [ ! -d ${SOURCE_DIR}/${MEDIA_DIR} ]; then - mkdir ${SOURCE_DIR}/${MEDIA_DIR}; -fi -rm -f ${SOURCE_DIR}/${MEDIA_DIR}/* - -if [ ! -d .objs ]; then - mkdir .objs; -fi -rm -f .objs/* - -rm -f static.h - -for file in `find ${MEDIA_DIR} -type f \( ! -name \*.swp \)`; do - echo "Injecting $file"; - base=`basename $file`; - ./tools/inject $file $base > ${SOURCE_DIR}/${MEDIA_DIR}/${base}.c; - if [ $? -ne 0 ]; then - echo "Injection error, check above messages for clues."; - exit 1; - fi -done - -echo "#define MODULE_BUILD_DATE \"${MODULE_BUILD_DATE}\"" >> static.h - -for src in `find ${SOURCE_DIR} -type f -name \*.c`; do - base=`basename $src`; - ${CC} ${CFLAGS} -fPIC -c $src -o .objs/${base}.o - if [ $? -ne 0 ]; then - echo "Build error, check above messages for clues."; - exit 1; - fi -done - -${CC} ${LDFLAGS} `find .objs -name \*.o -type f` -o ${MODULE} -echo "Building completed!" - -rm -rf ${SOURCE_DIR}/${MEDIA_DIR} -rm -rf .objs -rm -f tools/inject -rm -f static.h diff --git a/contrib/modules/skeleton/media/.gitignore b/contrib/modules/skeleton/media/.gitignore diff --git a/contrib/modules/skeleton/src/.gitignore b/contrib/modules/skeleton/src/.gitignore diff --git a/contrib/modules/skeleton/tools/inject.c b/contrib/modules/skeleton/tools/inject.c @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2013 Joris Vink <joris@coders.se> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/param.h> -#include <sys/stat.h> - -#include <ctype.h> -#include <err.h> -#include <errno.h> -#include <inttypes.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#if defined(OpenBSD) -#define PRI_TIME_T "d" -#endif - -#if defined(linux) -#if defined(__x86_64__) -#define PRI_TIME_T PRIu64 -#else -#define PRI_TIME_T "ld" -#endif -#endif - -#if defined(__MACH__) -#define PRI_TIME_T "ld" -#endif - -int -main(int argc, char *argv[]) -{ - struct stat st; - ssize_t len; - FILE *hdr; - char *ext; - unsigned char c[1]; - int fd, newline, count; - - if (argc != 3) - exit(1); - - if ((fd = open(argv[1], O_RDONLY)) == -1) - err(1, "open() %d", errno); - if ((hdr = fopen("static.h", "a+")) == NULL) - err(1, "fopen() %d", errno); - if ((ext = strchr(argv[2], '.')) != NULL) - *(ext)++ = '\0'; - else - ext = ""; - - if (stat(argv[1], &st) == -1) { - printf("stat(%s) failed: %d\n", argv[1], errno); - exit(1); - } - - printf("/**** AUTO GENERATED BY MAKEFILE - DO NOT TOUCH ****/\n"); - printf("#include <sys/param.h>\n\n"); - printf("u_int8_t static_%s_%s[] = {", ext, argv[2]); - - len = 0; - count = 0; - newline = 1; - for (;;) { - if (newline) { - printf("\n\t"); - count = 0; - newline = 0; - } - - len = read(fd, c, 1); - if (len == 0) - break; - - if (len == -1) { - printf("read(): %d\n", errno); - exit(1); - } - - if (len != 1) - exit(1); - - printf("0x%02x, ", c[0]); - if (count++ == 10) - newline = 1; - } - - close(fd); - - printf("};\n\n"); - printf("u_int32_t static_len_%s_%s = %" PRIu32 ";\n", - ext, argv[2], (u_int32_t)st.st_size); - - printf("time_t static_mtime_%s_%s = %" PRI_TIME_T ";\n", - ext, argv[2], st.st_mtime); - - fprintf(hdr, "extern u_int8_t static_%s_%s[];\n", ext, argv[2]); - fprintf(hdr, "extern u_int32_t static_len_%s_%s;\n", ext, argv[2]); - fprintf(hdr, "extern time_t static_mtime_%s_%s;\n", ext, argv[2]); - fclose(hdr); - - return (0); -} diff --git a/contrib/modules/task_curl/build.sh b/contrib/modules/task_curl/build.sh @@ -1,48 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2013 Joris Vink <joris@coders.se> -# -# Kore module build script, use this as a base for building -# your own modules for kore. - -# The name of the module you will be building -MODULE=task_curl.so - -# The directory containing your module source. -SOURCE_DIR=. - -# The directory containing the Kore source code. -KORE_DIR=../../../ - -# Compiler settings. -CC=gcc -CFLAGS="-I. -I${KORE_DIR}/includes -Wall -Wstrict-prototypes \ - -Wmissing-prototypes -Wmissing-declarations -Wshadow \ - -Wpointer-arith -Wcast-qual -Wsign-compare -g" - -LDFLAGS="-shared -lcurl" - -MODULE_BUILD_DATE=$(date +"%Y-%m-%d %H:%M:%S") - -### Begin building #### -echo "Building module ${MODULE}..." -rm -f ${MODULE} - -if [ ! -d .objs ]; then - mkdir .objs; -fi -rm -f .objs/* - -for src in `find ${SOURCE_DIR} -type f -name \*.c`; do - base=`basename $src`; - ${CC} ${CFLAGS} -fPIC -c $src -o .objs/${base}.o - if [ $? -ne 0 ]; then - echo "Build error, check above messages for clues."; - exit 1; - fi -done - -${CC} ${LDFLAGS} `find .objs -name \*.o -type f` -o ${MODULE} -echo "Building completed!" - -rm -rf .objs diff --git a/contrib/modules/task_curl/example.c b/contrib/modules/task_curl/example.c @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2014 Joris Vink <joris@coders.se> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * In this example, we use the background tasks available in Kore - * to fire off a POST to our /post_back page handler containing - * the user argument that was passed to us in our GET request to /. - * - * This illustrates how Kore its background tasks in effect work and - * how to operate on the channel in order to pass data back and forth. - * - * The page_handler() page handler is not called until the background - * task it fired off has completed. - * - * You need libcurl installed for this to build (including headers) - * - * Compile using build.sh, afterwards start using: - * # kore -nc module.conf (depending on where kore is installed) - * - * Test using: - * # curl -k https://127.0.0.1:4443/?user=foobar - * - * If the result echo'd back matches what you specified, its all green. - */ - -#include <curl/curl.h> - -#include "kore.h" -#include "http.h" -#include "kore_tasks.h" - -int run_curl(struct kore_task *); -int post_back(struct http_request *); -int page_handler(struct http_request *); -size_t curl_write_cb(char *, size_t, size_t, void *); - -int -page_handler(struct http_request *req) -{ - u_int32_t len; - char *user, result[64]; - - /* - * Lets check if a task has been created yet, this is important - * as we only want to fire this off once and we will be called - * again once it has been created. - */ - if (req->task == NULL) { - /* Grab the user argument */ - http_populate_arguments(req); - if (!http_argument_get_string("user", &user, &len)) { - http_response(req, 500, "ERROR\n", 6); - return (KORE_RESULT_OK); - } - - /* - * Create a new task that will execute the run_curl() - * function and bind it to our request. - * - * Binding a task to a request means Kore will reschedule - * the page handler for that request to refire after the - * task has completed. - */ - kore_task_create(&req->task, run_curl); - kore_task_bind_request(req->task, req); - - /* - * Start the task and write the user we received in our - * GET request to its channel. - */ - kore_task_run(req->task); - kore_task_channel_write(req->task, user, len); - - /* - * Tell Kore to retry us later. - */ - return (KORE_RESULT_RETRY); - } - - /* - * When we come back here, our background task is finished - * and we can check its result. - */ - if (req->task->result != KORE_RESULT_OK) { - kore_task_destroy(req->task); - http_response(req, 500, NULL, 0); - return (KORE_RESULT_OK); - } - - /* - * Lets read what our task has written to the channel. - * - * kore_task_channel_read() will return the amount of bytes - * that it received for that read. If the returned bytes is - * larger then the buffer you passed this is a sign of truncation - * and should be treated carefully. - */ - len = kore_task_channel_read(req->task, result, sizeof(result)); - if (len >= sizeof(result)) { - http_response(req, 500, NULL, 0); - } else { - http_response(req, 200, result, len); - } - - /* We good, destroy the task. */ - kore_task_destroy(req->task); - - return (KORE_RESULT_OK); -} - -int -post_back(struct http_request *req) -{ - u_int32_t len; - char *user; - - if (req->method != HTTP_METHOD_POST) { - http_response(req, 500, NULL, 0); - return (KORE_RESULT_OK); - } - - http_populate_arguments(req); - if (!http_argument_get_string("user", &user, &len)) { - http_response(req, 500, NULL, 0); - return (KORE_RESULT_OK); - } - - /* Simply echo the supplied user argument back. */ - http_response(req, 200, user, len); - - return (KORE_RESULT_OK); -} - -/* - * This is the function that is executed by our task which is created - * in the page_handler() callback. - * - * It sets up a CURL POST request to /post_back passing along the - * user argument which it receives from its channel from page_handler(). - */ -int -run_curl(struct kore_task *t) -{ - int l; - struct kore_buf *b; - u_int32_t len; - CURLcode res; - u_int8_t *data; - CURL *curl; - char user[64], fields[128]; - - /* - * Read the channel in order to obtain the user argument - * that was written to it by page_handler(). - */ - len = kore_task_channel_read(t, user, sizeof(user)); - if (len >= sizeof(user)) - return (KORE_RESULT_ERROR); - - l = snprintf(fields, sizeof(fields), "user=%.*s", len, user); - if (l == -1 || (size_t)l >= sizeof(fields)) - return (KORE_RESULT_ERROR); - - if ((curl = curl_easy_init()) == NULL) - return (KORE_RESULT_ERROR); - - b = kore_buf_create(128); - - /* Do CURL magic. */ - curl_easy_setopt(curl, CURLOPT_POST, 1); - curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, b); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, fields); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb); - curl_easy_setopt(curl, CURLOPT_URL, "https://127.0.0.1:4443/post_back"); - - res = curl_easy_perform(curl); - if (res != CURLE_OK) { - kore_buf_free(b); - curl_easy_cleanup(curl); - return (KORE_RESULT_ERROR); - } - - /* - * Grab the response from the CURL request and write the - * result back to the task channel. - */ - data = kore_buf_release(b, &len); - kore_task_channel_write(t, data, len); - kore_mem_free(data); - - return (KORE_RESULT_OK); -} - -size_t -curl_write_cb(char *ptr, size_t size, size_t nmemb, void *udata) -{ - struct kore_buf *b = udata; - - kore_buf_append(b, ptr, size * nmemb); - return (size * nmemb); -} diff --git a/contrib/modules/task_curl/module.conf b/contrib/modules/task_curl/module.conf @@ -1,31 +0,0 @@ -# Configuration for the contrib/modules/task_curl example. - -bind 127.0.0.1 4443 -chroot # configure this (ex: /home/joris/src/kore) -runas # configure this (ex: joris) - -workers 1 -pidfile kore.pid - -load ./task_curl.so - -ssl_no_compression - -validator v_user regex ^[a-z]*$ - -domain 127.0.0.1 { - certfile # configure this (ex: cert/server.crt) - certkey # configure this (ex: cert/server.key) - accesslog kore_access.log - - static / page_handler - static /post_back post_back - - params get / { - validate user v_user - } - - params post /post_back { - validate user v_user - } -}