1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

generic-sessions update

Generic sessions has been overdue some love to align it with
the progress in the rest of lws.

1) Strict Content Security Policy
2) http2 compatibility
3) fixes and additions for use in a separate process via unix domain socket
4) work on ws and http proxying in lws
5) add minimal example
This commit is contained in:
Andy Green 2019-04-05 21:13:59 +08:00
parent 7ca8b77f2c
commit f89aa401cc
51 changed files with 2208 additions and 395 deletions

View file

@ -88,6 +88,7 @@
#cmakedefine LWS_WITH_ESP32
#cmakedefine LWS_WITH_FTS
#cmakedefine LWS_WITH_GENCRYPTO
#cmakedefine LWS_WITH_GENERIC_SESSIONS
#cmakedefine LWS_WITH_HTTP2
#cmakedefine LWS_WITH_HTTP_BROTLI
#cmakedefine LWS_WITH_HTTP_PROXY

View file

@ -36,9 +36,9 @@
/* SHA-1 binary and hexified versions */
/** typedef struct lwsgw_hash_bin */
typedef struct { unsigned char bin[20]; /**< binary representation of hash */} lwsgw_hash_bin;
typedef struct { unsigned char bin[32]; /**< binary representation of hash */} lwsgw_hash_bin;
/** typedef struct lwsgw_hash */
typedef struct { char id[41]; /**< ascii hex representation of hash */ } lwsgw_hash;
typedef struct { char id[65]; /**< ascii hex representation of hash */ } lwsgw_hash;
/** enum lwsgs_auth_bits */
enum lwsgs_auth_bits {

View file

@ -116,7 +116,12 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i)
* we may want ws, but first we have to go through h1 to get that
*/
lws_role_call_client_bind(wsi, i);
if (lws_role_call_client_bind(wsi, i) < 0) {
lwsl_err("%s: unable to bind to role\n", __func__);
goto bail;
}
lwsl_info("%s: role binding to %s\n", __func__, wsi->role_ops->name);
/*
* PHASE 4: fill up the wsi with stuff from the connect_info as far as
@ -263,6 +268,15 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i)
if (i->pwsi)
*i->pwsi = wsi;
/* PHASE 8: notify protocol with role-specific connected callback */
lwsl_debug("%s: wsi %p: cb %d to %s %s\n", __func__,
wsi, wsi->role_ops->adoption_cb[0],
wsi->role_ops->name, wsi->protocol->name);
wsi->protocol->callback(wsi,
wsi->role_ops->adoption_cb[0],
wsi->user_space, NULL, 0);
#if defined(LWS_WITH_HUBBUB)
if (i->uri_replace_to)

View file

@ -117,6 +117,8 @@ lws_callback_ws_proxy(struct lws *wsi, enum lws_callback_reasons reason,
#endif
break;
case LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED:
return 1;
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
case LWS_CALLBACK_CLIENT_CLOSED:
@ -132,10 +134,22 @@ lws_callback_ws_proxy(struct lws *wsi, enum lws_callback_reasons reason,
proxy_header(wsi, wsi->parent, tmp, sizeof(tmp),
WSI_TOKEN_HTTP_ACCEPT_LANGUAGE, p, end);
proxy_header(wsi, wsi->parent, tmp, sizeof(tmp),
WSI_TOKEN_HTTP_COOKIE, p, end);
proxy_header(wsi, wsi->parent, tmp, sizeof(tmp),
WSI_TOKEN_HTTP_SET_COOKIE, p, end);
break;
}
case LWS_CALLBACK_CLIENT_RECEIVE:
wsi->parent->ws->proxy_buffered += len;
if (wsi->parent->ws->proxy_buffered > 10 * 1024 * 1024) {
lwsl_err("%s: proxied ws connection excessive buffering: dropping\n",
__func__);
return -1;
}
pkt = lws_malloc(sizeof(*pkt) + LWS_PRE + len, __func__);
if (!pkt)
return -1;
@ -164,6 +178,8 @@ lws_callback_ws_proxy(struct lws *wsi, enum lws_callback_reasons reason,
pkt->first, pkt->final)) < 0)
return -1;
wsi->parent->ws->proxy_buffered -= pkt->len;
lws_dll_remove_track_tail(dll, &wsi->ws->proxy_head);
lws_free(pkt);
@ -173,6 +189,9 @@ lws_callback_ws_proxy(struct lws *wsi, enum lws_callback_reasons reason,
/* h1 ws proxying... parent / server / incoming */
case LWS_CALLBACK_CONFIRM_EXTENSION_OKAY:
return 1;
case LWS_CALLBACK_CLOSED:
lwsl_user("%s: closed\n", __func__);
return -1;
@ -331,12 +350,15 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
wsi->reason_bf &= ~LWS_CB_REASON_AUX_BF__PROXY_HEADERS;
lwsl_debug("%s: %p: issuing proxy headers\n",
__func__, wsi);
n = LWS_WRITE_HTTP_HEADERS;
if (!wsi->http.prh_content_length)
n |= LWS_WRITE_H2_STREAM_END;
lwsl_debug("%s: %p: issuing proxy headers: clen %d\n",
__func__, wsi, (int)wsi->http.prh_content_length);
n = lws_write(wsi, wsi->http.pending_return_headers +
LWS_PRE,
wsi->http.pending_return_headers_len,
LWS_WRITE_HTTP_HEADERS);
wsi->http.pending_return_headers_len, n);
lws_free_set_NULL(wsi->http.pending_return_headers);
@ -468,17 +490,21 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
*/
proxy_header(parent, wsi, end, 256,
WSI_TOKEN_HTTP_CONTENT_LENGTH, &p, end);
WSI_TOKEN_HTTP_CONTENT_LENGTH, &p, end);
proxy_header(parent, wsi, end, 256,
WSI_TOKEN_HTTP_CONTENT_TYPE, &p, end);
WSI_TOKEN_HTTP_CONTENT_TYPE, &p, end);
proxy_header(parent, wsi, end, 256,
WSI_TOKEN_HTTP_ETAG, &p, end);
WSI_TOKEN_HTTP_ETAG, &p, end);
proxy_header(parent, wsi, end, 256,
WSI_TOKEN_HTTP_ACCEPT_LANGUAGE, &p, end);
WSI_TOKEN_HTTP_ACCEPT_LANGUAGE, &p, end);
proxy_header(parent, wsi, end, 256,
WSI_TOKEN_HTTP_CONTENT_ENCODING, &p, end);
WSI_TOKEN_HTTP_CONTENT_ENCODING, &p, end);
proxy_header(parent, wsi, end, 256,
WSI_TOKEN_HTTP_CACHE_CONTROL, &p, end);
WSI_TOKEN_HTTP_CACHE_CONTROL, &p, end);
proxy_header(parent, wsi, end, 256,
WSI_TOKEN_HTTP_SET_COOKIE, &p, end);
proxy_header(parent, wsi, end, 256,
WSI_TOKEN_HTTP_LOCATION, &p, end);
if (!parent->http2_substream)
if (lws_add_http_header_by_token(parent,
@ -508,8 +534,13 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
if (lws_finalize_http_header(parent, &p, end))
return 1;
parent->http.pending_return_headers_len =
lws_ptr_diff(p, start);
parent->http.prh_content_length = -1;
if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH))
parent->http.prh_content_length = atoll(
lws_hdr_simple_ptr(wsi,
WSI_TOKEN_HTTP_CONTENT_LENGTH));
parent->http.pending_return_headers_len = lws_ptr_diff(p, start);
parent->http.pending_return_headers =
lws_malloc(parent->http.pending_return_headers_len +
LWS_PRE, "return proxy headers");
@ -522,7 +553,9 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
parent->reason_bf |= LWS_CB_REASON_AUX_BF__PROXY_HEADERS;
lwsl_debug("%s: LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: "
"prepared headers\n", __func__);
"prepared %d headers (len %d)\n", __func__,
lws_http_client_http_response(wsi),
(int)parent->http.prh_content_length);
/*
* so at this point, the onward client connection can bear
@ -565,8 +598,6 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
* connection's request
*/
proxy_header(wsi, parent, (unsigned char *)buf, sizeof(buf),
WSI_TOKEN_HOST, p, end);
proxy_header(wsi, parent, (unsigned char *)buf, sizeof(buf),
WSI_TOKEN_HTTP_ETAG, p, end);
proxy_header(wsi, parent, (unsigned char *)buf, sizeof(buf),
@ -577,6 +608,8 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
WSI_TOKEN_HTTP_ACCEPT_ENCODING, p, end);
proxy_header(wsi, parent, (unsigned char *)buf, sizeof(buf),
WSI_TOKEN_HTTP_CACHE_CONTROL, p, end);
proxy_header(wsi, parent, (unsigned char *)buf, sizeof(buf),
WSI_TOKEN_HTTP_COOKIE, p, end);
buf[0] = '\0';
lws_get_peer_simple(parent, buf, sizeof(buf));

View file

@ -89,6 +89,16 @@ lws_create_context(const struct lws_context_creation_info *info)
lwsl_err("No memory for websocket context\n");
return NULL;
}
context->uid = info->uid;
context->gid = info->gid;
context->username = info->username;
context->groupname = info->groupname;
/* if he gave us names, set the uid / gid */
if (lws_plat_drop_app_privileges(context, 0))
goto bail;
lwsl_info("context created\n");
#if defined(LWS_WITH_TLS) && defined(LWS_WITH_NETWORK)
#if defined(LWS_WITH_MBEDTLS)
@ -424,15 +434,6 @@ lwsl_info("context created\n");
lws_server_get_canonical_hostname(context, info);
#endif
context->uid = info->uid;
context->gid = info->gid;
context->username = info->username;
context->groupname = info->groupname;
/* if he gave us names, set the uid / gid */
if (lws_plat_drop_app_privileges(context, 0))
goto bail;
#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
memcpy(context->caps, info->caps, sizeof(context->caps));
context->count_caps = info->count_caps;

View file

@ -947,7 +947,7 @@ lws_libuv_closehandle(struct lws *wsi)
return;
if (wsi->told_event_loop_closed) {
assert(0);
// assert(0);
return;
}

View file

@ -257,6 +257,9 @@ lws_struct_sq3_open(struct lws_context *context, const char *sqlite3_path,
chown(sqlite3_path, uid, gid);
chmod(sqlite3_path, 0600);
lwsl_notice("%s: created %s owned by %u:%u mode 0600\n", __func__,
sqlite3_path, (unsigned int)uid, (unsigned int)gid);
sqlite3_extended_result_codes(*pdb, 1);
return 0;

View file

@ -116,7 +116,7 @@ lws_read_h1(struct lws *wsi, unsigned char *buf, lws_filepos_t len)
case LRS_BODY:
http_postbody:
lwsl_notice("%s: http post body: remain %d\n", __func__,
lwsl_debug("%s: http post body: remain %d\n", __func__,
(int)wsi->http.rx_content_remain);
if (!wsi->http.rx_content_remain)
@ -659,28 +659,36 @@ rops_handle_POLLOUT_h1(struct lws *wsi)
if (lwsi_state(wsi) == LRS_ISSUE_HTTP_BODY) {
#if defined(LWS_WITH_HTTP_PROXY)
if (wsi->http.proxy_clientside) {
unsigned char *buf;
unsigned char *buf, prebuf[LWS_PRE + 1024];
size_t len = lws_buflist_next_segment_len(
&wsi->parent->http.buflist_post_body, &buf);
int n;
lwsl_debug("%s: %p: proxying body %d %d %d %d %d\n",
__func__, wsi, (int)len,
(int)wsi->http.tx_content_length,
(int)wsi->http.tx_content_remain,
(int)wsi->http.rx_content_length,
(int)wsi->http.rx_content_remain
);
if (len) {
n = lws_write(wsi, buf, len, LWS_WRITE_HTTP);
if (n < 0) {
lwsl_err("%s: PROXY_BODY: write failed\n",
__func__);
return -1;
if (len > sizeof(prebuf) - LWS_PRE)
len = sizeof(prebuf) - LWS_PRE;
memcpy(prebuf + LWS_PRE, buf, len);
lwsl_debug("%s: %p: proxying body %d %d %d %d %d\n",
__func__, wsi, (int)len,
(int)wsi->http.tx_content_length,
(int)wsi->http.tx_content_remain,
(int)wsi->http.rx_content_length,
(int)wsi->http.rx_content_remain
);
n = lws_write(wsi, prebuf + LWS_PRE, len, LWS_WRITE_HTTP);
if (n < 0) {
lwsl_err("%s: PROXY_BODY: write %d failed\n",
__func__, (int)len);
return LWS_HP_RET_BAIL_DIE;
}
lws_buflist_use_segment(&wsi->parent->http.buflist_post_body, len);
}
lws_buflist_use_segment(&wsi->parent->http.buflist_post_body, len);
if (wsi->parent->http.buflist_post_body)
lws_callback_on_writable(wsi);
else {

View file

@ -212,6 +212,7 @@ struct _lws_http_mode_related {
unsigned char *pending_return_headers;
size_t pending_return_headers_len;
size_t prh_content_length;
#if defined(LWS_WITH_HTTP_PROXY)
struct lws_rewrite *rw;

View file

@ -672,6 +672,7 @@ lws_http_serve(struct lws *wsi, char *uri, const char *origin,
lwsl_debug("sending no mimetype for %s\n", path);
wsi->sending_chunked = 0;
wsi->interpreting = 0;
/*
* check if this is in the list of file suffixes to be interpreted by
@ -684,13 +685,20 @@ lws_http_serve(struct lws *wsi, char *uri, const char *origin,
wsi->interpreting = 1;
if (!wsi->http2_substream)
wsi->sending_chunked = 1;
wsi->protocol_interpret_idx =
(char)(lws_intptr_t)pvo->value;
lwsl_info("want %s interpreted by %s\n", path,
lws_vhost_name_to_protocol(wsi->vhost,
pvo->value) -
&lws_get_vhost(wsi)->protocols[0];
lwsl_debug("want %s interpreted by %s (pcol is %s)\n", path,
wsi->vhost->protocols[
(int)(lws_intptr_t)(pvo->value)].name);
wsi->protocol = &wsi->vhost->protocols[
(int)(lws_intptr_t)(pvo->value)];
(int)wsi->protocol_interpret_idx].name,
wsi->protocol->name);
if (lws_bind_protocol(wsi, &wsi->vhost->protocols[
(int)wsi->protocol_interpret_idx], __func__))
return -1;
if (lws_ensure_user_space(wsi))
return -1;
break;
@ -698,6 +706,14 @@ lws_http_serve(struct lws *wsi, char *uri, const char *origin,
pvo = pvo->next;
}
if (wsi->sending_chunked) {
if (lws_add_http_header_by_token(wsi,
WSI_TOKEN_HTTP_TRANSFER_ENCODING,
(unsigned char *)"chunked", 7,
&p, end))
return -1;
}
if (m->protocol) {
const struct lws_protocols *pp = lws_vhost_name_to_protocol(
wsi->vhost, m->protocol);
@ -1091,11 +1107,29 @@ lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit,
}
i.path = rpath;
/* incoming may be h1 or h2... if he sends h1 HOST, use that
* directly, otherwise we must convert h2 :authority to h1
* host */
i.host = NULL;
n = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_AUTHORITY);
if (n > 0)
i.host = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_AUTHORITY);
else {
n = lws_hdr_total_length(wsi, WSI_TOKEN_HOST);
if (n > 0) {
i.host = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST);
}
}
#if 0
if (i.address[0] != '+' ||
!lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST))
i.host = i.address;
else
i.host = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST);
#endif
i.origin = NULL;
if (!ws) {
if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_POST_URI)
@ -1111,7 +1145,12 @@ lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit,
i.method = "GET";
}
lws_snprintf(host, sizeof(host), "%s:%d", i.address, i.port);
if (i.host)
lws_snprintf(host, sizeof(host), "%s:%u", i.host,
wsi->vhost->listen_port);
else
lws_snprintf(host, sizeof(host), "%s:%d", i.address, i.port);
i.host = host;
i.alpn = "http/1.1";
@ -1423,7 +1462,7 @@ lws_http_action(struct lws *wsi)
if (hit->origin_protocol == LWSMPRO_HTTPS ||
hit->origin_protocol == LWSMPRO_HTTP) {
n = lws_http_proxy_start(wsi, hit, uri_ptr, 0);
lwsl_notice("proxy start says %d\n", n);
// lwsl_notice("proxy start says %d\n", n);
if (n)
return n;
@ -1454,6 +1493,9 @@ lws_http_action(struct lws *wsi)
if (lws_bind_protocol(wsi, pp, "http action CALLBACK bind"))
return 1;
lwsl_notice("%s: %s, checking access rights for mask 0x%x\n",
__func__, hit->origin, hit->auth_mask);
args.p = uri_ptr;
args.len = uri_len;
args.max_len = hit->auth_mask;
@ -1569,7 +1611,7 @@ deal_body:
*/
if (lwsi_state(wsi) != LRS_ISSUING_FILE) {
/* Prepare to read body if we have a content length: */
lwsl_notice("wsi->http.rx_content_length %lld %d %d\n",
lwsl_debug("wsi->http.rx_content_length %lld %d %d\n",
(long long)wsi->http.rx_content_length,
wsi->upgraded_to_http2, wsi->http2_substream);
@ -2297,9 +2339,10 @@ lws_serve_http_file(struct lws *wsi, const char *file, const char *content_type,
* method that the client said he will accept
*/
if (!strncmp(content_type, "text/", 5) ||
!strcmp(content_type, "application/javascript") ||
!strcmp(content_type, "image/svg+xml"))
if (!wsi->interpreting && (
!strncmp(content_type, "text/", 5) ||
!strcmp(content_type, "application/javascript") ||
!strcmp(content_type, "image/svg+xml")))
lws_http_compression_apply(wsi, NULL, &p, end, 0);
}
#endif
@ -2827,7 +2870,7 @@ skip:
s->swallow[s->pos] = '\0';
if (n != s->pos) {
memmove(s->start + n, s->start + s->pos,
old_len - (sp - args->p));
old_len - (sp - args->p) - 1);
old_len += (n - s->pos) + 1;
}
memcpy(s->start, pc, n);

View file

@ -358,9 +358,8 @@ lws_extension_callback_pm_deflate(struct lws_context *context,
__func__, pmdrx->eb_out.len, priv->rx.avail_in,
(unsigned long)priv->count_rx_between_fin);
if (was_fin) {
if (was_fin && !pen) {
lwsl_ext("%s: was_fin\n", __func__);
assert(!pen);
priv->count_rx_between_fin = 0;
if (priv->args[PMD_SERVER_NO_CONTEXT_TAKEOVER]) {
lwsl_ext("PMD_SERVER_NO_CONTEXT_TAKEOVER\n");

View file

@ -96,6 +96,7 @@ struct _lws_websocket_related {
#if defined(LWS_WITH_HTTP_PROXY)
struct lws_dll proxy_head;
char actual_protocol[16];
size_t proxy_buffered;
#endif
/* Also used for close content... control opcode == < 128 */

View file

@ -0,0 +1,82 @@
cmake_minimum_required(VERSION 2.8)
include(CheckCSourceCompiles)
set(SAMP lws-minimal-http-server-generic-sessions)
set(SRCS minimal-http-server-generic-sessions.c)
# If we are being built as part of lws, confirm current build config supports
# reqconfig, else skip building ourselves.
#
# If we are being built externally, confirm installed lws was configured to
# support reqconfig, else error out with a helpful message about the problem.
#
MACRO(require_lws_config reqconfig _val result)
if (DEFINED ${reqconfig})
if (${reqconfig})
set (rq 1)
else()
set (rq 0)
endif()
else()
set(rq 0)
endif()
if (${_val} EQUAL ${rq})
set(SAME 1)
else()
set(SAME 0)
endif()
if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME})
if (${_val})
message("${SAMP}: skipping as lws being built without ${reqconfig}")
else()
message("${SAMP}: skipping as lws built with ${reqconfig}")
endif()
set(${result} 0)
else()
if (LWS_WITH_MINIMAL_EXAMPLES)
set(MET ${SAME})
else()
CHECK_C_SOURCE_COMPILES("#include <libwebsockets.h>\nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig})
if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig})
set(HAS_${reqconfig} 0)
else()
set(HAS_${reqconfig} 1)
endif()
if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val}))
set(MET 1)
else()
set(MET 0)
endif()
endif()
if (NOT MET)
if (${_val})
message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}")
else()
message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project")
endif()
endif()
endif()
ENDMACRO()
set(requirements 1)
require_lws_config(LWS_ROLE_H1 1 requirements)
require_lws_config(LWS_WITHOUT_SERVER 0 requirements)
require_lws_config(LWS_OPENSSL_SUPPORT 1 requirements)
require_lws_config(LWS_WITH_GENERIC_SESSIONS 1 requirements)
require_lws_config(LWS_WITH_LIBUV 1 requirements)
require_lws_config(LWS_WITH_PLUGINS 1 requirements)
if (requirements)
add_executable(${SAMP} ${SRCS})
if (websockets_shared)
target_link_libraries(${SAMP} websockets_shared)
add_dependencies(${SAMP} websockets_shared)
else()
target_link_libraries(${SAMP} websockets)
endif()
endif()

View file

@ -0,0 +1,26 @@
# lws minimal http server with generic-sessions
## build
```
$ cmake . && make
```
## usage
```
$ ./lws-minimal-http-server-tls
[2018/03/20 13:23:13:0131] USER: LWS minimal http server TLS | visit https://localhost:7681
[2018/03/20 13:23:13:0142] NOTICE: Creating Vhost 'default' port 7681, 1 protocols, IPv6 off
[2018/03/20 13:23:13:0142] NOTICE: Using SSL mode
[2018/03/20 13:23:13:0146] NOTICE: SSL ECDH curve 'prime256v1'
[2018/03/20 13:23:13:0146] NOTICE: HTTP2 / ALPN enabled
[2018/03/20 13:23:13:0195] NOTICE: lws_tls_client_create_vhost_context: doing cert filepath localhost-100y.cert
[2018/03/20 13:23:13:0195] NOTICE: Loaded client cert localhost-100y.cert
[2018/03/20 13:23:13:0195] NOTICE: lws_tls_client_create_vhost_context: doing private key filepath
[2018/03/20 13:23:13:0196] NOTICE: Loaded client cert private key localhost-100y.key
[2018/03/20 13:23:13:0196] NOTICE: created client ssl context for default
[2018/03/20 13:23:14:0207] NOTICE: vhost default: cert expiry: 730459d
```

View file

@ -0,0 +1,34 @@
-----BEGIN CERTIFICATE-----
MIIF5jCCA86gAwIBAgIJANq50IuwPFKgMA0GCSqGSIb3DQEBCwUAMIGGMQswCQYD
VQQGEwJHQjEQMA4GA1UECAwHRXJld2hvbjETMBEGA1UEBwwKQWxsIGFyb3VuZDEb
MBkGA1UECgwSbGlid2Vic29ja2V0cy10ZXN0MRIwEAYDVQQDDAlsb2NhbGhvc3Qx
HzAdBgkqhkiG9w0BCQEWEG5vbmVAaW52YWxpZC5vcmcwIBcNMTgwMzIwMDQxNjA3
WhgPMjExODAyMjQwNDE2MDdaMIGGMQswCQYDVQQGEwJHQjEQMA4GA1UECAwHRXJl
d2hvbjETMBEGA1UEBwwKQWxsIGFyb3VuZDEbMBkGA1UECgwSbGlid2Vic29ja2V0
cy10ZXN0MRIwEAYDVQQDDAlsb2NhbGhvc3QxHzAdBgkqhkiG9w0BCQEWEG5vbmVA
aW52YWxpZC5vcmcwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCjYtuW
aICCY0tJPubxpIgIL+WWmz/fmK8IQr11Wtee6/IUyUlo5I602mq1qcLhT/kmpoR8
Di3DAmHKnSWdPWtn1BtXLErLlUiHgZDrZWInmEBjKM1DZf+CvNGZ+EzPgBv5nTek
LWcfI5ZZtoGuIP1Dl/IkNDw8zFz4cpiMe/BFGemyxdHhLrKHSm8Eo+nT734tItnH
KT/m6DSU0xlZ13d6ehLRm7/+Nx47M3XMTRH5qKP/7TTE2s0U6+M0tsGI2zpRi+m6
jzhNyMBTJ1u58qAe3ZW5/+YAiuZYAB6n5bhUp4oFuB5wYbcBywVR8ujInpF8buWQ
Ujy5N8pSNp7szdYsnLJpvAd0sibrNPjC0FQCNrpNjgJmIK3+mKk4kXX7ZTwefoAz
TK4l2pHNuC53QVc/EF++GBLAxmvCDq9ZpMIYi7OmzkkAKKC9Ue6Ef217LFQCFIBK
Izv9cgi9fwPMLhrKleoVRNsecBsCP569WgJXhUnwf2lon4fEZr3+vRuc9shfqnV0
nPN1IMSnzXCast7I2fiuRXdIz96KjlGQpP4XfNVA+RGL7aMnWOFIaVrKWLzAtgzo
GMTvP/AuehKXncBJhYtW0ltTioVx+5yTYSAZWl+IssmXjefxJqYi2/7QWmv1QC9p
sNcjTMaBQLN03T1Qelbs7Y27sxdEnNUth4kI+wIDAQABo1MwUTAdBgNVHQ4EFgQU
9mYU23tW2zsomkKTAXarjr2vjuswHwYDVR0jBBgwFoAU9mYU23tW2zsomkKTAXar
jr2vjuswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEANjIBMrow
YNCbhAJdP7dhlhT2RUFRdeRUJD0IxrH/hkvb6myHHnK8nOYezFPjUlmRKUgNEDuA
xbnXZzPdCRNV9V2mShbXvCyiDY7WCQE2Bn44z26O0uWVk+7DNNLH9BnkwUtOnM9P
wtmD9phWexm4q2GnTsiL6Ul6cy0QlTJWKVLEUQQ6yda582e23J1AXqtqFcpfoE34
H3afEiGy882b+ZBiwkeV+oq6XVF8sFyr9zYrv9CvWTYlkpTQfLTZSsgPdEHYVcjv
xQ2D+XyDR0aRLRlvxUa9dHGFHLICG34Juq5Ai6lM1EsoD8HSsJpMcmrH7MWw2cKk
ujC3rMdFTtte83wF1uuF4FjUC72+SmcQN7A386BC/nk2TTsJawTDzqwOu/VdZv2g
1WpTHlumlClZeP+G/jkSyDwqNnTu1aodDmUa4xZodfhP1HWPwUKFcq8oQr148QYA
AOlbUOJQU7QwRWd1VbnwhDtQWXC92A2w1n/xkZSR1BM/NUSDhkBSUU1WjMbWg6Gg
mnIZLRerQCu1Oozr87rOQqQakPkyt8BUSNK3K42j2qcfhAONdRl8Hq8Qs5pupy+s
8sdCGDlwR3JNCMv6u48OK87F4mcIxhkSefFJUFII25pCGN5WtE4p5l+9cnO1GrIX
e2Hl/7M0c/lbZ4FvXgARlex2rkgS0Ka06HE=
-----END CERTIFICATE-----

View file

@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCjYtuWaICCY0tJ
PubxpIgIL+WWmz/fmK8IQr11Wtee6/IUyUlo5I602mq1qcLhT/kmpoR8Di3DAmHK
nSWdPWtn1BtXLErLlUiHgZDrZWInmEBjKM1DZf+CvNGZ+EzPgBv5nTekLWcfI5ZZ
toGuIP1Dl/IkNDw8zFz4cpiMe/BFGemyxdHhLrKHSm8Eo+nT734tItnHKT/m6DSU
0xlZ13d6ehLRm7/+Nx47M3XMTRH5qKP/7TTE2s0U6+M0tsGI2zpRi+m6jzhNyMBT
J1u58qAe3ZW5/+YAiuZYAB6n5bhUp4oFuB5wYbcBywVR8ujInpF8buWQUjy5N8pS
Np7szdYsnLJpvAd0sibrNPjC0FQCNrpNjgJmIK3+mKk4kXX7ZTwefoAzTK4l2pHN
uC53QVc/EF++GBLAxmvCDq9ZpMIYi7OmzkkAKKC9Ue6Ef217LFQCFIBKIzv9cgi9
fwPMLhrKleoVRNsecBsCP569WgJXhUnwf2lon4fEZr3+vRuc9shfqnV0nPN1IMSn
zXCast7I2fiuRXdIz96KjlGQpP4XfNVA+RGL7aMnWOFIaVrKWLzAtgzoGMTvP/Au
ehKXncBJhYtW0ltTioVx+5yTYSAZWl+IssmXjefxJqYi2/7QWmv1QC9psNcjTMaB
QLN03T1Qelbs7Y27sxdEnNUth4kI+wIDAQABAoICAFWe8MQZb37k2gdAV3Y6aq8f
qokKQqbCNLd3giGFwYkezHXoJfg6Di7oZxNcKyw35LFEghkgtQqErQqo35VPIoH+
vXUpWOjnCmM4muFA9/cX6mYMc8TmJsg0ewLdBCOZVw+wPABlaqz+0UOiSMMftpk9
fz9JwGd8ERyBsT+tk3Qi6D0vPZVsC1KqxxL/cwIFd3Hf2ZBtJXe0KBn1pktWht5A
Kqx9mld2Ovl7NjgiC1Fx9r+fZw/iOabFFwQA4dr+R8mEMK/7bd4VXfQ1o/QGGbMT
G+ulFrsiDyP+rBIAaGC0i7gDjLAIBQeDhP409ZhswIEc/GBtODU372a2CQK/u4Q/
HBQvuBtKFNkGUooLgCCbFxzgNUGc83GB/6IwbEM7R5uXqsFiE71LpmroDyjKTlQ8
YZkpIcLNVLw0usoGYHFm2rvCyEVlfsE3Ub8cFyTFk50SeOcF2QL2xzKmmbZEpXgl
xBHR0hjgon0IKJDGfor4bHO7Nt+1Ece8u2oTEKvpz5aIn44OeC5mApRGy83/0bvs
esnWjDE/bGpoT8qFuy+0urDEPNId44XcJm1IRIlG56ErxC3l0s11wrIpTmXXckqw
zFR9s2z7f0zjeyxqZg4NTPI7wkM3M8BXlvp2GTBIeoxrWB4V3YArwu8QF80QBgVz
mgHl24nTg00UH1OjZsABAoIBAQDOxftSDbSqGytcWqPYP3SZHAWDA0O4ACEM+eCw
au9ASutl0IDlNDMJ8nC2ph25BMe5hHDWp2cGQJog7pZ/3qQogQho2gUniKDifN77
40QdykllTzTVROqmP8+efreIvqlzHmuqaGfGs5oTkZaWj5su+B+bT+9rIwZcwfs5
YRINhQRx17qa++xh5mfE25c+M9fiIBTiNSo4lTxWMBShnK8xrGaMEmN7W0qTMbFH
PgQz5FcxRjCCqwHilwNBeLDTp/ZECEB7y34khVh531mBE2mNzSVIQcGZP1I/DvXj
W7UUNdgFwii/GW+6M0uUDy23UVQpbFzcV8o1C2nZc4Fb4zwBAoIBAQDKSJkFwwuR
naVJS6WxOKjX8MCu9/cKPnwBv2mmI2jgGxHTw5sr3ahmF5eTb8Zo19BowytN+tr6
2ZFoIBA9Ubc9esEAU8l3fggdfM82cuR9sGcfQVoCh8tMg6BP8IBLOmbSUhN3PG2m
39I802u0fFNVQCJKhx1m1MFFLOu7lVcDS9JN+oYVPb6MDfBLm5jOiPuYkFZ4gH79
J7gXI0/YKhaJ7yXthYVkdrSF6Eooer4RZgma62Dd1VNzSq3JBo6rYjF7Lvd+RwDC
R1thHrmf/IXplxpNVkoMVxtzbrrbgnC25QmvRYc0rlS/kvM4yQhMH3eA7IycDZMp
Y+0xm7I7jTT7AoIBAGKzKIMDXdCxBWKhNYJ8z7hiItNl1IZZMW2TPUiY0rl6yaCh
BVXjM9W0r07QPnHZsUiByqb743adkbTUjmxdJzjaVtxN7ZXwZvOVrY7I7fPWYnCE
fXCr4+IVpZI/ZHZWpGX6CGSgT6EOjCZ5IUufIvEpqVSmtF8MqfXO9o9uIYLokrWQ
x1dBl5UnuTLDqw8bChq7O5y6yfuWaOWvL7nxI8NvSsfj4y635gIa/0dFeBYZEfHI
UlGdNVomwXwYEzgE/c19ruIowX7HU/NgxMWTMZhpazlxgesXybel+YNcfDQ4e3RM
OMz3ZFiaMaJsGGNf4++d9TmMgk4Ns6oDs6Tb9AECggEBAJYzd+SOYo26iBu3nw3L
65uEeh6xou8pXH0Tu4gQrPQTRZZ/nT3iNgOwqu1gRuxcq7TOjt41UdqIKO8vN7/A
aJavCpaKoIMowy/aGCbvAvjNPpU3unU8jdl/t08EXs79S5IKPcgAx87sTTi7KDN5
SYt4tr2uPEe53NTXuSatilG5QCyExIELOuzWAMKzg7CAiIlNS9foWeLyVkBgCQ6S
me/L8ta+mUDy37K6vC34jh9vK9yrwF6X44ItRoOJafCaVfGI+175q/eWcqTX4q+I
G4tKls4sL4mgOJLq+ra50aYMxbcuommctPMXU6CrrYyQpPTHMNVDQy2ttFdsq9iK
TncCggEBAMmt/8yvPflS+xv3kg/ZBvR9JB1In2n3rUCYYD47ReKFqJ03Vmq5C9nY
56s9w7OUO8perBXlJYmKZQhO4293lvxZD2Iq4NcZbVSCMoHAUzhzY3brdgtSIxa2
gGveGAezZ38qKIU26dkz7deECY4vrsRkwhpTW0LGVCpjcQoaKvymAoCmAs8V2oMr
Ziw1YQ9uOUoWwOqm1wZqmVcOXvPIS2gWAs3fQlWjH9hkcQTMsUaXQDOD0aqkSY3E
NqOvbCV1/oUpRi3076khCoAXI1bKSn/AvR3KDP14B5toHI/F5OTSEiGhhHesgRrs
fBrpEY1IATtPq1taBZZogRqI3rOkkPk=
-----END PRIVATE KEY-----

View file

@ -0,0 +1,202 @@
/*
* lws-minimal-http-server-generic-sessions
*
* Copyright (C) 2019 Andy Green <andy@warmcat.com>
*
* This file is made available under the Creative Commons CC0 1.0
* Universal Public Domain Dedication.
*
* This demonstrates setting up and using generic sessions
*/
#include <libwebsockets.h>
#include <string.h>
#include <signal.h>
static int interrupted;
struct lws_context *context;
static const struct lws_protocol_vhost_options
pvo_mm1 = {
NULL, NULL, "message-db", (void *)"/var/www/sessions/messageboard.sqlite3"
}, pvo_m1 = {
NULL, &pvo_mm1, "protocol-lws-messageboard", ""
},
pvo13 = {
NULL, NULL, "email-confirm-url-base", (void *)"https://localhost:7681/"
}, pvo12 = {
&pvo13, NULL, "urlroot", (void *)"https://127.0.0.1:7681/"
}, pvo11 = {
&pvo12, NULL, "email-contact-person", (void *)"andy@warmcat.com"
}, pvo10 = {
&pvo11, NULL, "email-helo", (void *)"warmcat.com"
}, pvo9 = {
&pvo10, NULL, "email-expire", (void *)"3600"
}, pvo8 = {
&pvo9, NULL, "email-smtp-ip", (void *)"127.0.0.1"
}, pvo7 = {
&pvo8, NULL, "email-from", (void *)"noreply@warmcat.com"
}, pvo6 = {
&pvo7, NULL, "confounder", (void *)"some kind of secret confounder"
}, pvo5 = {
&pvo6, NULL, "timeout-anon-idle-secs", (void *)"1200"
}, pvo4 = {
&pvo5, NULL, "timeout-idle-secs", (void *)"6000"
}, pvo3 = {
&pvo4, NULL, "session-db", (void *)"/var/www/sessions/lws.sqlite3"
}, pvo2 = {
&pvo3, NULL, "admin-password-sha256",
(void *)"25d08521d996bad92605f5a40fe71179dc968e70f669cb1db6190dcd53258200" /* pvo value */
}, pvo1 = {
&pvo2, NULL, "admin-user", (void *)"admin"
}, pvo = {
&pvo_m1, &pvo1, "protocol-generic-sessions", ""
},
interpret1 = {
NULL, NULL, ".js", "protocol-lws-messageboard"
},
pvo_hsbph[] = {{
NULL, NULL, "referrer-policy:", "no-referrer"
}, {
&pvo_hsbph[0], NULL, "x-xss-protection:", "1; mode=block"
}, {
&pvo_hsbph[1], NULL, "x-content-type-options:", "nosniff"
}, {
&pvo_hsbph[2], NULL, "content-security-policy:",
"default-src 'self'; "
"img-src https://www.gravatar.com 'self' data: ; "
"script-src 'self'; "
"font-src 'self'; "
"style-src 'self'; "
"connect-src 'self'; "
"frame-ancestors 'self'; "
"base-uri 'none'; "
"form-action 'self';"
}};
static const struct lws_http_mount mount2 = {
/* .mount_next */ NULL, /* linked-list "next" */
/* .mountpoint */ "/needadmin", /* mountpoint URL */
/* .origin */ "./mount-origin/needadmin", /* serve from dir */
/* .def */ "index.html", /* default filename */
/* .protocol */ "protocol-lws-messageboard",
/* .cgienv */ NULL,
/* .extra_mimetypes */ NULL,
/* .interpret */ &interpret1,
/* .cgi_timeout */ 0,
/* .cache_max_age */ 0,
/* .auth_mask */ 7,
/* .cache_reusable */ 0,
/* .cache_revalidate */ 0,
/* .cache_intermediaries */ 0,
/* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */
/* .mountpoint_len */ 1, /* char count */
/* .basic_auth_login_file */ NULL,
};
static const struct lws_http_mount mount1 = {
/* .mount_next */ &mount2, /* linked-list "next" */
/* .mountpoint */ "/needauth", /* mountpoint URL */
/* .origin */ "./mount-origin/needauth", /* serve from dir */
/* .def */ "index.html", /* default filename */
/* .protocol */ "protocol-lws-messageboard",
/* .cgienv */ NULL,
/* .extra_mimetypes */ NULL,
/* .interpret */ &interpret1,
/* .cgi_timeout */ 0,
/* .cache_max_age */ 0,
/* .auth_mask */ 5,
/* .cache_reusable */ 0,
/* .cache_revalidate */ 0,
/* .cache_intermediaries */ 0,
/* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */
/* .mountpoint_len */ 1, /* char count */
/* .basic_auth_login_file */ NULL,
};
static const struct lws_http_mount mount = {
/* .mount_next */ &mount1, /* linked-list "next" */
/* .mountpoint */ "/", /* mountpoint URL */
/* .origin */ "./mount-origin", /* serve from dir */
/* .def */ "index.html", /* default filename */
/* .protocol */ "protocol-lws-messageboard",
/* .cgienv */ NULL,
/* .extra_mimetypes */ NULL,
/* .interpret */ &interpret1,
/* .cgi_timeout */ 0,
/* .cache_max_age */ 0,
/* .auth_mask */ 0,
/* .cache_reusable */ 0,
/* .cache_revalidate */ 0,
/* .cache_intermediaries */ 0,
/* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */
/* .mountpoint_len */ 1, /* char count */
/* .basic_auth_login_file */ NULL,
};
void sigint_handler(int sig)
{
lws_context_destroy(context);
interrupted = 1;
}
int main(int argc, const char **argv)
{
struct lws_context_creation_info info;
const char *p, *plugin_dirs[] = {
"/usr/local/share/libwebsockets-test-server/plugins",
NULL };
int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE
/* for LLL_ verbosity above NOTICE to be built into lws,
* lws must have been configured and built with
* -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */
/* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */
/* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */
/* | LLL_DEBUG */;
if ((p = lws_cmdline_option(argc, argv, "-d")))
logs = atoi(p);
lws_set_log_level(logs, NULL);
lwsl_user("LWS minimal http server TLS | visit https://localhost:7681\n");
signal(SIGINT, sigint_handler);
memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
info.port = 7681;
info.mounts = &mount;
info.error_document_404 = "/404.html";
info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT |
LWS_SERVER_OPTION_EXPLICIT_VHOSTS;
info.ssl_cert_filepath = "localhost-100y.cert";
info.ssl_private_key_filepath = "localhost-100y.key";
info.plugin_dirs = plugin_dirs;
info.pvo = &pvo;
if (lws_cmdline_option(argc, argv, "-h"))
info.options |= LWS_SERVER_OPTION_VHOST_UPG_STRICT_HOST_CHECK;
context = lws_create_context(&info);
if (!context) {
lwsl_err("lws init failed\n");
return 1;
}
info.headers = &pvo_hsbph[3];
if (!lws_create_vhost(context, &info)) {
lwsl_err("lws init failed\n");
return 1;
}
while (n >= 0 && !interrupted)
n = lws_service(context, 1000);
lws_context_destroy(context);
return 0;
}

View file

@ -0,0 +1,11 @@
<meta charset="UTF-8">
<html>
<body>
<img src="libwebsockets.org-logo.svg">
<img src="strict-csp.svg"><br>
<h1>404</h1>
Sorry, that file doesn't exist.
</body>
</html>

View file

@ -0,0 +1,5 @@
<html>
This is an example destination that will appear after successful Admin login.
This URL cannot be served if you're not logged in as admin.
</html>

View file

@ -0,0 +1,22 @@
document.addEventListener("DOMContentLoaded", function() {
var transport_protocol = "";
if ( performance && performance.timing.nextHopProtocol ) {
transport_protocol = performance.timing.nextHopProtocol;
} else if ( window.chrome && window.chrome.loadTimes ) {
transport_protocol = window.chrome.loadTimes().connectionInfo;
} else {
var p = performance.getEntriesByType("resource");
for (var i=0; i < p.length; i++) {
var value = "nextHopProtocol" in p[i];
if (value)
transport_protocol = p[i].nextHopProtocol;
}
}
if (transport_protocol == "h2")
document.getElementById("transport").innerHTML = "<img src=\"/http2.png\">";
}
}, false);

View file

@ -0,0 +1,3 @@
<html>
This is an example destination that will appear after a failed login
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

View file

@ -0,0 +1,57 @@
<html>
<head>
<meta charset="UTF-8">
<script src="/lws-common.js"></script>
<link rel="stylesheet" type="text/css" href="lwsgs.css"/>
<script src="lwsgs.js"></script>
</head>
<body class="seats">
<table class="lwsgs">
<tr>
<td class="logo">
<img src="lwsgs.svg">
</td>
<td class="">
<div id=lwsgs class="lwsgs"></div>
</td>
<td class="rlogo">
<img src="strict-csp.svg">
</td>
</tr>
<tr><td colspan="3" class="h99">
<table class="c100"><tr>
<td class="c">
<span id="nolog" class="group2">
This is a demo application for lws generic-sessions.<br><br>
It's a simple messageboard.<br><br>
What's interesting about it is there is <b>no serverside scripting</b>,<br>
instead client js makes a wss:// connection back to the server<br>
and then reacts to JSON from the ws protocol. Sessions stuff is <br>
handled by lws generic sessions, making the <a href="https://libwebsockets.org/git/libwebsockets/tree/plugins/generic-sessions/protocol_generic_sessions.c">actual<br>
test application</a> <a href="https://libwebsockets.org/git/libwebsockets/tree/plugins/generic-sessions/protocol_lws_messageboard.c">very small</a>.<br><br>
And because it's natively websocket, it's naturally connected<br>
for dynamic events and easy to maintain.
<br><br>
Register / Login at the top right to see and create new messages.
</span>
<span id="logged" class="group2">
<div id="newmsg">
<form action="/msg" method="post" target="hidden">
New message<br>
<textarea id="msg" placeholder="type your message here" cols="40" rows="5" name="msg"></textarea><br>
<input type="submit" id="send" name="send" disabled=1>
</form>
</div>
</span>
<div id="dmessages">
<span id="messages" ></span>
</div>
<span id="debug" class="group2"></span>
</td></tr></table>
</td></tr>
</table>
<iframe name="hidden" class="hidden"></iframe>
</body>
</html>

View file

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="127.63mm" height="27.837mm" version="1.1" viewBox="0 0 127.63446 27.837189" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="a" x="-.011681" y="-.053882" width="1.0234" height="1.1078" color-interpolation-filters="sRGB">
<feGaussianBlur stdDeviation="0.10687168"/>
</filter>
</defs>
<g transform="translate(452.86 42.871)">
<rect x="-452.86" y="-42.871" width="127.63" height="27.837" fill="none"/>
<g transform="matrix(4.0081 0 0 4.0081 -211.01 -224.26)" fill="#fff" filter="url(#a)" stroke="#fff">
<g style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal" aria-label="libwebsockets.org">
<path d="m-52.015 48.429q0 0.12497 0.03213 0.17852 0.0357 0.05356 0.0964 0.05356 0.07498 0 0.17495-0.03927l0.02499 0.20709q-0.04642 0.02856-0.13211 0.04642-0.08212 0.01785-0.14996 0.01785-0.13568 0-0.22137-0.08212-0.08212-0.08569-0.08212-0.29635v-2.1601h0.25707z"/>
<path d="m-51.417 47.068h0.25707v1.7852h-0.25707zm-0.04642-0.54271q0-0.08569 0.04642-0.13925 0.04999-0.05356 0.12854-0.05356 0.07855 0 0.12854 0.05356 0.05356 0.04999 0.05356 0.13925 0 0.08569-0.05356 0.13568-0.04999 0.04642-0.12854 0.04642-0.07855 0-0.12854-0.04999-0.04642-0.04999-0.04642-0.13211z"/>
<path d="m-50.686 46.354h0.25707v0.84976h0.01071q0.14639-0.17852 0.38918-0.17852 0.27492 0 0.4106 0.2178 0.13925 0.2178 0.13925 0.6891 0 0.48201-0.18566 0.71766-0.18209 0.23565-0.51771 0.23565-0.16424 0-0.29992-0.03571-0.13568-0.03927-0.20352-0.08926zm0.25707 2.2387q0.04999 0.02856 0.1214 0.04641 0.07498 0.01428 0.1571 0.01428 0.18566 0 0.29278-0.17495 0.11068-0.17852 0.11068-0.54628 0-0.15353-0.02142-0.27492-0.01785-0.12496-0.0607-0.21423-0.03927-0.08926-0.10711-0.13568-0.06427-0.04999-0.1571-0.04999-0.12854 0-0.21423 0.07855-0.08212 0.07498-0.1214 0.20708z"/>
<path d="m-48.092 47.068 0.24993 0.91403 0.04284 0.29635h0.01428l0.0357-0.29992 0.16781-0.91046h0.38561l-0.43916 1.8031h-0.33562l-0.26778-0.99615-0.02856-0.22851h-0.02142l-0.02499 0.23565-0.25707 0.98901h-0.34633l-0.45702-1.8031h0.46059l0.1928 0.89618 0.03213 0.31777h0.01428l0.04642-0.32134 0.2178-0.89261z"/>
<path d="m-45.889 48.721q-0.08926 0.07855-0.24279 0.12854-0.15353 0.04999-0.32134 0.04999-0.18566 0-0.32134-0.06427-0.13211-0.06427-0.2178-0.18566-0.08569-0.1214-0.12854-0.29278-0.03927-0.17495-0.03927-0.39632 0-0.48201 0.18923-0.71052 0.1928-0.23208 0.532-0.23208 0.11425 0 0.22137 0.0357 0.10711 0.03213 0.18923 0.11425 0.08569 0.07855 0.13568 0.21423 0.05356 0.13211 0.05356 0.33562 0 0.07855-0.01071 0.16781-0.0071 0.08926-0.02499 0.1928h-0.86762q0.0071 0.22137 0.09283 0.33919 0.08569 0.11782 0.27492 0.11782 0.11425 0 0.20709-0.0357 0.0964-0.0357 0.14639-0.07498zm-0.55699-1.3389q-0.13568 0-0.20352 0.11068-0.06784 0.10711-0.07855 0.30349h0.49272q0.01071-0.20352-0.04284-0.30706-0.05356-0.10711-0.16781-0.10711z"/>
<path d="m-45.569 46.354h0.42488v0.82834h0.01071q0.12854-0.1571 0.36776-0.1571 0.2535 0 0.39275 0.21066 0.14282 0.21066 0.14282 0.67838 0 0.507-0.19994 0.74622-0.19994 0.23565-0.54628 0.23565-0.18923 0-0.3499-0.0357-0.1571-0.03571-0.24279-0.07855zm0.42488 2.1137q0.07498 0.03927 0.19638 0.03927 0.13568 0 0.20708-0.12854 0.07141-0.13211 0.07141-0.43916 0-0.27135-0.05713-0.39632-0.05713-0.12854-0.17852-0.12854-0.17852 0-0.23922 0.18566z"/>
<path d="m-43.386 48.379q0-0.07498-0.04999-0.12496-0.04642-0.05356-0.1214-0.0964-0.07498-0.04642-0.16067-0.09283-0.08212-0.04641-0.1571-0.11425-0.07498-0.06784-0.12496-0.16424-0.04642-0.0964-0.04642-0.24279 0-0.24993 0.13568-0.38561 0.13568-0.13568 0.39989-0.13568 0.1571 0 0.29635 0.0357 0.13925 0.03213 0.22137 0.08212l-0.09997 0.32848q-0.06784-0.02856-0.16424-0.05356-0.0964-0.02856-0.18923-0.02856-0.17495 0-0.17495 0.14639 0 0.06784 0.04642 0.11425 0.04999 0.04284 0.12496 0.08569 0.07498 0.04284 0.1571 0.08926 0.08569 0.04642 0.16067 0.11782 0.07498 0.06784 0.1214 0.16781 0.04999 0.09997 0.04999 0.24636 0 0.24636-0.14996 0.39632-0.14996 0.14996-0.4463 0.14996-0.14639 0-0.2892-0.0357-0.13925-0.0357-0.22494-0.09283l0.11782-0.34276q0.07498 0.04285 0.17138 0.07498 0.09997 0.03213 0.20709 0.03213 0.08212 0 0.13568-0.0357 0.05356-0.03928 0.05356-0.1214z"/>
<path d="m-42.802 47.961q0-0.47487 0.18566-0.70695 0.18566-0.23208 0.51771-0.23208 0.35704 0 0.532 0.23565 0.17495 0.23565 0.17495 0.70338 0 0.47844-0.18566 0.71052-0.18566 0.22851-0.52128 0.22851-0.70338 0-0.70338-0.93902zm0.43916 0q0 0.26778 0.0607 0.41417t0.20352 0.14639q0.13568 0 0.19994-0.12497 0.06784-0.12854 0.06784-0.43559 0-0.27492-0.0607-0.41774-0.0607-0.14282-0.20708-0.14282-0.12497 0-0.19638 0.12854-0.06784 0.12497-0.06784 0.43202z"/>
<path d="m-40.094 48.757q-0.08926 0.07141-0.21423 0.10711-0.12496 0.0357-0.24993 0.0357-0.18209 0-0.30706-0.06427-0.1214-0.06784-0.19994-0.18923-0.07855-0.12496-0.11425-0.29635-0.03213-0.17495-0.03213-0.38918 0-0.46773 0.16781-0.70338 0.16781-0.23565 0.49272-0.23565 0.16067 0 0.26064 0.02856 0.10354 0.02856 0.18209 0.07141l-0.09997 0.35347q-0.06427-0.03213-0.12497-0.04642-0.05713-0.01785-0.13925-0.01785-0.14996 0-0.22494 0.13211-0.07498 0.12854-0.07498 0.41774 0 0.24279 0.07498 0.39632 0.07855 0.15353 0.24636 0.15353 0.08926 0 0.14996-0.02142 0.06427-0.02499 0.11782-0.0607z"/>
<path d="m-39.374 48.114h-0.09997v0.73908h-0.42488v-2.4993h0.42488v1.4746l0.08569-0.04999 0.29635-0.71052h0.46059l-0.32848 0.70695-0.15353 0.1214 0.16781 0.1214 0.36418 0.83548h-0.47844z"/>
<path d="m-37.256 48.721q-0.08926 0.07855-0.24279 0.12854-0.15353 0.04999-0.32134 0.04999-0.18566 0-0.32134-0.06427-0.13211-0.06427-0.2178-0.18566-0.08569-0.1214-0.12854-0.29278-0.03927-0.17495-0.03927-0.39632 0-0.48201 0.18923-0.71052 0.1928-0.23208 0.532-0.23208 0.11425 0 0.22137 0.0357 0.10711 0.03213 0.18923 0.11425 0.08569 0.07855 0.13568 0.21423 0.05356 0.13211 0.05356 0.33562 0 0.07855-0.01071 0.16781-0.0071 0.08926-0.02499 0.1928h-0.86763q0.0071 0.22137 0.09283 0.33919 0.08569 0.11782 0.27492 0.11782 0.11425 0 0.20708-0.0357 0.0964-0.0357 0.14639-0.07498zm-0.55699-1.3389q-0.13568 0-0.20352 0.11068-0.06784 0.10711-0.07855 0.30349h0.49272q0.01071-0.20352-0.04284-0.30706-0.05356-0.10711-0.16781-0.10711z"/>
<path d="m-37.075 47.068h0.19637v-0.33562l0.42488-0.13211v0.46773h0.34633v0.37847h-0.34633v0.77836q0 0.15353 0.02856 0.2178 0.03213 0.06427 0.11068 0.06427 0.05356 0 0.0964-0.01071t0.09283-0.03213l0.05356 0.33919q-0.07855 0.03928-0.18209 0.06427-0.10354 0.02856-0.2178 0.02856-0.20352 0-0.30706-0.11782-0.09997-0.11782-0.09997-0.39632v-0.93546h-0.19637z"/>
<path d="m-35.297 48.379q0-0.07498-0.04999-0.12496-0.04641-0.05356-0.1214-0.0964-0.07498-0.04642-0.16067-0.09283-0.08212-0.04641-0.1571-0.11425-0.07498-0.06784-0.12496-0.16424-0.04642-0.0964-0.04642-0.24279 0-0.24993 0.13568-0.38561 0.13568-0.13568 0.39989-0.13568 0.1571 0 0.29635 0.0357 0.13925 0.03213 0.22137 0.08212l-0.09997 0.32848q-0.06784-0.02856-0.16424-0.05356-0.0964-0.02856-0.18923-0.02856-0.17495 0-0.17495 0.14639 0 0.06784 0.04642 0.11425 0.04999 0.04284 0.12497 0.08569 0.07498 0.04284 0.1571 0.08926 0.08569 0.04642 0.16067 0.11782 0.07498 0.06784 0.1214 0.16781 0.04999 0.09997 0.04999 0.24636 0 0.24636-0.14996 0.39632-0.14996 0.14996-0.4463 0.14996-0.14639 0-0.2892-0.0357-0.13925-0.0357-0.22494-0.09283l0.11782-0.34276q0.07498 0.04285 0.17138 0.07498 0.09997 0.03213 0.20708 0.03213 0.08212 0 0.13568-0.0357 0.05356-0.03928 0.05356-0.1214z"/>
<path d="m-34.662 48.693q0-0.09997 0.04642-0.14996 0.04999-0.04999 0.13211-0.04999 0.08212 0 0.12854 0.04999 0.04999 0.04999 0.04999 0.14996 0 0.10354-0.04999 0.15353-0.04642 0.04999-0.12854 0.04999-0.08212 0-0.13211-0.04999-0.04642-0.04999-0.04642-0.15353z"/>
<path d="m-34.035 47.961q0-0.48201 0.16424-0.70695 0.16781-0.22851 0.47487-0.22851 0.32848 0 0.48201 0.23208 0.1571 0.23208 0.1571 0.70338 0 0.48558-0.16781 0.71052-0.16781 0.22494-0.4713 0.22494-0.32848 0-0.48558-0.23208-0.15353-0.23208-0.15353-0.70338zm0.26778 0q0 0.1571 0.01785 0.28564 0.02142 0.12854 0.06427 0.22137 0.04642 0.09283 0.11782 0.14639 0.07141 0.04999 0.17138 0.04999 0.18566 0 0.2785-0.16424 0.09283-0.16781 0.09283-0.53914 0-0.15353-0.02142-0.28206-0.01785-0.13211-0.06427-0.22494-0.04285-0.09283-0.11425-0.14282-0.07141-0.05356-0.17138-0.05356-0.18209 0-0.27849 0.16781-0.09283 0.16781-0.09283 0.53557z"/>
<path d="m-32.415 47.068h0.18209l0.04642 0.18923h0.01071q0.04999-0.10354 0.12854-0.16067 0.08212-0.0607 0.19637-0.0607 0.08212 0 0.18566 0.03213l-0.04999 0.26064q-0.09283-0.03213-0.16424-0.03213-0.11426 0-0.18566 0.06784-0.07141 0.06427-0.09283 0.17495v1.3139h-0.25707z"/>
<path d="m-30.314 48.936q0 0.34633-0.15353 0.51057-0.15353 0.16424-0.4463 0.16424-0.17852 0-0.29278-0.03213-0.11425-0.02856-0.18566-0.06784l0.07498-0.22137q0.07141 0.03213 0.1571 0.0607 0.08569 0.02856 0.21066 0.02856 0.2178 0 0.29635-0.1214 0.08212-0.1214 0.08212-0.40703v-0.13211h-0.01071q-0.05713 0.08212-0.14639 0.12854-0.08926 0.04641-0.22851 0.04641-0.28921 0-0.42488-0.22137-0.13568-0.22494-0.13568-0.70338 0-0.46059 0.17495-0.69624 0.17852-0.23565 0.52486-0.23565 0.16781 0 0.2892 0.03213t0.21423 0.07498zm-0.25707-1.6103q-0.10711-0.05713-0.27492-0.05713-0.18209 0-0.29278 0.16781-0.11068 0.16424-0.11068 0.52842 0 0.14996 0.01785 0.27849 0.01785 0.12497 0.0607 0.22137 0.04285 0.09283 0.10711 0.14639 0.06784 0.04999 0.16424 0.04999 0.13568 0 0.21423-0.07141t0.11425-0.21423z"/>
</g>
<g style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal" aria-label="lightweight, portable C library">
<path d="m-49.147 50.56q0 0.05637 0.01449 0.08052 0.0161 0.02416 0.04348 0.02416 0.03382 0 0.07891-0.01772l0.01127 0.09341q-0.02094 0.01288-0.05959 0.02094-0.03704 0.0081-0.06764 0.0081-0.0612 0-0.09985-0.03704-0.03704-0.03865-0.03704-0.13367v-0.97434h0.11595z"/>
<path d="m-48.878 49.946h0.11596v0.80524h-0.11596zm-0.02094-0.24479q0-0.03865 0.02094-0.06281 0.02255-0.02416 0.05798-0.02416t0.05798 0.02416q0.02416 0.02255 0.02416 0.06281 0 0.03865-0.02416 0.0612-0.02255 0.02094-0.05798 0.02094t-0.05798-0.02255q-0.02094-0.02255-0.02094-0.05959z"/>
<path d="m-48.041 50.789q0 0.15622-0.06925 0.2303-0.06925 0.07408-0.20131 0.07408-0.08052 0-0.13206-0.0145-0.05153-0.01288-0.08374-0.0306l0.03382-0.09985q0.03221 0.01449 0.07086 0.02738 0.03865 0.01288 0.09502 0.01288 0.09824 0 0.13367-0.05476 0.03704-0.05476 0.03704-0.18359v-0.05959h-0.0048q-0.02577 0.03704-0.06603 0.05798t-0.10307 0.02094q-0.13045 0-0.19165-0.09985-0.0612-0.10146-0.0612-0.31726 0-0.20775 0.07891-0.31404 0.08052-0.10629 0.23674-0.10629 0.07569 0 0.13045 0.01449 0.05476 0.01449 0.09663 0.03382zm-0.11595-0.72632q-0.04831-0.02577-0.12401-0.02577-0.08213 0-0.13206 0.07569-0.04992 0.07408-0.04992 0.23835 0 0.06764 0.0081 0.12562 0.0081 0.05637 0.02738 0.09985 0.01933 0.04187 0.04831 0.06603 0.0306 0.02255 0.07408 0.02255 0.0612 0 0.09663-0.03221t0.05154-0.09663z"/>
<path d="m-47.441 50.752v-0.48958q0-0.11273-0.02738-0.17071-0.02577-0.05959-0.10468-0.05959-0.05637 0-0.10307 0.04026-0.04509 0.04026-0.0612 0.10146v0.57816h-0.11595v-1.1273h0.11595v0.39779h0.0048q0.03221-0.04187 0.07891-0.06764 0.04832-0.02738 0.11918-0.02738 0.05315 0 0.0918 0.0145 0.04026 0.01449 0.06603 0.04992t0.03865 0.09502q0.01288 0.05798 0.01288 0.14494v0.52018z"/>
<path d="m-47.226 49.946h0.09824v-0.15944l0.11595-0.03704v0.19648h0.17393v0.10468h-0.17393v0.47992q0 0.07086 0.01611 0.10307 0.01772 0.0306 0.05637 0.0306 0.03221 0 0.05476-0.0064 0.02416-0.0081 0.05154-0.01933l0.02255 0.0918q-0.03543 0.01772-0.07891 0.02738-0.04187 0.01127-0.08858 0.01127-0.08052 0-0.11595-0.05154-0.03382-0.05315-0.03382-0.17071v-0.49603h-0.09824z"/>
<path d="m-46.272 49.946 0.14333 0.47026 0.02899 0.15461h0.0032l0.02416-0.15783 0.10951-0.46704h0.10951l-0.21418 0.82295h-0.06603l-0.16266-0.52824-0.02255-0.13528h-0.0032l-0.02255 0.13689-0.15783 0.52662h-0.06603l-0.22064-0.82295h0.12401l0.12401 0.46865 0.01933 0.15622h0.0032l0.02899-0.15944 0.13206-0.46543z"/>
<path d="m-45.286 50.697q-0.03865 0.03543-0.09824 0.05476t-0.12562 0.01933q-0.07569 0-0.13206-0.02899-0.05476-0.0306-0.0918-0.08535-0.03543-0.05637-0.05315-0.13367-0.01611-0.0773-0.01611-0.17393 0-0.20614 0.07569-0.31404t0.21419-0.1079q0.04509 0 0.08858 0.01127 0.04509 0.01127 0.08052 0.04509t0.05637 0.09502q0.02255 0.0612 0.02255 0.15944 0 0.02738-0.0032 0.05959-0.0016 0.0306-0.0048 0.06442h-0.40906q0 0.06925 0.01127 0.12562 0.01127 0.05637 0.03543 0.09663 0.02416 0.03865 0.0612 0.0612 0.03865 0.02094 0.09502 0.02094 0.04348 0 0.08535-0.0161 0.04348-0.01611 0.06603-0.03865zm-0.09019-0.43161q0.0032-0.12079-0.03382-0.17715-0.03704-0.05637-0.10146-0.05637-0.07408 0-0.11756 0.05637-0.04348 0.05637-0.05154 0.17715z"/>
<path d="m-45.084 49.946h0.11595v0.80524h-0.11595zm-0.02094-0.24479q0-0.03865 0.02094-0.06281 0.02255-0.02416 0.05798-0.02416t0.05798 0.02416q0.02416 0.02255 0.02416 0.06281 0 0.03865-0.02416 0.0612-0.02255 0.02094-0.05798 0.02094t-0.05798-0.02255q-0.02094-0.02255-0.02094-0.05959z"/>
<path d="m-44.247 50.789q0 0.15622-0.06925 0.2303-0.06925 0.07408-0.20131 0.07408-0.08052 0-0.13206-0.0145-0.05153-0.01288-0.08374-0.0306l0.03382-0.09985q0.03221 0.01449 0.07086 0.02738 0.03865 0.01288 0.09502 0.01288 0.09824 0 0.13367-0.05476 0.03704-0.05476 0.03704-0.18359v-0.05959h-0.0048q-0.02577 0.03704-0.06603 0.05798t-0.10307 0.02094q-0.13045 0-0.19165-0.09985-0.0612-0.10146-0.0612-0.31726 0-0.20775 0.07891-0.31404 0.08052-0.10629 0.23674-0.10629 0.07569 0 0.13045 0.01449 0.05476 0.01449 0.09663 0.03382zm-0.11595-0.72632q-0.04831-0.02577-0.12401-0.02577-0.08213 0-0.13206 0.07569-0.04993 0.07408-0.04993 0.23835 0 0.06764 0.0081 0.12562 0.0081 0.05637 0.02738 0.09985 0.01933 0.04187 0.04831 0.06603 0.0306 0.02255 0.07408 0.02255 0.0612 0 0.09663-0.03221t0.05154-0.09663z"/>
<path d="m-43.647 50.752v-0.48958q0-0.11273-0.02738-0.17071-0.02577-0.05959-0.10468-0.05959-0.05637 0-0.10307 0.04026-0.04509 0.04026-0.0612 0.10146v0.57816h-0.11595v-1.1273h0.11595v0.39779h0.0048q0.03221-0.04187 0.07891-0.06764 0.04831-0.02738 0.11918-0.02738 0.05315 0 0.0918 0.0145 0.04026 0.01449 0.06603 0.04992t0.03865 0.09502q0.01288 0.05798 0.01288 0.14494v0.52018z"/>
<path d="m-43.432 49.946h0.09824v-0.15944l0.11595-0.03704v0.19648h0.17393v0.10468h-0.17393v0.47992q0 0.07086 0.01611 0.10307 0.01771 0.0306 0.05637 0.0306 0.03221 0 0.05476-0.0064 0.02416-0.0081 0.05154-0.01933l0.02255 0.0918q-0.03543 0.01772-0.07891 0.02738-0.04187 0.01127-0.08858 0.01127-0.08052 0-0.11595-0.05154-0.03382-0.05315-0.03382-0.17071v-0.49603h-0.09824z"/>
<path d="m-42.945 50.682q0-0.04026 0.02255-0.06442 0.02416-0.02416 0.0612-0.02416 0.04187 0 0.06764 0.03382 0.02738 0.03382 0.02738 0.10629 0 0.05315-0.01449 0.09502-0.01288 0.04348-0.03543 0.07569-0.02094 0.03221-0.0467 0.05315-0.02577 0.02094-0.04993 0.0306l-0.04026-0.05476q0.02094-0.01127 0.03865-0.0306 0.01933-0.01772 0.0306-0.04026 0.01288-0.02255 0.01933-0.04831 0.0064-0.02416 0.0064-0.04831-0.03221 0.0097-0.05959-0.01288-0.02738-0.02255-0.02738-0.07086z"/>
<path d="m-42.373 49.946h0.08213l0.01771 0.08697h0.0064q0.05959-0.10629 0.18682-0.10629 0.12723 0 0.19004 0.09502 0.06442 0.09502 0.06442 0.31082 0 0.10146-0.02094 0.18359-0.02094 0.08052-0.05959 0.1385-0.03865 0.05637-0.09502 0.08696-0.05476 0.02899-0.1224 0.02899-0.0467 0-0.07408-0.0064-0.02738-0.0048-0.05959-0.02255v0.33176h-0.11595zm0.11595 0.67801q0.02255 0.01933 0.04992 0.0306 0.02899 0.01127 0.07569 0.01127 0.08535 0 0.13528-0.08697 0.04992-0.08696 0.04992-0.24801 0-0.06764-0.0097-0.1224-0.0081-0.05476-0.02738-0.09341-0.01933-0.04026-0.04992-0.0612-0.02899-0.02255-0.07247-0.02255-0.11756 0-0.15138 0.14333z"/>
<path d="m-41.707 50.349q0-0.21742 0.07408-0.31887 0.07569-0.10307 0.21419-0.10307 0.14816 0 0.21741 0.10468 0.07086 0.10468 0.07086 0.31726 0 0.21902-0.07569 0.32048t-0.21258 0.10146q-0.14816 0-0.21902-0.10468-0.06925-0.10468-0.06925-0.31726zm0.12079 0q0 0.07086 0.0081 0.12884 0.0097 0.05798 0.02899 0.09985 0.02094 0.04187 0.05315 0.06603 0.03221 0.02255 0.0773 0.02255 0.08375 0 0.12562-0.07408 0.04187-0.07569 0.04187-0.24318 0-0.06925-0.0097-0.12723-0.0081-0.05959-0.02899-0.10146-0.01933-0.04187-0.05154-0.06442-0.03221-0.02416-0.0773-0.02416-0.08213 0-0.12562 0.07569-0.04187 0.07569-0.04187 0.24157z"/>
<path d="m-40.977 49.946h0.08213l0.02094 0.08535h0.0048q0.02255-0.0467 0.05798-0.07247 0.03704-0.02738 0.08858-0.02738 0.03704 0 0.08375 0.01449l-0.02255 0.11756q-0.04187-0.01449-0.07408-0.01449-0.05154 0-0.08374 0.0306-0.03221 0.02899-0.04187 0.07891v0.59265h-0.11595z"/>
<path d="m-40.579 49.946h0.09824v-0.15944l0.11595-0.03704v0.19648h0.17393v0.10468h-0.17393v0.47992q0 0.07086 0.01611 0.10307 0.01772 0.0306 0.05637 0.0306 0.03221 0 0.05476-0.0064 0.02416-0.0081 0.05154-0.01933l0.02255 0.0918q-0.03543 0.01772-0.07891 0.02738-0.04187 0.01127-0.08858 0.01127-0.08052 0-0.11595-0.05154-0.03382-0.05315-0.03382-0.17071v-0.49603h-0.09824z"/>
<path d="m-40.063 49.995q0.0467-0.02899 0.11273-0.04509 0.06764-0.01611 0.14172-0.01611 0.06764 0 0.1079 0.02094 0.04187 0.01933 0.06442 0.05476 0.02416 0.03382 0.0306 0.07891 0.0081 0.04348 0.0081 0.0918 0 0.09663-0.0048 0.18842-0.0032 0.0918-0.0032 0.17393 0 0.0612 0.0032 0.11434 0.0048 0.05154 0.01611 0.09824h-0.08858l-0.02738-0.09502h-0.0064q-0.02416 0.04187-0.07086 0.07247t-0.12562 0.0306q-0.08697 0-0.14333-0.05959-0.05476-0.0612-0.05476-0.16749 0-0.06925 0.02255-0.11596 0.02416-0.0467 0.06603-0.07569 0.04348-0.02899 0.10146-0.04026 0.05959-0.01288 0.13206-0.01288 0.01611 0 0.03221 0 0.01611 0 0.03382 0.0016 0.0048-0.04993 0.0048-0.08858 0-0.0918-0.02738-0.12884-0.02738-0.03704-0.09985-0.03704-0.04509 0-0.09824 0.01449-0.05315 0.01288-0.08858 0.03382zm0.34947 0.38974q-0.0161-0.0016-0.03221-0.0016-0.01611-0.0016-0.03221-0.0016-0.03865 0-0.07569 0.0064t-0.06603 0.02255q-0.02899 0.0161-0.0467 0.04348-0.01611 0.02738-0.01611 0.06925 0 0.06442 0.0306 0.09985 0.03221 0.03543 0.08213 0.03543 0.06764 0 0.10468-0.03221 0.03704-0.03221 0.05153-0.07086z"/>
<path d="m-39.41 49.624h0.11595v0.38329h0.0048q0.06603-0.08052 0.17554-0.08052 0.12401 0 0.1852 0.09824 0.06281 0.09824 0.06281 0.31082 0 0.21741-0.08374 0.3237-0.08214 0.10629-0.23352 0.10629-0.07408 0-0.13528-0.0161-0.0612-0.01772-0.0918-0.04026zm0.11595 1.0098q0.02255 0.01288 0.05476 0.02094 0.03382 0.0064 0.07086 0.0064 0.08375 0 0.13206-0.07891 0.04993-0.08052 0.04993-0.2464 0-0.06925-0.0097-0.12401-0.0081-0.05637-0.02738-0.09663-0.01771-0.04026-0.04831-0.0612-0.02899-0.02255-0.07086-0.02255-0.05798 0-0.09663 0.03543-0.03704 0.03382-0.05476 0.09341z"/>
<path d="m-38.588 50.56q0 0.05637 0.01449 0.08052 0.0161 0.02416 0.04348 0.02416 0.03382 0 0.07891-0.01772l0.01127 0.09341q-0.02094 0.01288-0.05959 0.02094-0.03704 0.0081-0.06764 0.0081-0.0612 0-0.09985-0.03704-0.03704-0.03865-0.03704-0.13367v-0.97434h0.11595z"/>
<path d="m-37.856 50.697q-0.03865 0.03543-0.09824 0.05476t-0.12562 0.01933q-0.07569 0-0.13206-0.02899-0.05476-0.0306-0.0918-0.08535-0.03543-0.05637-0.05314-0.13367-0.01611-0.0773-0.01611-0.17393 0-0.20614 0.07569-0.31404t0.21419-0.1079q0.04509 0 0.08858 0.01127 0.04509 0.01127 0.08052 0.04509t0.05637 0.09502q0.02255 0.0612 0.02255 0.15944 0 0.02738-0.0032 0.05959-0.0016 0.0306-0.0048 0.06442h-0.40906q0 0.06925 0.01127 0.12562 0.01127 0.05637 0.03543 0.09663 0.02416 0.03865 0.0612 0.0612 0.03865 0.02094 0.09502 0.02094 0.04348 0 0.08536-0.0161 0.04348-0.01611 0.06603-0.03865zm-0.09019-0.43161q0.0032-0.12079-0.03382-0.17715-0.03704-0.05637-0.10146-0.05637-0.07408 0-0.11756 0.05637-0.04348 0.05637-0.05154 0.17715z"/>
<path d="m-36.734 50.708q-0.04026 0.03382-0.10146 0.04831t-0.12884 0.01449q-0.08535 0-0.15783-0.03221-0.07247-0.03221-0.12562-0.10146-0.05154-0.07086-0.08052-0.18198-0.02899-0.11112-0.02899-0.26734 0-0.16105 0.03221-0.27217 0.03382-0.11112 0.08858-0.18037t0.12562-0.09985q0.07247-0.0306 0.14816-0.0306 0.0773 0 0.12723 0.01127 0.05154 0.01127 0.08858 0.02738l-0.02899 0.10951q-0.03221-0.01772-0.07569-0.02738-0.04348-0.0097-0.09985-0.0097t-0.10629 0.02577q-0.04993 0.02416-0.08858 0.08052-0.03865 0.05476-0.0612 0.14494-0.02255 0.09019-0.02255 0.22064 0 0.23513 0.08052 0.3543 0.08052 0.11756 0.21419 0.11756 0.05476 0 0.09824-0.01449 0.04348-0.0161 0.07408-0.03704z"/>
<path d="m-36.176 50.56q0 0.05637 0.01449 0.08052 0.0161 0.02416 0.04348 0.02416 0.03382 0 0.07891-0.01772l0.01127 0.09341q-0.02094 0.01288-0.05959 0.02094-0.03704 0.0081-0.06764 0.0081-0.0612 0-0.09985-0.03704-0.03704-0.03865-0.03704-0.13367v-0.97434h0.11595z"/>
<path d="m-35.906 49.946h0.11595v0.80524h-0.11595zm-0.02094-0.24479q0-0.03865 0.02094-0.06281 0.02255-0.02416 0.05798-0.02416t0.05798 0.02416q0.02416 0.02255 0.02416 0.06281 0 0.03865-0.02416 0.0612-0.02255 0.02094-0.05798 0.02094t-0.05798-0.02255q-0.02094-0.02255-0.02094-0.05959z"/>
<path d="m-35.576 49.624h0.11596v0.38329h0.0048q0.06603-0.08052 0.17554-0.08052 0.12401 0 0.1852 0.09824 0.06281 0.09824 0.06281 0.31082 0 0.21741-0.08375 0.3237-0.08213 0.10629-0.23352 0.10629-0.07408 0-0.13528-0.0161-0.0612-0.01772-0.0918-0.04026zm0.11596 1.0098q0.02255 0.01288 0.05476 0.02094 0.03382 0.0064 0.07086 0.0064 0.08374 0 0.13206-0.07891 0.04993-0.08052 0.04993-0.2464 0-0.06925-0.0097-0.12401-0.0081-0.05637-0.02738-0.09663-0.01771-0.04026-0.04831-0.0612-0.02899-0.02255-0.07086-0.02255-0.05798 0-0.09663 0.03543-0.03704 0.03382-0.05476 0.09341z"/>
<path d="m-34.878 49.946h0.08213l0.02094 0.08535h0.0048q0.02255-0.0467 0.05798-0.07247 0.03704-0.02738 0.08858-0.02738 0.03704 0 0.08375 0.01449l-0.02255 0.11756q-0.04187-0.01449-0.07408-0.01449-0.05154 0-0.08374 0.0306-0.03221 0.02899-0.04187 0.07891v0.59265h-0.11595z"/>
<path d="m-34.446 49.995q0.0467-0.02899 0.11273-0.04509 0.06764-0.01611 0.14172-0.01611 0.06764 0 0.1079 0.02094 0.04187 0.01933 0.06442 0.05476 0.02416 0.03382 0.0306 0.07891 0.0081 0.04348 0.0081 0.0918 0 0.09663-0.0048 0.18842-0.0032 0.0918-0.0032 0.17393 0 0.0612 0.0032 0.11434 0.0048 0.05154 0.01611 0.09824h-0.08858l-0.02738-0.09502h-0.0064q-0.02416 0.04187-0.07086 0.07247t-0.12562 0.0306q-0.08696 0-0.14333-0.05959-0.05476-0.0612-0.05476-0.16749 0-0.06925 0.02255-0.11596 0.02416-0.0467 0.06603-0.07569 0.04348-0.02899 0.10146-0.04026 0.05959-0.01288 0.13206-0.01288 0.0161 0 0.03221 0t0.03382 0.0016q0.0048-0.04993 0.0048-0.08858 0-0.0918-0.02738-0.12884-0.02738-0.03704-0.09985-0.03704-0.04509 0-0.09824 0.01449-0.05315 0.01288-0.08858 0.03382zm0.34947 0.38974q-0.01611-0.0016-0.03221-0.0016-0.01611-0.0016-0.03221-0.0016-0.03865 0-0.07569 0.0064t-0.06603 0.02255q-0.02899 0.0161-0.0467 0.04348-0.01611 0.02738-0.01611 0.06925 0 0.06442 0.0306 0.09985 0.03221 0.03543 0.08214 0.03543 0.06764 0 0.10468-0.03221t0.05154-0.07086z"/>
<path d="m-33.793 49.946h0.08214l0.02094 0.08535h0.0048q0.02255-0.0467 0.05798-0.07247 0.03704-0.02738 0.08858-0.02738 0.03704 0 0.08375 0.01449l-0.02255 0.11756q-0.04187-0.01449-0.07408-0.01449-0.05154 0-0.08374 0.0306-0.03221 0.02899-0.04187 0.07891v0.59265h-0.11595z"/>
<path d="m-33.153 50.467 0.03382 0.15622h0.0081l0.02416-0.15622 0.1224-0.52018h0.11756l-0.19165 0.7231q-0.02255 0.08696-0.04509 0.16266-0.02255 0.07569-0.04992 0.13045-0.02577 0.05637-0.05959 0.08697-0.03221 0.03221-0.0773 0.03221t-0.07891-0.01449l0.01933-0.10951q0.02255 0.0081 0.04509 0.0032 0.02255-0.0048 0.04187-0.02738 0.02094-0.02255 0.03704-0.06764 0.01772-0.04348 0.0306-0.11434l-0.2609-0.80524h0.13206z"/>
</g>
</g>
<g>
<g transform="matrix(4.0081 0 0 4.0081 -210.57 -224.31)" stroke-width=".4463" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal" aria-label="libwebsockets.org">
<g stroke-width=".4463">
<path d="m-52.015 48.429q0 0.12497 0.03213 0.17852 0.0357 0.05356 0.0964 0.05356 0.07498 0 0.17495-0.03927l0.02499 0.20709q-0.04642 0.02856-0.13211 0.04642-0.08212 0.01785-0.14996 0.01785-0.13568 0-0.22137-0.08212-0.08212-0.08569-0.08212-0.29635v-2.1601h0.25707z"/>
<path d="m-51.417 47.068h0.25707v1.7852h-0.25707zm-0.04642-0.54271q0-0.08569 0.04642-0.13925 0.04999-0.05356 0.12854-0.05356 0.07855 0 0.12854 0.05356 0.05356 0.04999 0.05356 0.13925 0 0.08569-0.05356 0.13568-0.04999 0.04642-0.12854 0.04642-0.07855 0-0.12854-0.04999-0.04642-0.04999-0.04642-0.13211z"/>
<path d="m-50.686 46.354h0.25707v0.84976h0.01071q0.14639-0.17852 0.38918-0.17852 0.27492 0 0.4106 0.2178 0.13925 0.2178 0.13925 0.6891 0 0.48201-0.18566 0.71766-0.18209 0.23565-0.51771 0.23565-0.16424 0-0.29992-0.03571-0.13568-0.03927-0.20352-0.08926zm0.25707 2.2387q0.04999 0.02856 0.1214 0.04641 0.07498 0.01428 0.1571 0.01428 0.18566 0 0.29278-0.17495 0.11068-0.17852 0.11068-0.54628 0-0.15353-0.02142-0.27492-0.01785-0.12496-0.0607-0.21423-0.03927-0.08926-0.10711-0.13568-0.06427-0.04999-0.1571-0.04999-0.12854 0-0.21423 0.07855-0.08212 0.07498-0.1214 0.20708z"/>
</g>
<path d="m-48.092 47.068 0.24993 0.91403 0.04284 0.29635h0.01428l0.0357-0.29992 0.16781-0.91046h0.38561l-0.43916 1.8031h-0.33562l-0.26778-0.99615-0.02856-0.22851h-0.02142l-0.02499 0.23565-0.25707 0.98901h-0.34633l-0.45702-1.8031h0.46059l0.1928 0.89618 0.03213 0.31777h0.01428l0.04642-0.32134 0.2178-0.89261z"/>
<path d="m-45.889 48.721q-0.08926 0.07855-0.24279 0.12854-0.15353 0.04999-0.32134 0.04999-0.18566 0-0.32134-0.06427-0.13211-0.06427-0.2178-0.18566-0.08569-0.1214-0.12854-0.29278-0.03927-0.17495-0.03927-0.39632 0-0.48201 0.18923-0.71052 0.1928-0.23208 0.532-0.23208 0.11425 0 0.22137 0.0357 0.10711 0.03213 0.18923 0.11425 0.08569 0.07855 0.13568 0.21423 0.05356 0.13211 0.05356 0.33562 0 0.07855-0.01071 0.16781-0.0071 0.08926-0.02499 0.1928h-0.86762q0.0071 0.22137 0.09283 0.33919 0.08569 0.11782 0.27492 0.11782 0.11425 0 0.20709-0.0357 0.0964-0.0357 0.14639-0.07498zm-0.55699-1.3389q-0.13568 0-0.20352 0.11068-0.06784 0.10711-0.07855 0.30349h0.49272q0.01071-0.20352-0.04284-0.30706-0.05356-0.10711-0.16781-0.10711z"/>
<path d="m-45.569 46.354h0.42488v0.82834h0.01071q0.12854-0.1571 0.36776-0.1571 0.2535 0 0.39275 0.21066 0.14282 0.21066 0.14282 0.67838 0 0.507-0.19994 0.74622-0.19994 0.23565-0.54628 0.23565-0.18923 0-0.3499-0.0357-0.1571-0.03571-0.24279-0.07855zm0.42488 2.1137q0.07498 0.03927 0.19638 0.03927 0.13568 0 0.20708-0.12854 0.07141-0.13211 0.07141-0.43916 0-0.27135-0.05713-0.39632-0.05713-0.12854-0.17852-0.12854-0.17852 0-0.23922 0.18566z"/>
<path d="m-43.386 48.379q0-0.07498-0.04999-0.12496-0.04642-0.05356-0.1214-0.0964-0.07498-0.04642-0.16067-0.09283-0.08212-0.04641-0.1571-0.11425-0.07498-0.06784-0.12496-0.16424-0.04642-0.0964-0.04642-0.24279 0-0.24993 0.13568-0.38561 0.13568-0.13568 0.39989-0.13568 0.1571 0 0.29635 0.0357 0.13925 0.03213 0.22137 0.08212l-0.09997 0.32848q-0.06784-0.02856-0.16424-0.05356-0.0964-0.02856-0.18923-0.02856-0.17495 0-0.17495 0.14639 0 0.06784 0.04642 0.11425 0.04999 0.04284 0.12496 0.08569 0.07498 0.04284 0.1571 0.08926 0.08569 0.04642 0.16067 0.11782 0.07498 0.06784 0.1214 0.16781 0.04999 0.09997 0.04999 0.24636 0 0.24636-0.14996 0.39632-0.14996 0.14996-0.4463 0.14996-0.14639 0-0.2892-0.0357-0.13925-0.0357-0.22494-0.09283l0.11782-0.34276q0.07498 0.04285 0.17138 0.07498 0.09997 0.03213 0.20709 0.03213 0.08212 0 0.13568-0.0357 0.05356-0.03928 0.05356-0.1214z"/>
<path d="m-42.802 47.961q0-0.47487 0.18566-0.70695 0.18566-0.23208 0.51771-0.23208 0.35704 0 0.532 0.23565 0.17495 0.23565 0.17495 0.70338 0 0.47844-0.18566 0.71052-0.18566 0.22851-0.52128 0.22851-0.70338 0-0.70338-0.93902zm0.43916 0q0 0.26778 0.0607 0.41417t0.20352 0.14639q0.13568 0 0.19994-0.12497 0.06784-0.12854 0.06784-0.43559 0-0.27492-0.0607-0.41774-0.0607-0.14282-0.20708-0.14282-0.12497 0-0.19638 0.12854-0.06784 0.12497-0.06784 0.43202z"/>
<path d="m-40.094 48.757q-0.08926 0.07141-0.21423 0.10711-0.12496 0.0357-0.24993 0.0357-0.18209 0-0.30706-0.06427-0.1214-0.06784-0.19994-0.18923-0.07855-0.12496-0.11425-0.29635-0.03213-0.17495-0.03213-0.38918 0-0.46773 0.16781-0.70338 0.16781-0.23565 0.49272-0.23565 0.16067 0 0.26064 0.02856 0.10354 0.02856 0.18209 0.07141l-0.09997 0.35347q-0.06427-0.03213-0.12497-0.04642-0.05713-0.01785-0.13925-0.01785-0.14996 0-0.22494 0.13211-0.07498 0.12854-0.07498 0.41774 0 0.24279 0.07498 0.39632 0.07855 0.15353 0.24636 0.15353 0.08926 0 0.14996-0.02142 0.06427-0.02499 0.11782-0.0607z"/>
<path d="m-39.374 48.114h-0.09997v0.73908h-0.42488v-2.4993h0.42488v1.4746l0.08569-0.04999 0.29635-0.71052h0.46059l-0.32848 0.70695-0.15353 0.1214 0.16781 0.1214 0.36418 0.83548h-0.47844z"/>
<path d="m-37.256 48.721q-0.08926 0.07855-0.24279 0.12854-0.15353 0.04999-0.32134 0.04999-0.18566 0-0.32134-0.06427-0.13211-0.06427-0.2178-0.18566-0.08569-0.1214-0.12854-0.29278-0.03927-0.17495-0.03927-0.39632 0-0.48201 0.18923-0.71052 0.1928-0.23208 0.532-0.23208 0.11425 0 0.22137 0.0357 0.10711 0.03213 0.18923 0.11425 0.08569 0.07855 0.13568 0.21423 0.05356 0.13211 0.05356 0.33562 0 0.07855-0.01071 0.16781-0.0071 0.08926-0.02499 0.1928h-0.86763q0.0071 0.22137 0.09283 0.33919 0.08569 0.11782 0.27492 0.11782 0.11425 0 0.20708-0.0357 0.0964-0.0357 0.14639-0.07498zm-0.55699-1.3389q-0.13568 0-0.20352 0.11068-0.06784 0.10711-0.07855 0.30349h0.49272q0.01071-0.20352-0.04284-0.30706-0.05356-0.10711-0.16781-0.10711z"/>
<path d="m-37.075 47.068h0.19637v-0.33562l0.42488-0.13211v0.46773h0.34633v0.37847h-0.34633v0.77836q0 0.15353 0.02856 0.2178 0.03213 0.06427 0.11068 0.06427 0.05356 0 0.0964-0.01071t0.09283-0.03213l0.05356 0.33919q-0.07855 0.03928-0.18209 0.06427-0.10354 0.02856-0.2178 0.02856-0.20352 0-0.30706-0.11782-0.09997-0.11782-0.09997-0.39632v-0.93546h-0.19637z"/>
<path d="m-35.297 48.379q0-0.07498-0.04999-0.12496-0.04641-0.05356-0.1214-0.0964-0.07498-0.04642-0.16067-0.09283-0.08212-0.04641-0.1571-0.11425-0.07498-0.06784-0.12496-0.16424-0.04642-0.0964-0.04642-0.24279 0-0.24993 0.13568-0.38561 0.13568-0.13568 0.39989-0.13568 0.1571 0 0.29635 0.0357 0.13925 0.03213 0.22137 0.08212l-0.09997 0.32848q-0.06784-0.02856-0.16424-0.05356-0.0964-0.02856-0.18923-0.02856-0.17495 0-0.17495 0.14639 0 0.06784 0.04642 0.11425 0.04999 0.04284 0.12497 0.08569 0.07498 0.04284 0.1571 0.08926 0.08569 0.04642 0.16067 0.11782 0.07498 0.06784 0.1214 0.16781 0.04999 0.09997 0.04999 0.24636 0 0.24636-0.14996 0.39632-0.14996 0.14996-0.4463 0.14996-0.14639 0-0.2892-0.0357-0.13925-0.0357-0.22494-0.09283l0.11782-0.34276q0.07498 0.04285 0.17138 0.07498 0.09997 0.03213 0.20708 0.03213 0.08212 0 0.13568-0.0357 0.05356-0.03928 0.05356-0.1214z"/>
<g stroke-width=".4463">
<path d="m-34.662 48.693q0-0.09997 0.04642-0.14996 0.04999-0.04999 0.13211-0.04999 0.08212 0 0.12854 0.04999 0.04999 0.04999 0.04999 0.14996 0 0.10354-0.04999 0.15353-0.04642 0.04999-0.12854 0.04999-0.08212 0-0.13211-0.04999-0.04642-0.04999-0.04642-0.15353z"/>
<path d="m-34.035 47.961q0-0.48201 0.16424-0.70695 0.16781-0.22851 0.47487-0.22851 0.32848 0 0.48201 0.23208 0.1571 0.23208 0.1571 0.70338 0 0.48558-0.16781 0.71052-0.16781 0.22494-0.4713 0.22494-0.32848 0-0.48558-0.23208-0.15353-0.23208-0.15353-0.70338zm0.26778 0q0 0.1571 0.01785 0.28564 0.02142 0.12854 0.06427 0.22137 0.04642 0.09283 0.11782 0.14639 0.07141 0.04999 0.17138 0.04999 0.18566 0 0.2785-0.16424 0.09283-0.16781 0.09283-0.53914 0-0.15353-0.02142-0.28206-0.01785-0.13211-0.06427-0.22494-0.04285-0.09283-0.11425-0.14282-0.07141-0.05356-0.17138-0.05356-0.18209 0-0.27849 0.16781-0.09283 0.16781-0.09283 0.53557z"/>
<path d="m-32.415 47.068h0.18209l0.04642 0.18923h0.01071q0.04999-0.10354 0.12854-0.16067 0.08212-0.0607 0.19637-0.0607 0.08212 0 0.18566 0.03213l-0.04999 0.26064q-0.09283-0.03213-0.16424-0.03213-0.11426 0-0.18566 0.06784-0.07141 0.06427-0.09283 0.17495v1.3139h-0.25707z"/>
<path d="m-30.314 48.936q0 0.34633-0.15353 0.51057-0.15353 0.16424-0.4463 0.16424-0.17852 0-0.29278-0.03213-0.11425-0.02856-0.18566-0.06784l0.07498-0.22137q0.07141 0.03213 0.1571 0.0607 0.08569 0.02856 0.21066 0.02856 0.2178 0 0.29635-0.1214 0.08212-0.1214 0.08212-0.40703v-0.13211h-0.01071q-0.05713 0.08212-0.14639 0.12854-0.08926 0.04641-0.22851 0.04641-0.28921 0-0.42488-0.22137-0.13568-0.22494-0.13568-0.70338 0-0.46059 0.17495-0.69624 0.17852-0.23565 0.52486-0.23565 0.16781 0 0.2892 0.03213t0.21423 0.07498zm-0.25707-1.6103q-0.10711-0.05713-0.27492-0.05713-0.18209 0-0.29278 0.16781-0.11068 0.16424-0.11068 0.52842 0 0.14996 0.01785 0.27849 0.01785 0.12497 0.0607 0.22137 0.04285 0.09283 0.10711 0.14639 0.06784 0.04999 0.16424 0.04999 0.13568 0 0.21423-0.07141t0.11425-0.21423z"/>
</g>
</g>
<g transform="matrix(4.0081 0 0 4.0081 -210.57 -224.31)" stroke-width=".20131" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal" aria-label="lightweight, portable C library">
<path d="m-49.147 50.56q0 0.05637 0.01449 0.08052 0.0161 0.02416 0.04348 0.02416 0.03382 0 0.07891-0.01772l0.01127 0.09341q-0.02094 0.01288-0.05959 0.02094-0.03704 0.0081-0.06764 0.0081-0.0612 0-0.09985-0.03704-0.03704-0.03865-0.03704-0.13367v-0.97434h0.11595z"/>
<path d="m-48.878 49.946h0.11596v0.80524h-0.11596zm-0.02094-0.24479q0-0.03865 0.02094-0.06281 0.02255-0.02416 0.05798-0.02416t0.05798 0.02416q0.02416 0.02255 0.02416 0.06281 0 0.03865-0.02416 0.0612-0.02255 0.02094-0.05798 0.02094t-0.05798-0.02255q-0.02094-0.02255-0.02094-0.05959z"/>
<path d="m-48.041 50.789q0 0.15622-0.06925 0.2303-0.06925 0.07408-0.20131 0.07408-0.08052 0-0.13206-0.0145-0.05153-0.01288-0.08374-0.0306l0.03382-0.09985q0.03221 0.01449 0.07086 0.02738 0.03865 0.01288 0.09502 0.01288 0.09824 0 0.13367-0.05476 0.03704-0.05476 0.03704-0.18359v-0.05959h-0.0048q-0.02577 0.03704-0.06603 0.05798t-0.10307 0.02094q-0.13045 0-0.19165-0.09985-0.0612-0.10146-0.0612-0.31726 0-0.20775 0.07891-0.31404 0.08052-0.10629 0.23674-0.10629 0.07569 0 0.13045 0.01449 0.05476 0.01449 0.09663 0.03382zm-0.11595-0.72632q-0.04831-0.02577-0.12401-0.02577-0.08213 0-0.13206 0.07569-0.04992 0.07408-0.04992 0.23835 0 0.06764 0.0081 0.12562 0.0081 0.05637 0.02738 0.09985 0.01933 0.04187 0.04831 0.06603 0.0306 0.02255 0.07408 0.02255 0.0612 0 0.09663-0.03221t0.05154-0.09663z"/>
<path d="m-47.441 50.752v-0.48958q0-0.11273-0.02738-0.17071-0.02577-0.05959-0.10468-0.05959-0.05637 0-0.10307 0.04026-0.04509 0.04026-0.0612 0.10146v0.57816h-0.11595v-1.1273h0.11595v0.39779h0.0048q0.03221-0.04187 0.07891-0.06764 0.04832-0.02738 0.11918-0.02738 0.05315 0 0.0918 0.0145 0.04026 0.01449 0.06603 0.04992t0.03865 0.09502q0.01288 0.05798 0.01288 0.14494v0.52018z"/>
<path d="m-47.226 49.946h0.09824v-0.15944l0.11595-0.03704v0.19648h0.17393v0.10468h-0.17393v0.47992q0 0.07086 0.01611 0.10307 0.01772 0.0306 0.05637 0.0306 0.03221 0 0.05476-0.0064 0.02416-0.0081 0.05154-0.01933l0.02255 0.0918q-0.03543 0.01772-0.07891 0.02738-0.04187 0.01127-0.08858 0.01127-0.08052 0-0.11595-0.05154-0.03382-0.05315-0.03382-0.17071v-0.49603h-0.09824z"/>
<path d="m-46.272 49.946 0.14333 0.47026 0.02899 0.15461h0.0032l0.02416-0.15783 0.10951-0.46704h0.10951l-0.21418 0.82295h-0.06603l-0.16266-0.52824-0.02255-0.13528h-0.0032l-0.02255 0.13689-0.15783 0.52662h-0.06603l-0.22064-0.82295h0.12401l0.12401 0.46865 0.01933 0.15622h0.0032l0.02899-0.15944 0.13206-0.46543z"/>
<path d="m-45.286 50.697q-0.03865 0.03543-0.09824 0.05476t-0.12562 0.01933q-0.07569 0-0.13206-0.02899-0.05476-0.0306-0.0918-0.08535-0.03543-0.05637-0.05315-0.13367-0.01611-0.0773-0.01611-0.17393 0-0.20614 0.07569-0.31404t0.21419-0.1079q0.04509 0 0.08858 0.01127 0.04509 0.01127 0.08052 0.04509t0.05637 0.09502q0.02255 0.0612 0.02255 0.15944 0 0.02738-0.0032 0.05959-0.0016 0.0306-0.0048 0.06442h-0.40906q0 0.06925 0.01127 0.12562 0.01127 0.05637 0.03543 0.09663 0.02416 0.03865 0.0612 0.0612 0.03865 0.02094 0.09502 0.02094 0.04348 0 0.08535-0.0161 0.04348-0.01611 0.06603-0.03865zm-0.09019-0.43161q0.0032-0.12079-0.03382-0.17715-0.03704-0.05637-0.10146-0.05637-0.07408 0-0.11756 0.05637-0.04348 0.05637-0.05154 0.17715z"/>
<path d="m-45.084 49.946h0.11595v0.80524h-0.11595zm-0.02094-0.24479q0-0.03865 0.02094-0.06281 0.02255-0.02416 0.05798-0.02416t0.05798 0.02416q0.02416 0.02255 0.02416 0.06281 0 0.03865-0.02416 0.0612-0.02255 0.02094-0.05798 0.02094t-0.05798-0.02255q-0.02094-0.02255-0.02094-0.05959z"/>
<path d="m-44.247 50.789q0 0.15622-0.06925 0.2303-0.06925 0.07408-0.20131 0.07408-0.08052 0-0.13206-0.0145-0.05153-0.01288-0.08374-0.0306l0.03382-0.09985q0.03221 0.01449 0.07086 0.02738 0.03865 0.01288 0.09502 0.01288 0.09824 0 0.13367-0.05476 0.03704-0.05476 0.03704-0.18359v-0.05959h-0.0048q-0.02577 0.03704-0.06603 0.05798t-0.10307 0.02094q-0.13045 0-0.19165-0.09985-0.0612-0.10146-0.0612-0.31726 0-0.20775 0.07891-0.31404 0.08052-0.10629 0.23674-0.10629 0.07569 0 0.13045 0.01449 0.05476 0.01449 0.09663 0.03382zm-0.11595-0.72632q-0.04831-0.02577-0.12401-0.02577-0.08213 0-0.13206 0.07569-0.04993 0.07408-0.04993 0.23835 0 0.06764 0.0081 0.12562 0.0081 0.05637 0.02738 0.09985 0.01933 0.04187 0.04831 0.06603 0.0306 0.02255 0.07408 0.02255 0.0612 0 0.09663-0.03221t0.05154-0.09663z"/>
<path d="m-43.647 50.752v-0.48958q0-0.11273-0.02738-0.17071-0.02577-0.05959-0.10468-0.05959-0.05637 0-0.10307 0.04026-0.04509 0.04026-0.0612 0.10146v0.57816h-0.11595v-1.1273h0.11595v0.39779h0.0048q0.03221-0.04187 0.07891-0.06764 0.04831-0.02738 0.11918-0.02738 0.05315 0 0.0918 0.0145 0.04026 0.01449 0.06603 0.04992t0.03865 0.09502q0.01288 0.05798 0.01288 0.14494v0.52018z"/>
<path d="m-43.432 49.946h0.09824v-0.15944l0.11595-0.03704v0.19648h0.17393v0.10468h-0.17393v0.47992q0 0.07086 0.01611 0.10307 0.01771 0.0306 0.05637 0.0306 0.03221 0 0.05476-0.0064 0.02416-0.0081 0.05154-0.01933l0.02255 0.0918q-0.03543 0.01772-0.07891 0.02738-0.04187 0.01127-0.08858 0.01127-0.08052 0-0.11595-0.05154-0.03382-0.05315-0.03382-0.17071v-0.49603h-0.09824z"/>
<path d="m-42.945 50.682q0-0.04026 0.02255-0.06442 0.02416-0.02416 0.0612-0.02416 0.04187 0 0.06764 0.03382 0.02738 0.03382 0.02738 0.10629 0 0.05315-0.01449 0.09502-0.01288 0.04348-0.03543 0.07569-0.02094 0.03221-0.0467 0.05315-0.02577 0.02094-0.04993 0.0306l-0.04026-0.05476q0.02094-0.01127 0.03865-0.0306 0.01933-0.01772 0.0306-0.04026 0.01288-0.02255 0.01933-0.04831 0.0064-0.02416 0.0064-0.04831-0.03221 0.0097-0.05959-0.01288-0.02738-0.02255-0.02738-0.07086z"/>
<path d="m-42.373 49.946h0.08213l0.01771 0.08697h0.0064q0.05959-0.10629 0.18682-0.10629 0.12723 0 0.19004 0.09502 0.06442 0.09502 0.06442 0.31082 0 0.10146-0.02094 0.18359-0.02094 0.08052-0.05959 0.1385-0.03865 0.05637-0.09502 0.08696-0.05476 0.02899-0.1224 0.02899-0.0467 0-0.07408-0.0064-0.02738-0.0048-0.05959-0.02255v0.33176h-0.11595zm0.11595 0.67801q0.02255 0.01933 0.04992 0.0306 0.02899 0.01127 0.07569 0.01127 0.08535 0 0.13528-0.08697 0.04992-0.08696 0.04992-0.24801 0-0.06764-0.0097-0.1224-0.0081-0.05476-0.02738-0.09341-0.01933-0.04026-0.04992-0.0612-0.02899-0.02255-0.07247-0.02255-0.11756 0-0.15138 0.14333z"/>
<path d="m-41.707 50.349q0-0.21742 0.07408-0.31887 0.07569-0.10307 0.21419-0.10307 0.14816 0 0.21741 0.10468 0.07086 0.10468 0.07086 0.31726 0 0.21902-0.07569 0.32048t-0.21258 0.10146q-0.14816 0-0.21902-0.10468-0.06925-0.10468-0.06925-0.31726zm0.12079 0q0 0.07086 0.0081 0.12884 0.0097 0.05798 0.02899 0.09985 0.02094 0.04187 0.05315 0.06603 0.03221 0.02255 0.0773 0.02255 0.08375 0 0.12562-0.07408 0.04187-0.07569 0.04187-0.24318 0-0.06925-0.0097-0.12723-0.0081-0.05959-0.02899-0.10146-0.01933-0.04187-0.05154-0.06442-0.03221-0.02416-0.0773-0.02416-0.08213 0-0.12562 0.07569-0.04187 0.07569-0.04187 0.24157z"/>
<path d="m-40.977 49.946h0.08213l0.02094 0.08535h0.0048q0.02255-0.0467 0.05798-0.07247 0.03704-0.02738 0.08858-0.02738 0.03704 0 0.08375 0.01449l-0.02255 0.11756q-0.04187-0.01449-0.07408-0.01449-0.05154 0-0.08374 0.0306-0.03221 0.02899-0.04187 0.07891v0.59265h-0.11595z"/>
<path d="m-40.579 49.946h0.09824v-0.15944l0.11595-0.03704v0.19648h0.17393v0.10468h-0.17393v0.47992q0 0.07086 0.01611 0.10307 0.01772 0.0306 0.05637 0.0306 0.03221 0 0.05476-0.0064 0.02416-0.0081 0.05154-0.01933l0.02255 0.0918q-0.03543 0.01772-0.07891 0.02738-0.04187 0.01127-0.08858 0.01127-0.08052 0-0.11595-0.05154-0.03382-0.05315-0.03382-0.17071v-0.49603h-0.09824z"/>
<path d="m-40.063 49.995q0.0467-0.02899 0.11273-0.04509 0.06764-0.01611 0.14172-0.01611 0.06764 0 0.1079 0.02094 0.04187 0.01933 0.06442 0.05476 0.02416 0.03382 0.0306 0.07891 0.0081 0.04348 0.0081 0.0918 0 0.09663-0.0048 0.18842-0.0032 0.0918-0.0032 0.17393 0 0.0612 0.0032 0.11434 0.0048 0.05154 0.01611 0.09824h-0.08858l-0.02738-0.09502h-0.0064q-0.02416 0.04187-0.07086 0.07247t-0.12562 0.0306q-0.08697 0-0.14333-0.05959-0.05476-0.0612-0.05476-0.16749 0-0.06925 0.02255-0.11596 0.02416-0.0467 0.06603-0.07569 0.04348-0.02899 0.10146-0.04026 0.05959-0.01288 0.13206-0.01288 0.01611 0 0.03221 0 0.01611 0 0.03382 0.0016 0.0048-0.04993 0.0048-0.08858 0-0.0918-0.02738-0.12884-0.02738-0.03704-0.09985-0.03704-0.04509 0-0.09824 0.01449-0.05315 0.01288-0.08858 0.03382zm0.34947 0.38974q-0.0161-0.0016-0.03221-0.0016-0.01611-0.0016-0.03221-0.0016-0.03865 0-0.07569 0.0064t-0.06603 0.02255q-0.02899 0.0161-0.0467 0.04348-0.01611 0.02738-0.01611 0.06925 0 0.06442 0.0306 0.09985 0.03221 0.03543 0.08213 0.03543 0.06764 0 0.10468-0.03221 0.03704-0.03221 0.05153-0.07086z"/>
<path d="m-39.41 49.624h0.11595v0.38329h0.0048q0.06603-0.08052 0.17554-0.08052 0.12401 0 0.1852 0.09824 0.06281 0.09824 0.06281 0.31082 0 0.21741-0.08374 0.3237-0.08214 0.10629-0.23352 0.10629-0.07408 0-0.13528-0.0161-0.0612-0.01772-0.0918-0.04026zm0.11595 1.0098q0.02255 0.01288 0.05476 0.02094 0.03382 0.0064 0.07086 0.0064 0.08375 0 0.13206-0.07891 0.04993-0.08052 0.04993-0.2464 0-0.06925-0.0097-0.12401-0.0081-0.05637-0.02738-0.09663-0.01771-0.04026-0.04831-0.0612-0.02899-0.02255-0.07086-0.02255-0.05798 0-0.09663 0.03543-0.03704 0.03382-0.05476 0.09341z"/>
<path d="m-38.588 50.56q0 0.05637 0.01449 0.08052 0.0161 0.02416 0.04348 0.02416 0.03382 0 0.07891-0.01772l0.01127 0.09341q-0.02094 0.01288-0.05959 0.02094-0.03704 0.0081-0.06764 0.0081-0.0612 0-0.09985-0.03704-0.03704-0.03865-0.03704-0.13367v-0.97434h0.11595z"/>
<path d="m-37.856 50.697q-0.03865 0.03543-0.09824 0.05476t-0.12562 0.01933q-0.07569 0-0.13206-0.02899-0.05476-0.0306-0.0918-0.08535-0.03543-0.05637-0.05314-0.13367-0.01611-0.0773-0.01611-0.17393 0-0.20614 0.07569-0.31404t0.21419-0.1079q0.04509 0 0.08858 0.01127 0.04509 0.01127 0.08052 0.04509t0.05637 0.09502q0.02255 0.0612 0.02255 0.15944 0 0.02738-0.0032 0.05959-0.0016 0.0306-0.0048 0.06442h-0.40906q0 0.06925 0.01127 0.12562 0.01127 0.05637 0.03543 0.09663 0.02416 0.03865 0.0612 0.0612 0.03865 0.02094 0.09502 0.02094 0.04348 0 0.08536-0.0161 0.04348-0.01611 0.06603-0.03865zm-0.09019-0.43161q0.0032-0.12079-0.03382-0.17715-0.03704-0.05637-0.10146-0.05637-0.07408 0-0.11756 0.05637-0.04348 0.05637-0.05154 0.17715z"/>
<path d="m-36.734 50.708q-0.04026 0.03382-0.10146 0.04831t-0.12884 0.01449q-0.08535 0-0.15783-0.03221-0.07247-0.03221-0.12562-0.10146-0.05154-0.07086-0.08052-0.18198-0.02899-0.11112-0.02899-0.26734 0-0.16105 0.03221-0.27217 0.03382-0.11112 0.08858-0.18037t0.12562-0.09985q0.07247-0.0306 0.14816-0.0306 0.0773 0 0.12723 0.01127 0.05154 0.01127 0.08858 0.02738l-0.02899 0.10951q-0.03221-0.01772-0.07569-0.02738-0.04348-0.0097-0.09985-0.0097t-0.10629 0.02577q-0.04993 0.02416-0.08858 0.08052-0.03865 0.05476-0.0612 0.14494-0.02255 0.09019-0.02255 0.22064 0 0.23513 0.08052 0.3543 0.08052 0.11756 0.21419 0.11756 0.05476 0 0.09824-0.01449 0.04348-0.0161 0.07408-0.03704z"/>
<path d="m-36.176 50.56q0 0.05637 0.01449 0.08052 0.0161 0.02416 0.04348 0.02416 0.03382 0 0.07891-0.01772l0.01127 0.09341q-0.02094 0.01288-0.05959 0.02094-0.03704 0.0081-0.06764 0.0081-0.0612 0-0.09985-0.03704-0.03704-0.03865-0.03704-0.13367v-0.97434h0.11595z"/>
<path d="m-35.906 49.946h0.11595v0.80524h-0.11595zm-0.02094-0.24479q0-0.03865 0.02094-0.06281 0.02255-0.02416 0.05798-0.02416t0.05798 0.02416q0.02416 0.02255 0.02416 0.06281 0 0.03865-0.02416 0.0612-0.02255 0.02094-0.05798 0.02094t-0.05798-0.02255q-0.02094-0.02255-0.02094-0.05959z"/>
<path d="m-35.576 49.624h0.11596v0.38329h0.0048q0.06603-0.08052 0.17554-0.08052 0.12401 0 0.1852 0.09824 0.06281 0.09824 0.06281 0.31082 0 0.21741-0.08375 0.3237-0.08213 0.10629-0.23352 0.10629-0.07408 0-0.13528-0.0161-0.0612-0.01772-0.0918-0.04026zm0.11596 1.0098q0.02255 0.01288 0.05476 0.02094 0.03382 0.0064 0.07086 0.0064 0.08374 0 0.13206-0.07891 0.04993-0.08052 0.04993-0.2464 0-0.06925-0.0097-0.12401-0.0081-0.05637-0.02738-0.09663-0.01771-0.04026-0.04831-0.0612-0.02899-0.02255-0.07086-0.02255-0.05798 0-0.09663 0.03543-0.03704 0.03382-0.05476 0.09341z"/>
<path d="m-34.878 49.946h0.08213l0.02094 0.08535h0.0048q0.02255-0.0467 0.05798-0.07247 0.03704-0.02738 0.08858-0.02738 0.03704 0 0.08375 0.01449l-0.02255 0.11756q-0.04187-0.01449-0.07408-0.01449-0.05154 0-0.08374 0.0306-0.03221 0.02899-0.04187 0.07891v0.59265h-0.11595z"/>
<path d="m-34.446 49.995q0.0467-0.02899 0.11273-0.04509 0.06764-0.01611 0.14172-0.01611 0.06764 0 0.1079 0.02094 0.04187 0.01933 0.06442 0.05476 0.02416 0.03382 0.0306 0.07891 0.0081 0.04348 0.0081 0.0918 0 0.09663-0.0048 0.18842-0.0032 0.0918-0.0032 0.17393 0 0.0612 0.0032 0.11434 0.0048 0.05154 0.01611 0.09824h-0.08858l-0.02738-0.09502h-0.0064q-0.02416 0.04187-0.07086 0.07247t-0.12562 0.0306q-0.08696 0-0.14333-0.05959-0.05476-0.0612-0.05476-0.16749 0-0.06925 0.02255-0.11596 0.02416-0.0467 0.06603-0.07569 0.04348-0.02899 0.10146-0.04026 0.05959-0.01288 0.13206-0.01288 0.0161 0 0.03221 0t0.03382 0.0016q0.0048-0.04993 0.0048-0.08858 0-0.0918-0.02738-0.12884-0.02738-0.03704-0.09985-0.03704-0.04509 0-0.09824 0.01449-0.05315 0.01288-0.08858 0.03382zm0.34947 0.38974q-0.01611-0.0016-0.03221-0.0016-0.01611-0.0016-0.03221-0.0016-0.03865 0-0.07569 0.0064t-0.06603 0.02255q-0.02899 0.0161-0.0467 0.04348-0.01611 0.02738-0.01611 0.06925 0 0.06442 0.0306 0.09985 0.03221 0.03543 0.08214 0.03543 0.06764 0 0.10468-0.03221t0.05154-0.07086z"/>
<path d="m-33.793 49.946h0.08214l0.02094 0.08535h0.0048q0.02255-0.0467 0.05798-0.07247 0.03704-0.02738 0.08858-0.02738 0.03704 0 0.08375 0.01449l-0.02255 0.11756q-0.04187-0.01449-0.07408-0.01449-0.05154 0-0.08374 0.0306-0.03221 0.02899-0.04187 0.07891v0.59265h-0.11595z"/>
<path d="m-33.153 50.467 0.03382 0.15622h0.0081l0.02416-0.15622 0.1224-0.52018h0.11756l-0.19165 0.7231q-0.02255 0.08696-0.04509 0.16266-0.02255 0.07569-0.04992 0.13045-0.02577 0.05637-0.05959 0.08697-0.03221 0.03221-0.0773 0.03221t-0.07891-0.01449l0.01933-0.10951q0.02255 0.0081 0.04509 0.0032 0.02255-0.0048 0.04187-0.02738 0.02094-0.02255 0.03704-0.06764 0.01772-0.04348 0.0306-0.11434l-0.2609-0.80524h0.13206z"/>
</g>
<path d="m-435.92-23.597c0.28617-0.34918 0.57227-0.69834 0.85837-1.0475 0.42677 0.47526 0.85355 0.95052 1.2803 1.4258 0.76622 0.0048 1.5325 0.01002 2.2987 0.01443-0.82927-0.91657-1.6586-1.8331-2.4878-2.7497 0.40254-0.45586 0.80503-0.91173 1.2076-1.3676 0.78562 0.91658 1.5713 1.8332 2.3569 2.7497-4e-3 -0.87778-8e-3 -1.7556-0.0161-2.6333-0.40253-0.45101-0.80501-0.90202-1.2075-1.353 0.28858-0.42545 0.99829-0.86377 0.3475-1.2606-1.4591-1.6118-2.9183-3.2236-4.3774-4.8354-3.0679-0.01042-6.1393 0.04092-9.205-0.0084-0.72986-0.06429-1.6392-0.29547-1.8065-1.1337-0.35271-1.09 0.84574-2.3762 1.9465-1.8649 0.76081 0.14726 0.44105 1.6835-0.23166 1.1743 0.69856-1.0262-1.2808-0.90972-0.72049 0.09824 0.38397 0.88195 1.783 1.0275 2.3349 0.22513 0.57404-0.92504-0.20641-1.9788-1.0842-2.3446-0.87836-0.41949-1.9686-0.31147-2.7028 0.34337-1.0973 0.83626-1.6281 2.4707-0.91191 3.7193 0.4168 0.93386 1.3405 1.5318 2.3429 1.6481 1.343 0.16782 2.7026 0.06445 4.0539 0.09323h5.3734c1.0184 1.13 2.0368 2.2599 3.0553 3.3899-0.91656 1.0136-1.8331 2.0271-2.7497 3.0407-0.66422-0.85695-1.6664-1.5082-2.0708-2.5299-0.32706-1.1972 1.4194-2.1305 2.2518-1.2247 0.79933 0.44227-0.0473 1.8554-0.62433 1.0813 0.46733-0.15836 0.67752-0.90508-0.0577-0.86727-0.86169 0.32798-0.49311 1.6295 0.25772 1.8808 0.71628 0.34674 1.6137-0.30285 1.5227-1.0869 0.0733-1.1334-0.75524-2.3676-1.9525-2.4204-1.2813-0.24958-2.727 0.4999-3.0402 1.8142-0.43151 1.1314 0.27896 2.2662 1.0551 3.0447 0.91076 0.98537 1.8001 1.9916 2.7018 2.985z" fill="#f00"/>
<path d="m-428.86-22.458c8e-3 -2.1947 0.012-4.3894 0.0201-6.5841-1.356-1.553-2.7839-3.046-4.0921-4.6391-0.4374-0.54095-0.77164-1.181-0.74606-1.8954-0.036-1.3281 0.79082-2.6298 2.0264-3.1348 0.95151-0.42136 2.0903-0.46194 3.022 0.03768 1.2998 0.66198 1.9155 2.4493 1.2087 3.7417-0.54185 0.79964-1.9325 0.78325-2.3809-0.10621-0.43247-0.56653-0.40691-1.7268 0.41575-1.8879 0.66914-0.01363 0.83223 0.96617 0.0962 1.0053-0.16353 0.63656 1.1345 0.49025 1.0924-0.18221 0.16593-0.92802-0.8623-1.6839-1.7291-1.5091-0.97624 0.09675-1.834 1.1261-1.4963 2.1064 0.35552 0.96342 1.2138 1.6073 1.8524 2.3761 1.0266 1.1181 2.05 2.2391 3.0765 3.3574-8e-3 2.445-0.012 4.89-0.0201 7.335-0.78189-0.0068-1.5639-0.01403-2.3458-0.02044z"/>
<path d="m-429.09-21.883-6.584 0.02044c-1.5531-1.356-3.0461-2.7839-4.6392-4.092-0.54093-0.43739-1.181-0.77164-1.8954-0.74605-1.3281-0.03447-2.6298 0.79084-3.1348 2.0263-0.42133 0.95153-0.46193 2.0903 0.036 3.0221 0.66201 1.2998 2.4493 1.9155 3.7417 1.2087 0.79964-0.54184 0.78325-1.9325-0.10621-2.381-0.56654-0.43248-1.7268-0.40688-1.8879 0.41576-0.012 0.66918 0.96618 0.83223 1.0053 0.09607 0.63656-0.16373 0.49027 1.1345-0.18236 1.0924-0.92803 0.16585-1.6839-0.86229-1.5092-1.7291 0.0966-0.97624 1.1261-1.834 2.1064-1.4963 0.96341 0.35556 1.6073 1.2139 2.376 1.8524 1.1181 1.0266 2.2391 2.05 3.3574 3.0765l9.8442-0.02044c-1.143-0.9713-1.4343-1.4219-2.5296-2.3458z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 48 KiB

View file

@ -0,0 +1,128 @@
/*
* This section around grayOut came from here:
* http://www.codingforums.com/archive/index.php/t-151720.html
* Assumed public domain
*
* Init like this in your main html script, this also reapplies the gray
*
* lws_gray_out(true,{'zindex':'499'});
*
* To remove the gray
*
* lws_gray_out(false);
*
*/
function gsize(ptype)
{
var h = document.compatMode === "CSS1Compat" &&
!window.opera ?
document.documentElement.clientHeight :
document.body.clientHeight;
var w = document.compatMode === "CSS1Compat" &&
!window.opera ?
document.documentElement.clientWidth :
document.body.clientWidth;
var pageWidth, pageHeight, t;
if (document.body &&
(document.body.scrollWidth || document.body.scrollHeight)) {
t = document.body.scrollWidth;
pageWidth = (w > t) ? ("" + w + "px") : ("" + (t) + "px");
t = document.body.scrollHeight;
pageHeight = (h > t) ? ("" + h + "px") : ("" + (t) + "px");
} else if (document.body.offsetWidth) {
t = document.body.offsetWidth;
pageWidth = (w > t) ? ("" + w + "px") : ("" + (t) + "px");
t = document.body.offsetHeight;
pageHeight =(h > t) ? ("" + h + "px") : ("" + (t) + "px");
} else {
pageWidth = "100%";
pageHeight = "100%";
}
return (ptype === 1) ? pageWidth : pageHeight;
}
function addEvent( obj, type, fn ) {
if ( obj.attachEvent ) {
obj["e" + type + fn] = fn;
obj[type+fn] = function() { obj["e" + type + fn]( window.event );};
obj.attachEvent("on" + type, obj[type + fn]);
} else
obj.addEventListener(type, fn, false);
}
function removeEvent( obj, type, fn ) {
if ( obj.detachEvent ) {
obj.detachEvent("on" + type, obj[type + fn]);
obj[type + fn] = null;
} else
obj.removeEventListener(type, fn, false);
}
function lws_gray_out(vis, _options) {
var options = _options || {};
var zindex = options.zindex || 50;
var opacity = options.opacity || 70;
var opaque = (opacity / 100);
var bgcolor = options.bgcolor || "#000000";
var dark = document.getElementById("darkenScreenObject");
if (!dark) {
var tbody = document.getElementsByTagName("body")[0];
var tnode = document.createElement("div");
tnode.style.position = "absolute";
tnode.style.top = "0px";
tnode.style.left = "0px";
tnode.style.overflow = "hidden";
tnode.style.display ="none";
tnode.id = "darkenScreenObject";
tbody.appendChild(tnode);
dark = document.getElementById("darkenScreenObject");
}
if (vis) {
dark.style.opacity = opaque;
dark.style.MozOpacity = opaque;
// dark.style.filter ='alpha(opacity='+opacity+')';
dark.style.zIndex = zindex;
dark.style.backgroundColor = bgcolor;
dark.style.width = gsize(1);
dark.style.height = gsize(0);
dark.style.display = "block";
addEvent(window, "resize",
function() {
dark.style.height = gsize(0);
dark.style.width = gsize(1);
}
);
} else {
dark.style.display = "none";
removeEvent(window, "resize",
function() {
dark.style.height = gsize(0);
dark.style.width = gsize(1);
}
);
}
}
/*
* end of grayOut related stuff
*/
function new_ws(urlpath, protocol)
{
if (typeof MozWebSocket != "undefined")
return new MozWebSocket(urlpath, protocol);
return new WebSocket(urlpath, protocol);
}
function lws_san(s)
{
if (s.search("<") !== -1)
return "invalid string";
return s;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

View file

@ -0,0 +1,144 @@
.body { font-size: 12px }
.gstitle { font-size: 18px }
.group1 {
vertical-align:middle;
text-align:center;
background:#f0f0e0;
padding:12px;
border-radius:10px;
}
.group2 {
display:block;
vertical-align:middle;
font-size: 22px;
text-align:center;
margin:auto;
align:center;
background-color: rgba(255, 255, 255, 0.8);
padding:12px;
border-radius:10px;
}
body {
background-color: rgba(205, 205, 205, 1);
}
div.lwsgs {
z-index: 3;
text-align:right;
background-color: rgba(255, 255, 255, 0.8);
}
table.lwsgs {
width:100%;
height:100%;
transition: max-height 2s;
}
table.c100 {
text-align:center;
width:100%;
}
table.r {
vertical-align:top;
text-align:right;
}
table.l {
vertical-align:top;
text-align:left;
}
table.fixed {
table-layout: fixed;
}
td.logo {
vertical-align:top;
text-align:left;
width:200px
}
td.rlogo {
vertical-align:top;
text-align:right
}
td.lwsgs {
vertical-align:top;
float:right;
}
td.h99 {
height:99%;
vertical-align:middle;
}
td.c {
margin:auto;
align:center
}
td.tac {
text-align:center
}
td.ava {
display:inline-block;
vertical-align:top;
word-wrap:break-word;
}
iframe.hidden {
display:none;
}
div.hidden {
display:none;
}
div.hiddenr {
display:none;
text-align:right;
}
input {
margin: 2px;
padding: 2px;
}
input.em {
margin: 4px;
font-weight:bold;
}
input.wide {
margin: 6px;
padding: 6px;
}
input.hidden {
display: none;
}
form.r {
text-align:right;
}
span.bad {
color: red;
}
span.small {
font-size:8pt;
}
img.av {
width: 64px;
height: 64px;
}
.green {
color: green;
}

View file

@ -0,0 +1,637 @@
<!-- lwsgs rewrites the below $vars $v $v into the correct values on the fly -->
var lwsgs_user = "$lwsgs_user";
var lwsgs_auth = "$lwsgs_auth";
var lwsgs_email = "$lwsgs_email";
var lwsgs_html = '\
<div id="dlogin" class="hidden"> \
<form action="lwsgs-login" method="post"> \
<input type="hidden" name="admin" value="needadmin/admin-login.html"> \
<input type="hidden" name="good" value="index.html"> \
<input type="hidden" name="bad" value="failed-login.html"> \
<input type="hidden" name="forgot-good" value="sent-forgot-ok.html"> \
<input type="hidden" name="forgot-bad" value="sent-forgot-fail.html">\
<input type="hidden" name="forgot-post-good" value="post-forgot-ok.html">\
<input type="hidden" name="forgot-post-bad" value="post-forgot-fail.html">\
<table class="r">\
<tr>\
<td>User Name\
<input type="text" size="10" id="username" name="username"></td>\
<td>Password\
<input type="password" id="password" size="10" name="password"><div id="pw1"></div></td>\
</tr><tr>\
<td colspan="2" class="c">\
<input type="submit" id="login" name="login" value="Login" class="em">\
&nbsp;<input type="submit" id="forgot" name="forgot" value="Forgot password">\
&nbsp;<input id="doreg" type="button" value="Sign up"></td>\
</tr>\
</table>\
</form>\
</div>\
\
<div id="dlogout" class="hiddenr">\
<form action="lwsgs-logout" method="post" class="r">\
<input type="hidden" name="good" value="index.html">\
<table class="r">\
<tr><td><table><tr><td><span id=grav></span></td></tr><tr><td>\
<a href="#" id="clink">\
<span id="curuser"></span></a></td></tr></table></td>\
<td class="tac"><input type="submit" name="logout" value="Logout"></td>\
</tr></table></td></tr>\
</table>\
</form></div>\
\
<div id="dregister" class="hidden">\
<form action="lwsgs-login" method="post">\
<input type="hidden" name="admin" value="needadmin/admin-login.html">\
<input type="hidden" name="good" value="successful-login.html">\
<input type="hidden" name="bad" value="failed-login.html">\
<input type="hidden" name="reg-good" value="post-register-ok.html">\
<input type="hidden" name="reg-bad" value="post-register-fail.html">\
<input type="hidden" name="forgot-good" value="sent-forgot-ok.html">\
<input type="hidden" name="forgot-bad" value="sent-forgot-fail.html">\
<input type="hidden" name="forgot-post-good" value="post-forgot-ok.html">\
<input type="hidden" name="forgot-post-bad" value="post-forgot-fail.html">\
<table class="l">\
<tr>\
<td colspan=2 align=center>\
<span id="curuser"></span>\
<b>Please enter your details to register</b>:\
</td>\
</tr>\
<tr><td align=right>\
User Name:</td>\
<td><input type="text" size="10" id="rusername" name="username" &nbsp;<span id=uchk></span></td>\
</tr>\
<tr>\
<td align=right>Password:</td>\
<td><input type="password" size="10" id="rpassword" name="password">&nbsp;<span id="rpw1"></span></td>\
</tr>\
<tr>\
</tr>\
<tr>\
<td align=right><span id="pw2">Password (again):</span></td>\
<td><input type="password" size="10" id="password2" name="password2">&nbsp;<span id="match"></span></td>\
</tr>\
<tr>\
<td align=right>Email:</td>\
<td><input type="email" size="10" id="email" name="email"\
placeholder="me@example.com" &nbsp;<span id=echk></span></td>\
</tr>\
<tr>\
<td colspan=2 align=center>\
<input type="submit" id="register" name="register" value="Register" >\
<input type="submit" id="rforgot" name="forgot" value="Forgot Password" class="hidden">\
<input type="button" id="cancel" name="cancel" value="Cancel">\
</td>\
</tr>\
</table>\
</form>\
</div>\
\
<div id="dchange" class="hidden">\
<form action="lwsgs-change" method="post">\
<input type="hidden" id="cusername" name="username">\
<input type="hidden" name="admin" value="needadmin/admin-login.html">\
<input type="hidden" name="good" value="index.html">\
<input type="hidden" name="bad" value="failed-login.html">\
<input type="hidden" name="reg-good" value="post-register-ok.html">\
<input type="hidden" name="reg-bad" value="post-register-fail.html">\
<input type="hidden" name="forgot-good" value="sent-forgot-ok.html">\
<input type="hidden" name="forgot-bad" value="sent-forgot-fail.html">\
<input type="hidden" name="forgot-post-good" value="post-forgot-ok.html">\
<input type="hidden" name="forgot-post-bad" value="post-forgot-fail.html">\
<table class="l">\
<tr>\
<td colspan=2 align=center>\
<span id="ccuruser"></span>\
<b>Please enter your details to change</b>:\
</td>\
</tr>\
<tr><td align=right id="ccurpw_name">\
Current Password:</td>\
<td><input type="password" size="10" id="ccurpw" name="curpw"\
>&nbsp;<span id=cuchk></span></td>\
</tr>\
<tr>\
<td align=right>Password:</td>\
<td><input type="password" size="10" id="cpassword" name="password"\
&nbsp;<span id="cpw1"></span></td>\
</tr>\
<tr>\
<td align=right><span id="pw2">Password (again)</span></td>\
<td><input type="password" size="10" id="cpassword2" name="password2"\
>&nbsp;<span id="cmatch"></span></td>\
</tr>\
<!-- not supported yet\
<tr>\
<td align=right id="cemail_name">Email:</td>\
<td><input type="email" size="10" id="cemail" name="email"\
placeholder="?" \
&nbsp;<span id=cechk></span></td>\
</tr> -->\
<tr>\
<td colspan=2 align=center>\
<input type="submit" id="change" name="change"\
value="Change" class="wide">\
<input type="submit" id="cforgot" name="forgot"\
value="Forgot Password" class="wide hidden">\
<input type="button" id="cancel2" name="cancel"\
value="Cancel" class="wide">\
</td>\
</tr>\
<tr>\
<td colspan=2>\
<input type="checkbox" id="showdel" name="showdel"\
> Show Delete&nbsp;\
<input type="submit" id="delete" name="delete" \
value="Delete Account" class="wide hidden">\
</td>\
</tr>\
</table>\
</form>\
</div>\
\
<div id="dadmin" class="hidden">\
Admin settings TBD\
</div>\
';
/*-- this came from
-- https://raw.githubusercontent.com/blueimp/JavaScript-MD5/master/js/md5.min.js
-- under MIT license */
!function(n){"use strict";function t(n,t){var r=(65535&n)+(65535&t),e=(n>>16)+(t>>16)+(r>>16);return e<<16|65535&r}function r(n,t){return n<<t|n>>>32-t}function e(n,e,o,u,c,f){return t(r(t(t(e,n),t(u,f)),c),o)}function o(n,t,r,o,u,c,f){return e(t&r|~t&o,n,t,u,c,f)}function u(n,t,r,o,u,c,f){return e(t&o|r&~o,n,t,u,c,f)}function c(n,t,r,o,u,c,f){return e(t^r^o,n,t,u,c,f)}function f(n,t,r,o,u,c,f){return e(r^(t|~o),n,t,u,c,f)}function i(n,r){n[r>>5]|=128<<r%32,n[(r+64>>>9<<4)+14]=r;var e,i,a,h,d,l=1732584193,g=-271733879,v=-1732584194,m=271733878;for(e=0;e<n.length;e+=16)i=l,a=g,h=v,d=m,l=o(l,g,v,m,n[e],7,-680876936),m=o(m,l,g,v,n[e+1],12,-389564586),v=o(v,m,l,g,n[e+2],17,606105819),g=o(g,v,m,l,n[e+3],22,-1044525330),l=o(l,g,v,m,n[e+4],7,-176418897),m=o(m,l,g,v,n[e+5],12,1200080426),v=o(v,m,l,g,n[e+6],17,-1473231341),g=o(g,v,m,l,n[e+7],22,-45705983),l=o(l,g,v,m,n[e+8],7,1770035416),m=o(m,l,g,v,n[e+9],12,-1958414417),v=o(v,m,l,g,n[e+10],17,-42063),g=o(g,v,m,l,n[e+11],22,-1990404162),l=o(l,g,v,m,n[e+12],7,1804603682),m=o(m,l,g,v,n[e+13],12,-40341101),v=o(v,m,l,g,n[e+14],17,-1502002290),g=o(g,v,m,l,n[e+15],22,1236535329),l=u(l,g,v,m,n[e+1],5,-165796510),m=u(m,l,g,v,n[e+6],9,-1069501632),v=u(v,m,l,g,n[e+11],14,643717713),g=u(g,v,m,l,n[e],20,-373897302),l=u(l,g,v,m,n[e+5],5,-701558691),m=u(m,l,g,v,n[e+10],9,38016083),v=u(v,m,l,g,n[e+15],14,-660478335),g=u(g,v,m,l,n[e+4],20,-405537848),l=u(l,g,v,m,n[e+9],5,568446438),m=u(m,l,g,v,n[e+14],9,-1019803690),v=u(v,m,l,g,n[e+3],14,-187363961),g=u(g,v,m,l,n[e+8],20,1163531501),l=u(l,g,v,m,n[e+13],5,-1444681467),m=u(m,l,g,v,n[e+2],9,-51403784),v=u(v,m,l,g,n[e+7],14,1735328473),g=u(g,v,m,l,n[e+12],20,-1926607734),l=c(l,g,v,m,n[e+5],4,-378558),m=c(m,l,g,v,n[e+8],11,-2022574463),v=c(v,m,l,g,n[e+11],16,1839030562),g=c(g,v,m,l,n[e+14],23,-35309556),l=c(l,g,v,m,n[e+1],4,-1530992060),m=c(m,l,g,v,n[e+4],11,1272893353),v=c(v,m,l,g,n[e+7],16,-155497632),g=c(g,v,m,l,n[e+10],23,-1094730640),l=c(l,g,v,m,n[e+13],4,681279174),m=c(m,l,g,v,n[e],11,-358537222),v=c(v,m,l,g,n[e+3],16,-722521979),g=c(g,v,m,l,n[e+6],23,76029189),l=c(l,g,v,m,n[e+9],4,-640364487),m=c(m,l,g,v,n[e+12],11,-421815835),v=c(v,m,l,g,n[e+15],16,530742520),g=c(g,v,m,l,n[e+2],23,-995338651),l=f(l,g,v,m,n[e],6,-198630844),m=f(m,l,g,v,n[e+7],10,1126891415),v=f(v,m,l,g,n[e+14],15,-1416354905),g=f(g,v,m,l,n[e+5],21,-57434055),l=f(l,g,v,m,n[e+12],6,1700485571),m=f(m,l,g,v,n[e+3],10,-1894986606),v=f(v,m,l,g,n[e+10],15,-1051523),g=f(g,v,m,l,n[e+1],21,-2054922799),l=f(l,g,v,m,n[e+8],6,1873313359),m=f(m,l,g,v,n[e+15],10,-30611744),v=f(v,m,l,g,n[e+6],15,-1560198380),g=f(g,v,m,l,n[e+13],21,1309151649),l=f(l,g,v,m,n[e+4],6,-145523070),m=f(m,l,g,v,n[e+11],10,-1120210379),v=f(v,m,l,g,n[e+2],15,718787259),g=f(g,v,m,l,n[e+9],21,-343485551),l=t(l,i),g=t(g,a),v=t(v,h),m=t(m,d);return[l,g,v,m]}function a(n){var t,r="";for(t=0;t<32*n.length;t+=8)r+=String.fromCharCode(n[t>>5]>>>t%32&255);return r}function h(n){var t,r=[];for(r[(n.length>>2)-1]=void 0,t=0;t<r.length;t+=1)r[t]=0;for(t=0;t<8*n.length;t+=8)r[t>>5]|=(255&n.charCodeAt(t/8))<<t%32;return r}function d(n){return a(i(h(n),8*n.length))}function l(n,t){var r,e,o=h(n),u=[],c=[];for(u[15]=c[15]=void 0,o.length>16&&(o=i(o,8*n.length)),r=0;16>r;r+=1)u[r]=909522486^o[r],c[r]=1549556828^o[r];return e=i(u.concat(h(t)),512+8*t.length),a(i(c.concat(e),640))}function g(n){var t,r,e="0123456789abcdef",o="";for(r=0;r<n.length;r+=1)t=n.charCodeAt(r),o+=e.charAt(t>>>4&15)+e.charAt(15&t);return o}function v(n){return unescape(encodeURIComponent(n))}function m(n){return d(v(n))}function p(n){return g(m(n))}function s(n,t){return l(v(n),v(t))}function C(n,t){return g(s(n,t))}function A(n,t,r){return t?r?s(t,n):C(t,n):r?m(n):p(n)}"function"==typeof define&&define.amd?define(function(){return A}):"object"==typeof module&&module.exports?module.exports=A:n.md5=A}(this);
if (lwsgs_user.substring(0, 1) == "$") {
alert("lwsgs.js: lws generic sessions misconfigured and not providing vars");
}
function lwsgs_san(s)
{
if (s.search("<") != -1)
return "invalid string";
return s;
}
function lwsgs_update()
{
var en_login = 1, en_forgot = 1;
if (document.getElementById('password').value.length &&
document.getElementById('password').value.length < 8)
en_login = 0;
if (!document.getElementById('username').value ||
!document.getElementById('password').value)
en_login = 0;
if (!document.getElementById('username').value ||
document.getElementById('password').value)
en_forgot = 0;
document.getElementById('login').disabled = !en_login;
document.getElementById('forgot').disabled = !en_forgot;
if (lwsgs_user)
document.getElementById("curuser").innerHTML = lwsgs_san(lwsgs_user);
if (lwsgs_user === "")
document.getElementById("dlogin").style.display = "inline";
else
document.getElementById("dlogout").style.display = "inline";
}
function lwsgs_open_registration()
{
document.getElementById("dadmin").style.display = "none";
document.getElementById("dlogin").style.display = "none";
document.getElementById("dlogout").style.display = "none";
document.getElementById("dchange").style.display = "none";
document.getElementById("dregister").style.display = "inline";
}
function lwsgs_cancel_registration()
{
document.getElementById("dadmin").style.display = "none";
document.getElementById("dregister").style.display = "none";
document.getElementById("dchange").style.display = "none";
if (lwsgs_user === "")
document.getElementById("dlogin").style.display = "inline";
else
document.getElementById("dlogout").style.display = "inline";
}
function lwsgs_select_change()
{
document.getElementById("dlogin").style.display = "none";
document.getElementById("dlogout").style.display = "none";
document.getElementById("dregister").style.display = "none";
if (lwsgs_auth & 2) {
document.getElementById("dadmin").style.display = "inline";
document.getElementById("dchange").style.display = "none";
} else {
document.getElementById("dadmin").style.display = "none";
document.getElementById("dchange").style.display = "inline";
}
event.preventDefault()
}
var lwsgs_user_check = '0';
var lwsgs_email_check = '0';
function lwsgs_rupdate()
{
var en_register = 1, en_forgot = 0;
if (document.getElementById('rpassword').value ==
document.getElementById('password2').value) {
if (document.getElementById('rpassword').value.length)
document.getElementById('match').innerHTML =
"<b class=\"green\">\u2713</b>";
else
document.getElementById('match').innerHTML = "";
document.getElementById('pw2').style = "";
} else {
if (document.getElementById('password2').value ||
document.getElementById('email').value) { // ie, he is filling in "register" path and cares
document.getElementById('match').innerHTML =
"<span class=\"bad\">\u2718 <b>Passwords do not match</b></span>";
} else
document.getElementById('match').innerHTML =
"<span class=\"bad\">\u2718 Passwords do not match</span>";
en_register = 0;
}
if (document.getElementById('rpassword').value.length &&
document.getElementById('rpassword').value.length < 8) {
en_register = 0;
document.getElementById('rpw1').innerHTML = "Need 8 chars";
} else
if (document.getElementById('rpassword').value.length)
document.getElementById('rpw1').innerHTML = "<b class=\"green\">\u2713</b>";
else
document.getElementById('rpw1').innerHTML = "";
if (!document.getElementById('rpassword').value ||
!document.getElementById('password2').value ||
!document.getElementById('rusername').value ||
!document.getElementById('email').value ||
lwsgs_email_check === '1'||
lwsgs_user_check === '1')
en_register = 0;
document.getElementById('register').disabled = !en_register;
document.getElementById('rpassword').disabled = lwsgs_user_check === '1';
document.getElementById('password2').disabled = lwsgs_user_check === '1';
document.getElementById('email').disabled = lwsgs_user_check === '1';
if (lwsgs_user_check === '0') {
var uc = document.getElementById('uchk');
if (uc) {
if (document.getElementById('rusername').value)
uc.innerHTML = "<b class=\"green\">\u2713</b>";
else
uc.innerHTML = "";
}
} else {
if (document.getElementById('uchk'))
ocument.getElementById('uchk').innerHTML = "<b class=\"red\">\u2718 Already registered</b>";
en_forgot = 1;
}
if (lwsgs_email_check === '0') {
var ec = document.getElementById('echk');
if (ec) {
if (document.getElementById('email').value)
ec.innerHTML = "<b class=\"green\">\u2713</b>";
else
ec.innerHTML = "";
}
} else {
if (document.getElementById('echk'))
document.getElementById('echk').innerHTML = "<b class=\"red\">\u2718 Already registered</b>";
en_forgot = 1;
}
if (en_forgot)
document.getElementById('rforgot').style.display = "inline";
else
document.getElementById('rforgot').style.display = "none";
if (lwsgs_user_check === '1')
op = '0.5';
else
op = '1.0';
document.getElementById('rpassword').style.opacity = op;
document.getElementById('password2').style.opacity = op;
document.getElementById('email').style.opacity = op;
}
function lwsgs_cupdate()
{
var en_change = 1, en_forgot = 1, pwok = 1;
if (lwsgs_auth & 8) {
document.getElementById('ccurpw').style.display = "none";
document.getElementById('ccurpw_name').style.display = "none";
} else {
if (!document.getElementById('ccurpw').value ||
document.getElementById('ccurpw').value.length < 8) {
en_change = 0;
pwok = 0;
document.getElementById('cuchk').innerHTML = "<b class=\"red\">\u2718</b>";
} else {
en_forgot = 0;
document.getElementById('cuchk').innerHTML = "";
}
document.getElementById('ccurpw').style.display = "inline";
document.getElementById('ccurpw_name').style.display = "inline";
}
if (document.getElementById('cpassword').value ==
document.getElementById('cpassword2').value) {
if (document.getElementById('cpassword').value.length)
document.getElementById('cmatch').innerHTML = "<b class=\"green\">\u2713</b>";
else
document.getElementById('cmatch').innerHTML = "";
document.getElementById('pw2').style = "";
} else {
if (document.getElementById('cpassword2').value //||
//document.getElementById('cemail').value
) { // ie, he is filling in "register" path and cares
document.getElementById('cmatch').innerHTML =
"<span class=\"red\">\u2718 <b>Passwords do not match</b></span>";
} else
document.getElementById('cmatch').innerHTML = "<span class=\"red\">\u2718 Passwords do not match</span>";
en_change = 0;
}
if (document.getElementById('cpassword').value.length &&
document.getElementById('cpassword').value.length < 8) {
en_change = 0;
document.getElementById('cpw1').innerHTML = "Need 8 chars";
} else {
var cpw = document.getElementById('cpw1');
if (cpw) {
if (document.getElementById('cpassword').value.length)
cpw.innerHTML = "<b class=\"green\">\u2713</b>";
else
cpw.innerHTML = "";
}
}
if (!document.getElementById('cpassword').value ||
!document.getElementById('cpassword2').value ||
pwok === 0)
en_change = 0;
if (document.getElementById('showdel').checked)
document.getElementById('delete').style.display = "inline";
else
document.getElementById('delete').style.display = "none";
document.getElementById('change').disabled = !en_change;
document.getElementById('cpassword').disabled = pwok === 0;
document.getElementById('cpassword2').disabled = pwok === 0;
document.getElementById('showdel').disabled = pwok === 0;
document.getElementById('delete').disabled = pwok === 0;
//document.getElementById('cemail').disabled = pwok === 0;
/*
if (lwsgs_auth & 8) {
document.getElementById('cemail').style.display = "none";
document.getElementById('cemail_name').style.display = "none";
} else {
document.getElementById('cemail').style.display = "inline";
document.getElementById('cemail_name').style.display = "inline";
if (lwsgs_email_check === '0' &&
document.getElementById('cemail').value != lwsgs_email) {
if (document.getElementById('cemail').value)
document.getElementById('cechk').innerHTML = "<b style=\"color:green\">\u2713</b>";
else
document.getElementById('cechk').innerHTML = "";
} else {
document.getElementById('cechk').innerHTML = "<b style=\"color:red\">\u2718 Already registered</b>";
en_forgot = 1;
}
} */
if (lwsgs_auth & 8)
en_forgot = 0;
if (en_forgot)
document.getElementById('cforgot').style.display = "inline";
else
document.getElementById('cforgot').style.display = "none";
if (pwok === 0)
op = '0.5';
else
op = '1.0';
document.getElementById('cpassword').style.opacity = op;
document.getElementById('cpassword2').style.opacity = op;
// document.getElementById('cemail').style.opacity = op;
}
function lwsgs_check_user()
{
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
lwsgs_user_check = xmlHttp.responseText;
lwsgs_rupdate();
}
}
xmlHttp.open("GET", "lwsgs-check/username="+document.getElementById('rusername').value, true);
xmlHttp.send(null);
}
function lwsgs_check_email(id)
{
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
lwsgs_email_check = xmlHttp.responseText;
lwsgs_rupdate();
}
}
xmlHttp.open("GET", "lwsgs-check/email="+document.getElementById(id).value, true);
xmlHttp.send(null);
}
function rupdate_user()
{
lwsgs_rupdate();
lwsgs_check_user();
}
function rupdate_email()
{
lwsgs_rupdate();
lwsgs_check_email('email');
}
function cupdate_email()
{
lwsgs_cupdate();
lwsgs_check_email('cemail');
}
function lwsgs_initial()
{
document.getElementById('lwsgs').innerHTML = lwsgs_html;
if (lwsgs_user) {
document.getElementById("curuser").innerHTML =
"currently logged in as " + lwsgs_san(lwsgs_user) + "</br>";
document.getElementById("ccuruser").innerHTML =
"<span class=\"gstitle\">Login settings for " +
lwsgs_san(lwsgs_user) + "</span></br>";
}
document.getElementById('username').oninput = lwsgs_update;
document.getElementById('username').onchange = lwsgs_update;
document.getElementById('password').oninput = lwsgs_update;
document.getElementById('password').onchange = lwsgs_update;
document.getElementById('doreg').onclick = lwsgs_open_registration;
document.getElementById('clink').onclick = lwsgs_select_change;
document.getElementById('cancel').onclick =lwsgs_cancel_registration;
document.getElementById('cancel2').onclick =lwsgs_cancel_registration;
document.getElementById('rpassword').oninput = lwsgs_rupdate;
document.getElementById('password2').oninput = lwsgs_rupdate;
document.getElementById('rusername').oninput = rupdate_user;
document.getElementById('email').oninput = rupdate_email;
document.getElementById('ccurpw').oninput = lwsgs_cupdate;
document.getElementById('cpassword').oninput = lwsgs_cupdate;
document.getElementById('cpassword2').oninput = lwsgs_cupdate;
<!-- document.getElementById('cemail').oninput = cupdate_email;-->
document.getElementById('showdel').onchange = lwsgs_cupdate;
if (lwsgs_email)
document.getElementById('grav').innerHTML =
"<img class='av' " +
"src=\"https://www.gravatar.com/avatar/" +
md5(lwsgs_email) +
"?d=identicon\">";
//if (lwsgs_email)
//document.getElementById('cemail').placeholder = lwsgs_email;
document.getElementById('cusername').value = lwsgs_user;
lwsgs_update();
lwsgs_cupdate();
}
window.addEventListener("load", function() {
lwsgs_initial();
document.getElementById("nolog").style.display = !!lwsgs_user ? "none" : "inline-block";
document.getElementById("logged").style.display = !lwsgs_user ? "none" : "inline-block";
document.getElementById("msg").onkeyup = mupd;
document.getElementById("msg").onchange = mupd;
var ws;
function mb_format(s)
{
var r = "", n, wos = 0;
for (n = 0; n < s.length; n++) {
if (s[n] == ' ')
wos = 0;
else {
wos++;
if (wos === 40) {
wos = 0;
r = r + ' ';
}
}
if (s[n] == '<') {
r = r + "&lt;";
continue;
}
if (s[n] == '\n') {
r = r + "<br>";
continue;
}
r = r + s[n];
}
return r;
}
function add_div(n, m)
{
var q = document.getElementById(n);
var d = new Date(m.time * 1000), s = d.toTimeString(), t;
t = s.indexOf('(');
if (t)
s = s.substring(0, t);
q.innerHTML = "<br><div class=\"group2\"><table class=\"fixed\"><tr><td>" +
"<img class=\"av\" src=\"https://www.gravatar.com/avatar/" + md5(m.email) +
"?d=identicon\"><br>" +
"<b>" + lwsgs_san(m.username) + "</b><br>" +
"<span class=\"small\">" + d.toDateString() +
"<br>" + s + "</span><br>" +
"IP: " + lwsgs_san(m.ip) +
"</td><td class=\"ava\"><span>" +
mb_format(m.content) +
"</span></td></tr></table></div><br>" + q.innerHTML;
}
function get_appropriate_ws_url()
{
var pcol;
var u = document.URL;
if (u.substring(0, 5) == "https") {
pcol = "wss://";
u = u.substr(8);
} else {
pcol = "ws://";
if (u.substring(0, 4) == "http")
u = u.substr(7);
}
u = u.split('/');
return pcol + u[0] + "/xxx";
}
if (lwsgs_user) {
if (typeof MozWebSocket != "undefined")
ws = new MozWebSocket(get_appropriate_ws_url(),
"protocol-lws-messageboard");
else
ws = new WebSocket(get_appropriate_ws_url(),
"protocol-lws-messageboard");
try {
ws.onopen = function() {
document.getElementById("debug").textContent = "ws opened";
}
ws.onmessage =function got_packet(msg) {
add_div("messages", JSON.parse(msg.data));
}
ws.onclose = function(){
}
} catch(exception) {
alert('<p>Error' + exception);
}
}
function mupd()
{
document.getElementById("send").disabled = !document.getElementById("msg").value;
}
}, false);

View file

@ -0,0 +1,2 @@
!function(n){"use strict";function t(n,t){var r=(65535&n)+(65535&t),e=(n>>16)+(t>>16)+(r>>16);return e<<16|65535&r}function r(n,t){return n<<t|n>>>32-t}function e(n,e,o,u,c,f){return t(r(t(t(e,n),t(u,f)),c),o)}function o(n,t,r,o,u,c,f){return e(t&r|~t&o,n,t,u,c,f)}function u(n,t,r,o,u,c,f){return e(t&o|r&~o,n,t,u,c,f)}function c(n,t,r,o,u,c,f){return e(t^r^o,n,t,u,c,f)}function f(n,t,r,o,u,c,f){return e(r^(t|~o),n,t,u,c,f)}function i(n,r){n[r>>5]|=128<<r%32,n[(r+64>>>9<<4)+14]=r;var e,i,a,h,d,l=1732584193,g=-271733879,v=-1732584194,m=271733878;for(e=0;e<n.length;e+=16)i=l,a=g,h=v,d=m,l=o(l,g,v,m,n[e],7,-680876936),m=o(m,l,g,v,n[e+1],12,-389564586),v=o(v,m,l,g,n[e+2],17,606105819),g=o(g,v,m,l,n[e+3],22,-1044525330),l=o(l,g,v,m,n[e+4],7,-176418897),m=o(m,l,g,v,n[e+5],12,1200080426),v=o(v,m,l,g,n[e+6],17,-1473231341),g=o(g,v,m,l,n[e+7],22,-45705983),l=o(l,g,v,m,n[e+8],7,1770035416),m=o(m,l,g,v,n[e+9],12,-1958414417),v=o(v,m,l,g,n[e+10],17,-42063),g=o(g,v,m,l,n[e+11],22,-1990404162),l=o(l,g,v,m,n[e+12],7,1804603682),m=o(m,l,g,v,n[e+13],12,-40341101),v=o(v,m,l,g,n[e+14],17,-1502002290),g=o(g,v,m,l,n[e+15],22,1236535329),l=u(l,g,v,m,n[e+1],5,-165796510),m=u(m,l,g,v,n[e+6],9,-1069501632),v=u(v,m,l,g,n[e+11],14,643717713),g=u(g,v,m,l,n[e],20,-373897302),l=u(l,g,v,m,n[e+5],5,-701558691),m=u(m,l,g,v,n[e+10],9,38016083),v=u(v,m,l,g,n[e+15],14,-660478335),g=u(g,v,m,l,n[e+4],20,-405537848),l=u(l,g,v,m,n[e+9],5,568446438),m=u(m,l,g,v,n[e+14],9,-1019803690),v=u(v,m,l,g,n[e+3],14,-187363961),g=u(g,v,m,l,n[e+8],20,1163531501),l=u(l,g,v,m,n[e+13],5,-1444681467),m=u(m,l,g,v,n[e+2],9,-51403784),v=u(v,m,l,g,n[e+7],14,1735328473),g=u(g,v,m,l,n[e+12],20,-1926607734),l=c(l,g,v,m,n[e+5],4,-378558),m=c(m,l,g,v,n[e+8],11,-2022574463),v=c(v,m,l,g,n[e+11],16,1839030562),g=c(g,v,m,l,n[e+14],23,-35309556),l=c(l,g,v,m,n[e+1],4,-1530992060),m=c(m,l,g,v,n[e+4],11,1272893353),v=c(v,m,l,g,n[e+7],16,-155497632),g=c(g,v,m,l,n[e+10],23,-1094730640),l=c(l,g,v,m,n[e+13],4,681279174),m=c(m,l,g,v,n[e],11,-358537222),v=c(v,m,l,g,n[e+3],16,-722521979),g=c(g,v,m,l,n[e+6],23,76029189),l=c(l,g,v,m,n[e+9],4,-640364487),m=c(m,l,g,v,n[e+12],11,-421815835),v=c(v,m,l,g,n[e+15],16,530742520),g=c(g,v,m,l,n[e+2],23,-995338651),l=f(l,g,v,m,n[e],6,-198630844),m=f(m,l,g,v,n[e+7],10,1126891415),v=f(v,m,l,g,n[e+14],15,-1416354905),g=f(g,v,m,l,n[e+5],21,-57434055),l=f(l,g,v,m,n[e+12],6,1700485571),m=f(m,l,g,v,n[e+3],10,-1894986606),v=f(v,m,l,g,n[e+10],15,-1051523),g=f(g,v,m,l,n[e+1],21,-2054922799),l=f(l,g,v,m,n[e+8],6,1873313359),m=f(m,l,g,v,n[e+15],10,-30611744),v=f(v,m,l,g,n[e+6],15,-1560198380),g=f(g,v,m,l,n[e+13],21,1309151649),l=f(l,g,v,m,n[e+4],6,-145523070),m=f(m,l,g,v,n[e+11],10,-1120210379),v=f(v,m,l,g,n[e+2],15,718787259),g=f(g,v,m,l,n[e+9],21,-343485551),l=t(l,i),g=t(g,a),v=t(v,h),m=t(m,d);return[l,g,v,m]}function a(n){var t,r="";for(t=0;t<32*n.length;t+=8)r+=String.fromCharCode(n[t>>5]>>>t%32&255);return r}function h(n){var t,r=[];for(r[(n.length>>2)-1]=void 0,t=0;t<r.length;t+=1)r[t]=0;for(t=0;t<8*n.length;t+=8)r[t>>5]|=(255&n.charCodeAt(t/8))<<t%32;return r}function d(n){return a(i(h(n),8*n.length))}function l(n,t){var r,e,o=h(n),u=[],c=[];for(u[15]=c[15]=void 0,o.length>16&&(o=i(o,8*n.length)),r=0;16>r;r+=1)u[r]=909522486^o[r],c[r]=1549556828^o[r];return e=i(u.concat(h(t)),512+8*t.length),a(i(c.concat(e),640))}function g(n){var t,r,e="0123456789abcdef",o="";for(r=0;r<n.length;r+=1)t=n.charCodeAt(r),o+=e.charAt(t>>>4&15)+e.charAt(15&t);return o}function v(n){return unescape(encodeURIComponent(n))}function m(n){return d(v(n))}function p(n){return g(m(n))}function s(n,t){return l(v(n),v(t))}function C(n,t){return g(s(n,t))}function A(n,t,r){return t?r?s(t,n):C(t,n):r?m(n):p(n)}"function"==typeof define&&define.amd?define(function(){return A}):"object"==typeof module&&module.exports?module.exports=A:n.md5=A}(this);
//# sourceMappingURL=md5.min.js.map

View file

@ -0,0 +1,5 @@
<html>
This is an example destination that will appear after successful Admin login.
This URL cannot be served if you're not logged in as admin.
</html>

View file

@ -0,0 +1,4 @@
<html>
This is an example destination that will appear after successful non-Admin login
</html>

View file

@ -0,0 +1,5 @@
<html>
Sorry, something went wrong.
Click <a href="../">here</a> to continue.
</html>

View file

@ -0,0 +1,6 @@
<html>
This is a one-time password recovery login.
Please click <a href="./">here</a> and click your username at the top to reset your password.
</html>

View file

@ -0,0 +1,27 @@
<html>
<head>
<script src="lwsgs.js" nonce=lwscaro></script>
</head>
<body>
<table>
<tr>
<td colspan=2 align=center>
<img src="lwsgs-logo.png">
</td>
</tr>
<tr>
<td>
Your registration as <span id="u"></span> is accepted,<br>
you will receive an email shortly with instructions<br>
to verify and enable the account for normal use.<br><br>
The link is only valid for an hour, after that if it has<br>
not been verified your account will be deleted.
</td>
</tr>
</table>
</body>
<script nonce=lwscaro>
document.getElementById('u').innerHTML = "<b>" + lwsgs_san(lwsgs_user) + "</b>";
</script>
</html>

View file

@ -0,0 +1,20 @@
<html>
<head>
<script src="lwsgs.js"></script>
</head>
<body>
<table>
<tr>
<td colspan=2 align=center>
<img src="lwsws-logo.png">
</td>
</tr>
<tr>
<td>
Sorry, the link was invalid.
</td>
</tr>
</table>
</body>
</html>

View file

@ -0,0 +1,25 @@
<html>
<head>
<script src="lwsgs.js"></script>
</head>
<body>
<table>
<tr>
<td colspan=2 align=center>
<img src="lwsgs-logo.png">
</td>
</tr>
<tr>
<td>
Thanks for signing up, your registration as <span id="u"></span> is verified.<br>
<br>
Click <a href="/lwsgs">here</a> to continue.
</td>
</tr>
</table>
</body>
<script nonce="lwscaro">
document.getElementById('u').innerHTML = "<b>" + san(lwsgs_user) + "</b>";
</script>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

View file

@ -0,0 +1,5 @@
<html>
Sorry, something went wrong.
Click <a href="../">here</a> to continue.
</html>

View file

@ -0,0 +1,4 @@
An email has been sent to your registered address.
Please follow the instructions to reset your password.

View file

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24.78mm" height="24.78mm" version="1.1" viewBox="0 0 24.780247 24.780247" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="linearGradient955" x1="66.618" x2="82.588" y1="81.176" y2="64.828" gradientTransform="matrix(.82538 0 0 .82538 -392 -92.399)" gradientUnits="userSpaceOnUse">
<stop stop-color="#0aa70b" offset="0"/>
<stop stop-color="#3bff39" offset="1"/>
</linearGradient>
<filter id="filter945" x="-.0516" y="-.0516" width="1.1032" height="1.1032" color-interpolation-filters="sRGB">
<feGaussianBlur stdDeviation="0.58510713"/>
</filter>
</defs>
<g transform="translate(342.15 43.638)">
<circle transform="matrix(.82538 0 0 .82538 -392 -92.399)" cx="75.406" cy="74.089" r="13.607" filter="url(#filter945)" stroke="#000" stroke-linecap="round" stroke-width="1.565"/>
<circle cx="-330.23" cy="-31.716" r="11.231" fill="url(#linearGradient955)" stroke="#000" stroke-linecap="round" stroke-width="1.2917"/>
<g transform="matrix(.70929 0 0 .70929 -99.465 -12.686)" stroke-width=".51676px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal" aria-label="Strict">
<path d="m-330.78-33.775q0 0.73996-0.53676 1.154-0.53676 0.41407-1.4569 0.41407-0.99684 0-1.5336-0.25688v-0.62878q0.34506 0.14569 0.75147 0.23004 0.4064 0.08435 0.80514 0.08435 0.65177 0 0.9815-0.24538 0.32972-0.24921 0.32972-0.69012 0-0.29138-0.11885-0.47542-0.11502-0.18787-0.39107-0.34506-0.27221-0.15719-0.83198-0.35656-0.78213-0.27988-1.1195-0.66328-0.33356-0.3834-0.33356-1.0007 0-0.64794 0.48692-1.0313 0.48691-0.3834 1.2882-0.3834 0.83581 0 1.5374 0.30672l-0.2032 0.56743q-0.69395-0.29138-1.3496-0.29138-0.51759 0-0.80897 0.22237t-0.29138 0.61727q0 0.29138 0.10735 0.47925 0.10735 0.18403 0.36039 0.34123 0.25688 0.15336 0.78214 0.34122 0.88182 0.31439 1.2115 0.67478 0.33356 0.3604 0.33356 0.93549z"/>
<path d="m-328.37-32.732q0.16869 0 0.32589-0.023 0.15719-0.02684 0.24921-0.05368v0.48692q-0.10352 0.04984-0.30672 0.08051-0.19937 0.03451-0.3604 0.03451-1.2192 0-1.2192-1.2844v-2.4998h-0.60194v-0.30672l0.60194-0.26455 0.26838-0.89716h0.36807v0.97384h1.2192v0.49458h-1.2192v2.4729q0 0.37957 0.18019 0.58277 0.1802 0.2032 0.49459 0.2032z"/>
<path d="m-325.04-36.562q0.27989 0 0.50226 0.04601l-0.0882 0.59044q-0.26072-0.05751-0.46008-0.05751-0.50993 0-0.87415 0.41407-0.3604 0.41407-0.3604 1.0313v2.2544h-0.63644v-4.2021h0.52525l0.0729 0.7783h0.0307q0.23388-0.41024 0.5636-0.63261 0.32972-0.22237 0.72462-0.22237z"/>
<path d="m-323.11-32.284h-0.63644v-4.2021h0.63644zm-0.69012-5.3408q0-0.21854 0.10735-0.31822 0.10735-0.10352 0.26838-0.10352 0.15336 0 0.26455 0.10352 0.11118 0.10352 0.11118 0.31822 0 0.2147-0.11118 0.32206-0.11119 0.10352-0.26455 0.10352-0.16103 0-0.26838-0.10352-0.10735-0.10735-0.10735-0.32206z"/>
<path d="m-320.07-32.207q-0.91249 0-1.4147-0.55976-0.49842-0.5636-0.49842-1.5911 0-1.0543 0.50609-1.6294 0.50992-0.5751 1.4492-0.5751 0.30288 0 0.60577 0.06518 0.30288 0.06518 0.47541 0.15336l-0.19553 0.54059q-0.21087-0.08435-0.46008-0.13802-0.24921-0.05751-0.44091-0.05751-1.2806 0-1.2806 1.6333 0 0.77447 0.31055 1.1885 0.31439 0.41407 0.92783 0.41407 0.52526 0 1.0774-0.22621v0.5636q-0.42174 0.21854-1.062 0.21854z"/>
<path d="m-316.65-32.732q0.16869 0 0.32589-0.023 0.15719-0.02684 0.24921-0.05368v0.48692q-0.10352 0.04984-0.30672 0.08051-0.19937 0.03451-0.3604 0.03451-1.2192 0-1.2192-1.2844v-2.4998h-0.60194v-0.30672l0.60194-0.26455 0.26838-0.89716h0.36806v0.97384h1.2192v0.49458h-1.2192v2.4729q0 0.37957 0.1802 0.58277 0.1802 0.2032 0.49459 0.2032z"/>
</g>
<g fill="#fff">
<g transform="matrix(.70929 0 0 .70929 -99.465 -12.686)" stroke-width=".3317px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal" aria-label="Content">
<path d="m-332.67-30.173q-0.5931 0-0.93764 0.39622-0.34208 0.39376-0.34208 1.0804 0 0.70631 0.32977 1.0927 0.33224 0.38392 0.94503 0.38392 0.37653 0 0.85889-0.13536v0.36669q-0.37407 0.14028-0.92288 0.14028-0.7949 0-1.228-0.48236-0.43067-0.48236-0.43067-1.3708 0-0.55619 0.20672-0.97456 0.20919-0.41837 0.60049-0.64478 0.39376-0.22641 0.92533-0.22641 0.56603 0 0.98933 0.20672l-0.1772 0.35931q-0.40852-0.19196-0.81705-0.19196z"/>
<path d="m-328.77-28.248q0 0.65955-0.33224 1.0312-0.33223 0.36915-0.91795 0.36915-0.36177 0-0.64233-0.16981-0.28055-0.16981-0.43313-0.48728-0.15259-0.31747-0.15259-0.74322 0-0.65955 0.32978-1.0262 0.32977-0.36915 0.91549-0.36915 0.56603 0 0.89827 0.37653 0.3347 0.37653 0.3347 1.0189zm-2.0549 0q0 0.51681 0.20672 0.78752 0.20673 0.27071 0.60787 0.27071t0.60787-0.26825q0.20918-0.27071 0.20918-0.78998 0-0.51435-0.20918-0.78014-0.20673-0.26825-0.61279-0.26825-0.40115 0-0.60541 0.26333-0.20426 0.26333-0.20426 0.78506z"/>
<path d="m-326.21-26.897v-1.7449q0-0.32978-0.15012-0.4922-0.15012-0.16243-0.47005-0.16243-0.42329 0-0.62017 0.22887-0.19688 0.22887-0.19688 0.75553v1.4151h-0.40853v-2.6973h0.33223l0.0664 0.36915h0.0197q0.12551-0.19934 0.35192-0.30762 0.22642-0.11075 0.50451-0.11075 0.48728 0 0.73338 0.23626 0.2461 0.2338 0.2461 0.75061v1.7596z"/>
<path d="m-324.09-27.185q0.10828 0 0.20918-0.01477 0.1009-0.01723 0.15997-0.03445v0.31255q-0.0665 0.03199-0.19688 0.05168-0.12797 0.02215-0.23134 0.02215-0.7826 0-0.7826-0.82444v-1.6046h-0.38637v-0.19688l0.38637-0.16981 0.17227-0.57588h0.23626v0.6251h0.7826v0.31747h-0.7826v1.5873q0 0.24364 0.11567 0.37407 0.11566 0.13043 0.31747 0.13043z"/>
<path d="m-322.04-26.848q-0.59802 0-0.94502-0.36423-0.34454-0.36423-0.34454-1.0115 0-0.65217 0.31993-1.0361 0.32239-0.38392 0.86381-0.38392 0.50697 0 0.80229 0.3347 0.29532 0.33224 0.29532 0.87858v0.25841h-1.8581q0.0123 0.47497 0.23872 0.72107 0.22887 0.2461 0.64232 0.2461 0.4356 0 0.86135-0.18212v0.36423q-0.21657 0.09352-0.41099 0.13289-0.19195 0.04184-0.46513 0.04184zm-0.11074-2.4536q-0.32485 0-0.51927 0.21165-0.19196 0.21165-0.22642 0.58572h1.4102q0-0.38638-0.17227-0.59064-0.17227-0.20672-0.4922-0.20672z"/>
<path d="m-318.51-26.897v-1.7449q0-0.32978-0.15012-0.4922-0.15013-0.16243-0.47006-0.16243-0.42329 0-0.62017 0.22887-0.19688 0.22887-0.19688 0.75553v1.4151h-0.40853v-2.6973h0.33224l0.0664 0.36915h0.0197q0.12552-0.19934 0.35193-0.30762 0.22641-0.11075 0.5045-0.11075 0.48728 0 0.73338 0.23626 0.2461 0.2338 0.2461 0.75061v1.7596z"/>
<path d="m-316.4-27.185q0.10829 0 0.20919-0.01477 0.1009-0.01723 0.15996-0.03445v0.31255q-0.0664 0.03199-0.19688 0.05168-0.12797 0.02215-0.23133 0.02215-0.7826 0-0.7826-0.82444v-1.6046h-0.38638v-0.19688l0.38638-0.16981 0.17227-0.57588h0.23625v0.6251h0.7826v0.31747h-0.7826v1.5873q0 0.24364 0.11567 0.37407 0.11567 0.13043 0.31747 0.13043z"/>
</g>
<g transform="matrix(.70929 0 0 .70929 -99.465 -12.686)" stroke-width=".32428px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal" aria-label="Security">
<path d="m-332.03-22.859q0 0.46434-0.33683 0.72417-0.33682 0.25984-0.91423 0.25984-0.62553 0-0.96236-0.1612v-0.39456q0.21653 0.09142 0.47155 0.14435 0.25503 0.05293 0.50524 0.05293 0.409 0 0.61591-0.15398 0.20691-0.15638 0.20691-0.43306 0-0.18285-0.0746-0.29833-0.0722-0.11789-0.2454-0.21653-0.17082-0.09864-0.52208-0.22375-0.4908-0.17563-0.70252-0.41622-0.20931-0.24059-0.20931-0.62794 0-0.4066 0.30555-0.64718t0.80838-0.24059q0.52448 0 0.96476 0.19247l-0.12751 0.35607q-0.43547-0.18285-0.84687-0.18285-0.3248 0-0.50765 0.13954-0.18284 0.13954-0.18284 0.38735 0 0.18285 0.0674 0.30074 0.0674 0.11548 0.22615 0.21412 0.1612 0.09624 0.4908 0.21412 0.55336 0.19728 0.76027 0.42344 0.20931 0.22615 0.20931 0.58704z"/>
<path d="m-330.26-21.875q-0.58463 0-0.92386-0.35607-0.33683-0.35607-0.33683-0.98882 0-0.63756 0.31277-1.0129 0.31517-0.37532 0.84446-0.37532 0.49562 0 0.78432 0.3272 0.28871 0.3248 0.28871 0.8589v0.25262h-1.8164q0.012 0.46434 0.23338 0.70492 0.22374 0.24059 0.62793 0.24059 0.42584 0 0.84206-0.17804v0.35607q-0.21171 0.09142-0.40178 0.12992-0.18766 0.0409-0.45471 0.0409zm-0.10827-2.3987q-0.31757 0-0.50764 0.20691-0.18766 0.20691-0.22134 0.5726h1.3786q0-0.37772-0.16841-0.57741-0.16841-0.2021-0.48118-0.2021z"/>
<path d="m-327.56-21.875q-0.5726 0-0.88777-0.35126-0.31277-0.35366-0.31277-0.99844 0-0.66162 0.31758-1.0225 0.31998-0.36088 0.90942-0.36088 0.19007 0 0.38013 0.0409 0.19007 0.0409 0.29833 0.09624l-0.1227 0.33923q-0.13232-0.05293-0.2887-0.08661-0.15639-0.03609-0.27668-0.03609-0.80357 0-0.80357 1.0249 0 0.48599 0.19488 0.74582 0.19728 0.25984 0.58223 0.25984 0.3296 0 0.67605-0.14195v0.35366q-0.26465 0.13714-0.66643 0.13714z"/>
<path d="m-325.89-24.56v1.7106q0 0.32239 0.14676 0.48118 0.14675 0.15879 0.45952 0.15879 0.41381 0 0.60388-0.22615 0.19247-0.22615 0.19247-0.73861v-1.3858h0.39938v2.6369h-0.32961l-0.0577-0.35367h-0.0217q-0.1227 0.19488-0.34163 0.29833-0.21653 0.10345-0.49561 0.10345-0.48118 0-0.72177-0.22856-0.23818-0.22856-0.23818-0.73139v-1.725z"/>
<path d="m-322.04-24.608q0.17563 0 0.31517 0.02887l-0.0553 0.37051q-0.1636-0.03609-0.2887-0.03609-0.31999 0-0.54855 0.25984-0.22615 0.25984-0.22615 0.64718v1.4147h-0.39938v-2.6369h0.32961l0.0457 0.4884h0.0192q0.14676-0.25743 0.35366-0.39697 0.20691-0.13954 0.45472-0.13954z"/>
<path d="m-320.83-21.923h-0.39938v-2.6369h0.39938zm-0.43306-3.3514q0-0.13714 0.0674-0.19969 0.0674-0.06496 0.16841-0.06496 0.0962 0 0.16601 0.06496 0.0698 0.06496 0.0698 0.19969 0 0.13473-0.0698 0.2021-0.0698 0.06496-0.16601 0.06496-0.10105 0-0.16841-0.06496-0.0674-0.06736-0.0674-0.2021z"/>
<path d="m-319.13-22.205q0.10586 0 0.2045-0.01443 0.0986-0.01684 0.15638-0.03368v0.30555q-0.065 0.03128-0.19247 0.05052-0.1251 0.02165-0.22615 0.02165-0.76507 0-0.76507-0.80597v-1.5686h-0.37773v-0.19247l0.37773-0.16601 0.16841-0.56298h0.23096v0.6111h0.76508v0.31036h-0.76508v1.5518q0 0.23818 0.11308 0.3657t0.31036 0.12751z"/>
<path d="m-318.66-24.56h0.42825l0.57742 1.5037q0.19006 0.51486 0.23577 0.74342h0.0192q0.0313-0.1227 0.12992-0.41862 0.10105-0.29833 0.6544-1.8285h0.42825l-1.1332 3.0025q-0.16841 0.44509-0.39456 0.63034-0.22375 0.18766-0.55095 0.18766-0.18285 0-0.36088-0.0409v-0.31998q0.13232 0.02887 0.29592 0.02887 0.41141 0 0.58704-0.46193l0.14676-0.37532z"/>
</g>
<g transform="matrix(.70929 0 0 .70929 -99.465 -12.686)" stroke-width=".32334px" style="font-feature-settings:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal" aria-label="Policy">
<path d="m-329.37-19.254q0 0.53256-0.36464 0.82043-0.36224 0.28547-1.0387 0.28547h-0.41261v1.3794h-0.40782v-3.5072h0.90919q1.3146 0 1.3146 1.0219zm-1.816 0.75566h0.36703q0.54215 0 0.78445-0.17512 0.24229-0.17512 0.24229-0.56135 0-0.34784-0.2279-0.51817t-0.71008-0.17032h-0.45579z"/>
<path d="m-326.43-18.086q0 0.64291-0.32386 1.0051-0.32385 0.35984-0.89479 0.35984-0.35264 0-0.62612-0.16552t-0.42221-0.47498q-0.14873-0.30946-0.14873-0.72447 0-0.64291 0.32145-1.0003 0.32146-0.35984 0.8924-0.35984 0.55175 0 0.8756 0.36703 0.32626 0.36704 0.32626 0.99315zm-2.0031 0q0 0.50377 0.20151 0.76765t0.59253 0.26388q0.39103 0 0.59254-0.26148 0.2039-0.26388 0.2039-0.77005 0-0.50137-0.2039-0.76046-0.20151-0.26148-0.59733-0.26148-0.39103 0-0.59014 0.25668-0.19911 0.25668-0.19911 0.76525z"/>
<path d="m-325.33-16.769h-0.39822v-3.7327h0.39822z"/>
<path d="m-324.09-16.769h-0.39822v-2.6292h0.39822zm-0.43181-3.3417q0-0.13674 0.0672-0.19911 0.0672-0.06477 0.16793-0.06477 0.0959 0 0.16552 0.06477 0.0696 0.06477 0.0696 0.19911t-0.0696 0.20151q-0.0696 0.06477-0.16552 0.06477-0.10076 0-0.16793-0.06477-0.0672-0.06717-0.0672-0.20151z"/>
<path d="m-322.19-16.721q-0.57094 0-0.8852-0.35024-0.31186-0.35264-0.31186-0.99555 0-0.6597 0.31666-1.0195 0.31906-0.35984 0.90679-0.35984 0.18951 0 0.37903 0.04078 0.18951 0.04078 0.29746 0.09596l-0.12234 0.33825q-0.13194-0.05278-0.28787-0.08636-0.15593-0.03598-0.27588-0.03598-0.80123 0-0.80123 1.0219 0 0.48458 0.19431 0.74366 0.19671 0.25908 0.58054 0.25908 0.32865 0 0.67409-0.14154v0.35264q-0.26388 0.13674-0.6645 0.13674z"/>
<path d="m-321.31-19.398h0.427l0.57574 1.4993q0.18952 0.51337 0.2351 0.74127h0.0192q0.0312-0.12234 0.12954-0.41741 0.10076-0.29747 0.65251-1.8232h0.427l-1.1299 2.9938q-0.16792 0.4438-0.39342 0.62852-0.2231 0.18712-0.54935 0.18712-0.18232 0-0.35984-0.04078v-0.31906q0.13194 0.02879 0.29507 0.02879 0.41021 0 0.58533-0.46059l0.14634-0.37423z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -0,0 +1,4 @@
<html>
This is an example destination that will appear after successful non-Admin login
</html>

View file

@ -93,7 +93,8 @@ callback_minimal_server_echo(struct lws *wsi, enum lws_callback_reasons reason,
break;
case LWS_CALLBACK_ESTABLISHED:
lwsl_user("LWS_CALLBACK_ESTABLISHED\n");
/* generate a block of output before travis times us out */
lwsl_warn("LWS_CALLBACK_ESTABLISHED\n");
pss->ring = lws_ring_create(sizeof(struct msg), RING_DEPTH,
__minimal_destroy_message);
if (!pss->ring)

View file

@ -1,7 +1,7 @@
/*
* ws protocol handler plugin for "generic sessions"
*
* Copyright (C) 2010-2016 Andy Green <andy@warmcat.com>
* Copyright (C) 2010-2019 Andy Green <andy@warmcat.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -21,27 +21,65 @@
#include "private-lwsgs.h"
static int
lwsgs_smtp_client_done(struct lws_smtp_email *e, void *buf, size_t len)
{
free(e);
return 0;
}
static int
lwsgs_smtp_client_done_sentvfy(struct lws_smtp_email *e, void *buf, size_t len)
{
struct per_vhost_data__gs *vhd = (struct per_vhost_data__gs *)e->data;
const char *username = (const char *)e->extra;
char s[200], esc[96];
lwsl_notice("%s: registration email sent: %s\n", __func__, username);
/* mark the user as having sent the verification email */
lws_snprintf(s, sizeof(s) - 1,
"update users set verified=1 where username='%s' and verified==0;",
lws_sql_purify(esc, username, sizeof(esc) - 1));
if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) {
lwsl_err("%s: Unable to update user: %s\n", __func__,
sqlite3_errmsg(vhd->pdb));
return 1;
}
free(e);
return 0;
}
/* handle account confirmation links */
int
lwsgs_handler_confirm(struct per_vhost_data__gs *vhd, struct lws *wsi,
struct per_session_data__gs *pss)
{
char cookie[1024], s[256], esc[50];
char cookie[1024], s[256], esc[90];
struct lws_gs_event_args a;
struct lwsgs_user u;
if (lws_hdr_copy_fragment(wsi, cookie, sizeof(cookie),
WSI_TOKEN_HTTP_URI_ARGS, 0) < 0)
WSI_TOKEN_HTTP_URI_ARGS, 0) < 0) {
lwsl_err("%s: missing URI_ARGS\n", __func__);
goto verf_fail;
}
if (strncmp(cookie, "token=", 6))
if (strncmp(cookie, "token=", 6)) {
lwsl_err("%s: missing URI_ARGS token=\n", __func__);
goto verf_fail;
}
u.username[0] = '\0';
u.verified = -1;
lws_snprintf(s, sizeof(s) - 1,
"select username,email,verified from users where token = '%s';",
lws_sql_purify(esc, &cookie[6], sizeof(esc) - 1));
puts(s);
if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) !=
SQLITE_OK) {
lwsl_err("Unable to lookup token: %s\n",
@ -50,7 +88,8 @@ lwsgs_handler_confirm(struct per_vhost_data__gs *vhd, struct lws *wsi,
}
if (!u.username[0] || u.verified != 1) {
lwsl_notice("verify token doesn't map to unverified user\n");
lwsl_notice("verify token %s doesn't map to unverified user (user='%s', verified=%d)\n",
&cookie[6], u.username, u.verified);
goto verf_fail;
}
@ -111,7 +150,7 @@ int
lwsgs_handler_forgot(struct per_vhost_data__gs *vhd, struct lws *wsi,
struct per_session_data__gs *pss)
{
char cookie[1024], s[256], esc[50];
char cookie[1024], s[256], esc[96];
struct lwsgs_user u;
const char *a;
@ -196,26 +235,24 @@ forgot_fail:
int
lwsgs_handler_check(struct per_vhost_data__gs *vhd,
struct lws *wsi, struct per_session_data__gs *pss)
struct lws *wsi, struct per_session_data__gs *pss,
const char *in)
{
static const char * const colname[] = { "username", "email" };
char cookie[1024], s[256], esc[50], *pc;
unsigned char *p, *start, *end, buffer[LWS_PRE + 256];
char s[256], esc[96], *pc;
unsigned char *p, *start, *end, buffer[LWS_PRE + 1024];
struct lwsgs_user u;
int n;
/*
* either /check?email=xxx@yyy or: /check?username=xxx
* either /check/email=xxx@yyy or: /check/username=xxx
* returns '0' if not already registered, else '1'
*/
u.username[0] = '\0';
if (lws_hdr_copy_fragment(wsi, cookie, sizeof(cookie),
WSI_TOKEN_HTTP_URI_ARGS, 0) < 0)
goto reply;
n = !strncmp(cookie, "email=", 6);
pc = strchr(cookie, '=');
n = !strncmp(in, "email=", 6);
pc = strchr(in, '=');
if (!pc) {
lwsl_notice("cookie has no =\n");
goto reply;
@ -262,6 +299,7 @@ reply:
lwsl_err("_write returned %d from %ld\n", n, (long)(p - start));
return -1;
}
pss->check_response_value = s[0];
pss->check_response = 1;
@ -276,7 +314,7 @@ int
lwsgs_handler_change_password(struct per_vhost_data__gs *vhd, struct lws *wsi,
struct per_session_data__gs *pss)
{
char s[256], esc[50], username[50];
char s[256], esc[96], username[96];
struct lwsgs_user u;
lwsgw_hash sid;
int n = 0;
@ -361,15 +399,14 @@ sql:
int
lwsgs_handler_forgot_pw_form(struct per_vhost_data__gs *vhd,
struct lws *wsi,
struct per_session_data__gs *pss)
struct lws *wsi, struct per_session_data__gs *pss)
{
char esc[96], esc1[96], esc2[96], esc3[96], esc4[96];
char s[LWSGS_EMAIL_CONTENT_SIZE];
unsigned char buffer[LWS_PRE + LWSGS_EMAIL_CONTENT_SIZE];
char esc[50], esc1[50], esc2[50], esc3[50], esc4[50];
unsigned char sid_rand[32];
lws_smtp_email_t *em;
struct lwsgs_user u;
lwsgw_hash hash;
unsigned char sid_rand[20];
int n;
lwsl_notice("FORGOT %s %s\n",
@ -423,7 +460,19 @@ lwsgs_handler_forgot_pw_form(struct per_vhost_data__gs *vhd,
lwsl_err("Problem getting random for token\n");
return 1;
}
sha1_to_lwsgw_hash(sid_rand, &hash);
sha256_to_lwsgw_hash(sid_rand, &hash);
lws_snprintf(s, sizeof(s) - 1,
"update users set token='%s',token_time='%ld' where username='%s';",
hash.id, (long)lws_now_secs(),
lws_sql_purify(esc, u.username, sizeof(esc) - 1));
if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) !=
SQLITE_OK) {
lwsl_err("Unable to set token: %s\n",
sqlite3_errmsg(vhd->pdb));
return 1;
}
n = lws_snprintf(s, sizeof(s),
"From: Forgot Password Assistant Noreply <%s>\n"
"To: %s <%s>\n"
@ -437,7 +486,7 @@ lwsgs_handler_forgot_pw_form(struct per_vhost_data__gs *vhd,
lws_sql_purify(esc2, u.email, sizeof(esc2) - 1),
lws_sql_purify(esc3, u.username, sizeof(esc3) - 1),
lws_sql_purify(esc4, pss->ip, sizeof(esc4) - 1));
lws_snprintf(s + n, sizeof(s) -n,
n += lws_snprintf(s + n, sizeof(s) - n,
"%s/lwsgs-forgot?token=%s"
"&good=%s"
"&bad=%s\n\n"
@ -456,27 +505,15 @@ lwsgs_handler_forgot_pw_form(struct per_vhost_data__gs *vhd,
sizeof(esc3) - 1),
vhd->email_contact_person);
lws_snprintf((char *)buffer, sizeof(buffer) - 1,
"insert into email(username, content)"
" values ('%s', '%s');",
lws_sql_purify(esc, u.username, sizeof(esc) - 1), s);
if (sqlite3_exec(vhd->pdb, (char *)buffer, NULL,
NULL, NULL) != SQLITE_OK) {
lwsl_err("Unable to insert email: %s\n",
sqlite3_errmsg(vhd->pdb));
return 1;
}
puts(s);
lws_snprintf(s, sizeof(s) - 1,
"update users set token='%s',token_time='%ld' where username='%s';",
hash.id, (long)lws_now_secs(),
lws_sql_purify(esc, u.username, sizeof(esc) - 1));
if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) !=
SQLITE_OK) {
lwsl_err("Unable to set token: %s\n",
sqlite3_errmsg(vhd->pdb));
em = lws_smtp_client_alloc_email_helper(s, n, vhd->email_from, u.email,
u.username, strlen(u.username),
vhd, lwsgs_smtp_client_done);
if (!em)
return 1;
if (lws_smtp_client_add_email(vhd->smtp_client, em))
return 1;
}
return 0;
}
@ -487,11 +524,13 @@ lwsgs_handler_register_form(struct per_vhost_data__gs *vhd,
struct per_session_data__gs *pss)
{
unsigned char buffer[LWS_PRE + LWSGS_EMAIL_CONTENT_SIZE];
char esc[50], esc1[50], esc2[50], esc3[50], esc4[50];
char esc[96], esc1[96], esc2[96], esc3[96], esc4[96];
char s[LWSGS_EMAIL_CONTENT_SIZE];
unsigned char sid_rand[20];
unsigned char sid_rand[32];
lws_smtp_email_t *em;
struct lwsgs_user u;
lwsgw_hash hash;
size_t n;
lwsl_notice("REGISTER %s %s %s\n",
lws_spa_get_string(pss->spa, FGS_USERNAME),
@ -551,7 +590,7 @@ lwsgs_handler_register_form(struct per_vhost_data__gs *vhd,
lwsl_err("Problem getting random for token\n");
return 1;
}
sha1_to_lwsgw_hash(sid_rand, &hash);
sha256_to_lwsgw_hash(sid_rand, &hash);
lws_snprintf((char *)buffer, sizeof(buffer) - 1,
"insert into users(username,"
@ -571,11 +610,11 @@ lwsgs_handler_register_form(struct per_vhost_data__gs *vhd,
return 1;
}
lws_snprintf(s, sizeof(s),
n = lws_snprintf(s, sizeof(s),
"From: Noreply <%s>\n"
"To: %s <%s>\n"
"Subject: Registration verification\n"
"\n"
"Subject: Registration verification\n"
"\n"
"Hello, %s\n\n"
"We received a registration from IP %s using this email,\n"
"to confirm it is legitimate, please click the link below.\n\n"
@ -594,16 +633,16 @@ lwsgs_handler_register_form(struct per_vhost_data__gs *vhd,
vhd->email_confirm_url, hash.id,
vhd->email_contact_person);
lws_snprintf((char *)buffer, sizeof(buffer) - 1,
"insert into email(username, content) values ('%s', '%s');",
lws_sql_purify(esc, lws_spa_get_string(pss->spa, FGS_USERNAME),
sizeof(esc) - 1), s);
if (sqlite3_exec(vhd->pdb, (char *)buffer, NULL, NULL, NULL) != SQLITE_OK) {
lwsl_err("Unable to insert email: %s\n",
sqlite3_errmsg(vhd->pdb));
em = lws_smtp_client_alloc_email_helper(s, n, vhd->email_from,
lws_spa_get_string(pss->spa, FGS_EMAIL),
lws_spa_get_string(pss->spa, FGS_USERNAME),
strlen(lws_spa_get_string(pss->spa, FGS_USERNAME)),
vhd, lwsgs_smtp_client_done_sentvfy);
if (!em)
return 1;
if (lws_smtp_client_add_email(vhd->smtp_client, em))
return 1;
}
return 0;
}

View file

@ -67,6 +67,7 @@ struct per_vhost_data__gs {
struct lws_context *context;
char session_db[256];
char admin_user[32];
char urlroot[48];
char confounder[32];
char email_contact_person[128];
char email_title[128];
@ -119,7 +120,7 @@ int
lwsgs_check_credentials(struct per_vhost_data__gs *vhd,
const char *username, const char *password);
void
sha1_to_lwsgw_hash(unsigned char *hash, lwsgw_hash *shash);
sha256_to_lwsgw_hash(unsigned char *hash, lwsgw_hash *shash);
unsigned int
lwsgs_now_secs(void);
int
@ -151,7 +152,7 @@ lwsgs_handler_forgot(struct per_vhost_data__gs *vhd, struct lws *wsi,
struct per_session_data__gs *pss);
int
lwsgs_handler_check(struct per_vhost_data__gs *vhd, struct lws *wsi,
struct per_session_data__gs *pss);
struct per_session_data__gs *pss, const char *in);
int
lwsgs_handler_change_password(struct per_vhost_data__gs *vhd, struct lws *wsi,
struct per_session_data__gs *pss);

View file

@ -50,141 +50,6 @@ struct lwsgs_fill_args {
};
static const struct lws_protocols protocols[];
#if 0
static int
lwsgs_lookup_callback_email(void *priv, int cols, char **col_val,
char **col_name)
{
struct lwsgs_fill_args *a = (struct lwsgs_fill_args *)priv;
int n;
for (n = 0; n < cols; n++) {
if (!strcmp(col_name[n], "content")) {
lws_strncpy(a->buf, col_val[n], a->len);
continue;
}
}
return 0;
}
static int
lwsgs_email_cb_get_body(struct lws_email *email, char *buf, int len)
{
struct per_vhost_data__gs *vhd = (struct per_vhost_data__gs *)email->data;
struct lwsgs_fill_args a;
char ss[150], esc[50];
a.buf = buf;
a.len = len;
lws_snprintf(ss, sizeof(ss) - 1,
"select content from email where username='%s';",
lws_sql_purify(esc, vhd->u.username, sizeof(esc) - 1));
lws_strncpy(buf, "failed", len);
if (sqlite3_exec(vhd->pdb, ss, lwsgs_lookup_callback_email, &a,
NULL) != SQLITE_OK) {
lwsl_err("Unable to lookup email: %s\n",
sqlite3_errmsg(vhd->pdb));
return 1;
}
return 0;
}
#endif
#if 0
static int
lwsgs_smtp_client_done(struct lws_smtp_email *e, void *buf, size_t len)
{
struct per_vhost_data__gs *vhd = (struct per_vhost_data__gs *)e->data;
char s[200], esc[50];
/* mark the user as having sent the verification email */
lws_snprintf(s, sizeof(s) - 1,
"update users set verified=1 where username='%s' and verified==0;",
lws_sql_purify(esc, vhd->u.username, sizeof(esc) - 1));
if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) {
lwsl_err("%s: Unable to update user: %s\n", __func__,
sqlite3_errmsg(vhd->pdb));
return 1;
}
lws_snprintf(s, sizeof(s) - 1,
"delete from email where username='%s';",
lws_sql_purify(esc, vhd->u.username, sizeof(esc) - 1));
if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) {
lwsl_err("%s: Unable to delete email text: %s\n", __func__,
sqlite3_errmsg(vhd->pdb));
return 1;
}
return 0;
}
#endif
#if 0
static int
lwsgs_smtp_send_pending(struct lws_email *email)
{
struct per_vhost_data__gs *vhd = lws_container_of(email,
struct per_vhost_data__gs, email);
char s[LWSGS_EMAIL_CONTENT_SIZE], esc[50];
time_t now = lws_now_secs();
/*
* users not verified in 24h get deleted
*/
lws_snprintf(s, sizeof(s) - 1, "delete from users where ((verified != %d)"
" and (creation_time <= %lu));", LWSGS_VERIFIED_ACCEPTED,
(unsigned long)now - vhd->timeout_email_secs);
if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) {
lwsl_err("Unable to expire users: %s\n",
sqlite3_errmsg(vhd->pdb));
return 1;
}
lws_snprintf(s, sizeof(s) - 1, "update users set token_time=0 where "
"(token_time <= %lu);",
(unsigned long)now - vhd->timeout_email_secs);
if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) {
lwsl_err("Unable to expire users: %s\n",
sqlite3_errmsg(vhd->pdb));
return 1;
}
vhd->u.username[0] = '\0';
lws_snprintf(s, sizeof(s) - 1, "select username from email limit 1;");
if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &vhd->u,
NULL) != SQLITE_OK) {
lwsl_err("Unable to lookup user: %s\n", sqlite3_errmsg(vhd->pdb));
return 1;
}
lws_snprintf(s, sizeof(s) - 1,
"select username, creation_time, email, ip, verified, token"
" from users where username='%s' limit 1;",
lws_sql_purify(esc, vhd->u.username, sizeof(esc) - 1));
if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &vhd->u,
NULL) != SQLITE_OK) {
lwsl_err("Unable to lookup user: %s\n",
sqlite3_errmsg(vhd->pdb));
return 1;
}
if (!vhd->u.username[0])
/*
* nothing to do, we are idle and no suitable
* accounts waiting for verification. When a new user
* is added we will get kicked to try again.
*/
return 1;
lws_strncpy(email->email_to, vhd->u.email, sizeof(email->email_to));
return 0;
}
#endif
struct lwsgs_subst_args
{
@ -199,7 +64,7 @@ lwsgs_subst(void *data, int index)
struct lwsgs_subst_args *a = (struct lwsgs_subst_args *)data;
struct lwsgs_user u;
lwsgw_hash sid;
char esc[50], s[100];
char esc[96], s[100];
int n;
a->pss->result[0] = '\0';
@ -240,6 +105,21 @@ lwsgs_subst(void *data, int index)
return NULL;
}
static int
lws_get_effective_host(struct lws *wsi, char *buf, size_t buflen)
{
/* h2 */
if (lws_hdr_copy(wsi, buf, buflen - 1,
WSI_TOKEN_HTTP_COLON_AUTHORITY) > 0)
return 0;
/* h1 */
if (lws_hdr_copy(wsi, buf, buflen - 1, WSI_TOKEN_HOST) > 0)
return 0;
return 1;
}
static int
callback_generic_sessions(struct lws *wsi, enum lws_callback_reasons reason,
void *user, void *in, size_t len)
@ -248,24 +128,25 @@ callback_generic_sessions(struct lws *wsi, enum lws_callback_reasons reason,
const struct lws_protocol_vhost_options *pvo;
struct per_vhost_data__gs *vhd = (struct per_vhost_data__gs *)
lws_protocol_vh_priv_get(lws_get_vhost(wsi),
&protocols[0]);
lws_vhost_name_to_protocol(lws_get_vhost(wsi),
"protocol-generic-sessions"));
char cookie[1024], username[32], *pc = cookie;
unsigned char buffer[LWS_PRE + LWSGS_EMAIL_CONTENT_SIZE];
struct lws_process_html_args *args;
struct lws_process_html_args *args = in;
struct lws_session_info *sinfo;
char s[LWSGS_EMAIL_CONTENT_SIZE];
unsigned char *p, *start, *end;
lws_smtp_client_info_t sci;
const char *cp, *cp1;
sqlite3_stmt *sm;
lwsgw_hash sid;
const char *cp;
int n;
switch (reason) {
case LWS_CALLBACK_PROTOCOL_INIT: /* per vhost */
vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
&protocols[0], sizeof(struct per_vhost_data__gs));
lws_get_protocol(wsi), sizeof(struct per_vhost_data__gs));
if (!vhd)
return 1;
vhd->context = lws_get_context(wsi);
@ -282,13 +163,17 @@ callback_generic_sessions(struct lws *wsi, enum lws_callback_reasons reason,
strcpy(sci.ip, "127.0.0.1");
strcpy(vhd->email_from, "noreply@unconfigured.com");
strcpy(vhd->email_title, "Registration Email from unconfigured");
vhd->urlroot[0] = '\0';
pvo = (const struct lws_protocol_vhost_options *)in;
while (pvo) {
if (!strcmp(pvo->name, "admin-user"))
lws_strncpy(vhd->admin_user, pvo->value,
sizeof(vhd->admin_user));
if (!strcmp(pvo->name, "admin-password-sha1"))
if (!strcmp(pvo->name, "urlroot"))
lws_strncpy(vhd->urlroot, pvo->value,
sizeof(vhd->urlroot));
if (!strcmp(pvo->name, "admin-password-sha256"))
lws_strncpy(vhd->admin_password_sha256.id, pvo->value,
sizeof(vhd->admin_password_sha256.id));
if (!strcmp(pvo->name, "session-db"))
@ -337,9 +222,8 @@ callback_generic_sessions(struct lws *wsi, enum lws_callback_reasons reason,
return 1;
}
if (sqlite3_open_v2(vhd->session_db, &vhd->pdb,
SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE, NULL) != SQLITE_OK) {
if (lws_struct_sq3_open(lws_get_context(wsi),
vhd->session_db, &vhd->pdb)) {
lwsl_err("Unable to open session db %s: %s\n",
vhd->session_db, sqlite3_errmsg(vhd->pdb));
@ -348,7 +232,7 @@ callback_generic_sessions(struct lws *wsi, enum lws_callback_reasons reason,
if (sqlite3_prepare(vhd->pdb,
"create table if not exists sessions ("
" name char(40),"
" name char(65),"
" username varchar(32),"
" expire integer"
");",
@ -373,10 +257,10 @@ callback_generic_sessions(struct lws *wsi, enum lws_callback_reasons reason,
" creation_time integer,"
" ip varchar(46),"
" email varchar(100),"
" pwhash varchar(42),"
" pwsalt varchar(42),"
" pwhash varchar(65),"
" pwsalt varchar(65),"
" pwchange_time integer,"
" token varchar(42),"
" token varchar(65),"
" verified integer,"
" token_time integer,"
" last_forgot_validated integer,"
@ -389,18 +273,6 @@ callback_generic_sessions(struct lws *wsi, enum lws_callback_reasons reason,
return 1;
}
sprintf(s, "create table if not exists email ("
" username varchar(32),"
" content blob,"
" primary key (username)"
");");
if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) {
lwsl_err("Unable to create user table: %s\n",
sqlite3_errmsg(vhd->pdb));
return 1;
}
sci.data = vhd;
sci.abs = lws_abstract_get_by_name("raw_skt");
sci.vh = lws_get_vhost(wsi);
@ -411,6 +283,8 @@ callback_generic_sessions(struct lws *wsi, enum lws_callback_reasons reason,
return 1;
}
lwsl_notice("%s: created SMTP client\n", __func__);
break;
case LWS_CALLBACK_PROTOCOL_DESTROY:
@ -426,72 +300,112 @@ callback_generic_sessions(struct lws *wsi, enum lws_callback_reasons reason,
case LWS_CALLBACK_HTTP_WRITEABLE:
if (!pss->check_response)
break;
pss->check_response = 0;
n = lws_write(wsi, (unsigned char *)&pss->check_response_value,
1, LWS_WRITE_HTTP_FINAL);
1, LWS_WRITE_HTTP | LWS_WRITE_H2_STREAM_END);
if (n != 1)
return -1;
goto try_to_reuse;
case LWS_CALLBACK_HTTP:
lwsl_info("LWS_CALLBACK_HTTP: %s\n", (const char *)in);
if (!pss) {
lwsl_err("%s: no valid pss\n", __func__);
return 1;
}
pss->login_session.id[0] = '\0';
pss->phs.pos = 0;
lws_strncpy(pss->onward, (char *)in, sizeof(pss->onward));
if (!strcmp((const char *)in, "/lwsgs-forgot")) {
cp = in;
if ((*(const char *)in == '/'))
cp++;
if (lws_get_effective_host(wsi, cookie, sizeof(cookie))) {
lwsl_err("%s: HTTP: no effective host\n", __func__);
return 1;
}
lwsl_notice("LWS_CALLBACK_HTTP: %s, HOST '%s'\n",
(const char *)in, cookie);
n = strlen(cp);
lws_snprintf(pss->onward, sizeof(pss->onward),
"%s%s", vhd->urlroot, (const char *)in);
if (n >= 12 &&
!strcmp(cp + n - 12, "lwsgs-forgot")) {
lwsgs_handler_forgot(vhd, wsi, pss);
goto redirect_with_cookie;
}
if (!strcmp((const char *)in, "/lwsgs-confirm")) {
if (n >= 13 &&
!strcmp(cp + n - 13, "lwsgs-confirm")) {
lwsgs_handler_confirm(vhd, wsi, pss);
goto redirect_with_cookie;
}
if (!strcmp((const char *)in, "/lwsgs-check")) {
lwsgs_handler_check(vhd, wsi, pss);
cp = strstr(cp, "lwsgs-check/");
if (cp) {
lwsgs_handler_check(vhd, wsi, pss, cp + 12);
/* second, async part will complete transaction */
break;
}
if (!strcmp((const char *)in, "/lwsgs-login"))
if (n >= 11 && !strcmp(cp + n - 11, "lwsgs-login"))
break;
if (!strcmp((const char *)in, "/lwsgs-logout"))
if (n >= 12 && !strcmp(cp + n - 12, "lwsgs-logout"))
break;
if (!strcmp((const char *)in, "/lwsgs-forgot"))
if (n >= 12 && !strcmp(cp + n - 12, "lwsgs-forgot"))
break;
if (!strcmp((const char *)in, "/lwsgs-change"))
if (n >= 12 && !strcmp(cp + n - 12, "lwsgs-change"))
break;
/* if no legitimate url for GET, return 404 */
lwsl_err("http doing 404 on %s\n", (const char *)in);
lwsl_err("http doing 404 on %s\n", cp);
lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL);
return -1;
//goto try_to_reuse;
case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
args = (struct lws_process_html_args *)in;
if (!args->chunked)
break;
case LWS_CALLBACK_CHECK_ACCESS_RIGHTS:
n = 0;
username[0] = '\0';
sid.id[0] = '\0';
args = (struct lws_process_html_args *)in;
lwsl_debug("LWS_CALLBACK_CHECK_ACCESS_RIGHTS\n");
lwsl_notice("%s: LWS_CALLBACK_CHECK_ACCESS_RIGHTS: need 0x%x\n",
__func__, args->max_len);
if (!lwsgs_get_sid_from_wsi(wsi, &sid)) {
if (lwsgs_lookup_session(vhd, &sid, username, sizeof(username))) {
static const char * const oprot[] = {
"http://", "https://"
};
lwsl_notice("session lookup for %s failed, probably expired\n", sid.id);
if (lwsgs_lookup_session(vhd, &sid, username,
sizeof(username))) {
/*
* if we're authenticating for ws, we don't
* want to redirect it or gain a cookie on that,
* he'll need to get the cookie from http
* interactions outside of this.
*/
if (args->chunked) {
lwsl_notice("%s: ws auth failed\n",
__func__);
return 1;
}
lwsl_notice("session lookup for %s failed, "
"probably expired\n", sid.id);
pss->delete_session = sid;
args->final = 1; /* signal we dealt with it */
if (lws_hdr_copy(wsi, cookie, sizeof(cookie) - 1,
WSI_TOKEN_HOST) < 0)
return 1;
lws_snprintf(pss->onward, sizeof(pss->onward) - 1,
"%s%s%s", oprot[!!lws_is_ssl(wsi)],
cookie, args->p);
lwsl_notice("redirecting to ourselves with cookie refresh\n");
/* we need a redirect to ourselves, session cookie is expired */
"%s%s", vhd->urlroot, args->p);
lwsl_notice("redirecting to ourselves with "
"cookie refresh\n");
/* we need a redirect to ourselves,
* session cookie is expired */
goto redirect_with_cookie;
}
} else
@ -590,10 +504,18 @@ callback_generic_sessions(struct lws *wsi, enum lws_callback_reasons reason,
if (!pss->spa)
break;
lwsl_info("LWS_CALLBACK_HTTP_BODY_COMPLETION: %s\n", pss->onward);
lws_spa_finalize(pss->spa);
cp1 = (const char *)pss->onward;
if (*cp1 == '/')
cp1++;
if (!strcmp((char *)pss->onward, "/lwsgs-change")) {
lws_spa_finalize(pss->spa);
n = strlen(cp1);
if (lws_get_effective_host(wsi, cookie, sizeof(cookie)))
return 1;
if (!strcmp(cp1 + n - 12, "lwsgs-change")) {
if (!lwsgs_handler_change_password(vhd, wsi, pss)) {
cp = lws_spa_get_string(pss->spa, FGS_GOOD);
goto pass;
@ -602,12 +524,15 @@ callback_generic_sessions(struct lws *wsi, enum lws_callback_reasons reason,
cp = lws_spa_get_string(pss->spa, FGS_BAD);
lwsl_notice("user/password no good %s\n",
lws_spa_get_string(pss->spa, FGS_USERNAME));
lws_strncpy(pss->onward, cp, sizeof(pss->onward) - 1);
lws_snprintf(pss->onward, sizeof(pss->onward),
"%s%s", vhd->urlroot, cp);
pss->onward[sizeof(pss->onward) - 1] = '\0';
goto completion_flow;
}
if (!strcmp((char *)pss->onward, "/lwsgs-login")) {
if (!strcmp(cp1 + n - 11, "lwsgs-login")) {
lwsl_err("%s: lwsgs-login\n", __func__);
if (lws_spa_get_string(pss->spa, FGS_FORGOT) &&
lws_spa_get_string(pss->spa, FGS_FORGOT)[0]) {
if (lwsgs_handler_forgot_pw_form(vhd, wsi, pss)) {
@ -623,8 +548,8 @@ callback_generic_sessions(struct lws *wsi, enum lws_callback_reasons reason,
if (!lws_spa_get_string(pss->spa, FGS_USERNAME) ||
!lws_spa_get_string(pss->spa, FGS_PASSWORD)) {
lwsl_notice("username '%s' or pw '%s' missing\n",
lws_spa_get_string(pss->spa, FGS_USERNAME),
lws_spa_get_string(pss->spa, FGS_PASSWORD));
lws_spa_get_string(pss->spa, FGS_USERNAME),
lws_spa_get_string(pss->spa, FGS_PASSWORD));
return -1;
}
@ -640,8 +565,10 @@ callback_generic_sessions(struct lws *wsi, enum lws_callback_reasons reason,
lws_smtp_client_kick(vhd->smtp_client);
}
reg_done:
lws_strncpy(pss->onward, lws_spa_get_string(pss->spa, n),
sizeof(pss->onward));
lws_snprintf(pss->onward, sizeof(pss->onward),
"%s%s", vhd->urlroot,
lws_spa_get_string(pss->spa, n));
pss->login_expires = 0;
pss->logging_out = 1;
goto completion_flow;
@ -665,28 +592,32 @@ reg_done:
/* check users in database */
if (!lwsgs_check_credentials(vhd, lws_spa_get_string(pss->spa, FGS_USERNAME),
lws_spa_get_string(pss->spa, FGS_PASSWORD))) {
lwsl_info("pw hash check met\n");
if (!lwsgs_check_credentials(vhd,
lws_spa_get_string(pss->spa, FGS_USERNAME),
lws_spa_get_string(pss->spa, FGS_PASSWORD))) {
lwsl_notice("pw hash check met\n");
cp = lws_spa_get_string(pss->spa, FGS_GOOD);
goto pass;
} else
lwsl_notice("user/password no good %s\n",
lws_spa_get_string(pss->spa, FGS_USERNAME));
lwsl_notice("user/password no good %s %s\n",
lws_spa_get_string(pss->spa, FGS_USERNAME),
lws_spa_get_string(pss->spa, FGS_PASSWORD));
if (!lws_spa_get_string(pss->spa, FGS_BAD)) {
lwsl_info("No admin or good target url in form\n");
return -1;
}
lws_strncpy(pss->onward, lws_spa_get_string(pss->spa, FGS_BAD),
sizeof(pss->onward));
lwsl_debug("failed\n");
lws_snprintf(pss->onward, sizeof(pss->onward),
"%s%s", vhd->urlroot,
lws_spa_get_string(pss->spa, FGS_BAD));
lwsl_notice("failed: %s\n", pss->onward);
goto completion_flow;
}
if (!strcmp((char *)pss->onward, "/lwsgs-logout")) {
if (!strcmp(cp1 + n - 12, "lwsgs-logout")) {
lwsl_notice("/logout\n");
@ -695,6 +626,11 @@ reg_done:
return 1;
}
/*
* We keep the same session, but mark it as not
* being associated to any authenticated user
*/
lwsgw_update_session(vhd, &pss->login_session, "");
if (!lws_spa_get_string(pss->spa, FGS_GOOD)) {
@ -702,8 +638,9 @@ reg_done:
return -1;
}
lws_strncpy(pss->onward, lws_spa_get_string(pss->spa, FGS_GOOD),
sizeof(pss->onward));
lws_snprintf(pss->onward, sizeof(pss->onward),
"%s%s", vhd->urlroot,
lws_spa_get_string(pss->spa, FGS_GOOD));
pss->login_expires = 0;
pss->logging_out = 1;
@ -714,7 +651,8 @@ reg_done:
break;
pass:
lws_strncpy(pss->onward, cp, sizeof(pss->onward));
lws_snprintf(pss->onward, sizeof(pss->onward),
"%s%s", vhd->urlroot, cp);
if (lwsgs_get_sid_from_wsi(wsi, &sid))
sid.id[0] = '\0';
@ -726,18 +664,18 @@ pass:
/* we need to create a new, authorized session */
if (lwsgs_new_session_id(vhd, &pss->login_session,
lws_spa_get_string(pss->spa, FGS_USERNAME),
pss->login_expires))
lws_spa_get_string(pss->spa, FGS_USERNAME),
pss->login_expires))
goto try_to_reuse;
lwsl_info("Creating new session: %s\n",
lwsl_notice("Creating new session: %s\n",
pss->login_session.id);
} else {
/*
* we can just update the existing session to be
* authorized
*/
lwsl_info("Authorizing existing session %s", sid.id);
lwsl_notice("Authorizing existing session %s", sid.id);
lwsgw_update_session(vhd, &sid,
lws_spa_get_string(pss->spa, FGS_USERNAME));
pss->login_session = sid;
@ -757,6 +695,8 @@ completion_flow:
case LWS_CALLBACK_ADD_HEADERS:
lwsgw_expire_old_sessions(vhd);
lwsl_warn("ADD_HEADERS\n");
args = (struct lws_process_html_args *)in;
if (!pss)
return 1;
@ -765,7 +705,7 @@ completion_flow:
lwsgw_cookie_from_session(&pss->delete_session, 0, &pc,
cookie + sizeof(cookie) - 1);
lwsl_info("deleting cookie '%s'\n", cookie);
lwsl_notice("deleting cookie '%s'\n", cookie);
if (lws_add_http_header_by_name(wsi,
(unsigned char *)"set-cookie:",
@ -811,13 +751,24 @@ redirect_with_cookie:
start = p;
end = p + sizeof(buffer) - LWS_PRE;
lwsl_warn("%s: redirect_with_cookie\n", __func__);
if (lws_add_http_header_status(wsi, HTTP_STATUS_SEE_OTHER, &p, end))
return 1;
if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_LOCATION,
(unsigned char *)pss->onward,
strlen(pss->onward), &p, end))
return 1;
{
char loc[1024], uria[128];
uria[0] = '\0';
lws_hdr_copy_fragment(wsi, uria, sizeof(uria),
WSI_TOKEN_HTTP_URI_ARGS, 0);
n = lws_snprintf(loc, sizeof(loc), "%s?%s",
pss->onward, uria);
lwsl_notice("%s: redirect to '%s'\n", __func__, loc);
if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_LOCATION,
(unsigned char *)loc, n, &p, end))
return 1;
}
if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
(unsigned char *)"text/html", 9, &p, end))
@ -834,16 +785,20 @@ redirect_with_cookie:
if (lws_add_http_header_by_name(wsi,
(unsigned char *)"set-cookie:",
(unsigned char *)cookie, pc - cookie,
&p, end))
&p, end)) {
lwsl_err("fail0\n");
return 1;
}
}
if (!pss->login_session.id[0]) {
pss->login_expires = lws_now_secs() +
vhd->timeout_anon_absolute_secs;
if (lwsgs_new_session_id(vhd, &pss->login_session, "",
pss->login_expires))
pss->login_expires)) {
lwsl_err("fail1\n");
return 1;
}
} else
pss->login_expires = lws_now_secs() +
vhd->timeout_absolute_secs;
@ -859,21 +814,26 @@ redirect_with_cookie:
pss->login_expires, &pc,
cookie + sizeof(cookie) - 1);
lwsl_info("setting cookie '%s'\n", cookie);
lwsl_err("%s: setting cookie '%s'\n", __func__, cookie);
pss->logging_out = 0;
if (lws_add_http_header_by_name(wsi,
(unsigned char *)"set-cookie:",
(unsigned char *)cookie, pc - cookie,
&p, end))
&p, end)) {
lwsl_err("fail2\n");
return 1;
}
}
if (lws_finalize_http_header(wsi, &p, end))
return 1;
n = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS);
// lwsl_hexdump_notice(start, p - start);
n = lws_write(wsi, start, p - start, LWS_WRITE_H2_STREAM_END |
LWS_WRITE_HTTP_HEADERS);
if (n < 0)
return 1;

View file

@ -1,7 +1,7 @@
/*
* ws protocol handler plugin for messageboard "generic sessions" demo
*
* Copyright (C) 2010-2016 Andy Green <andy@warmcat.com>
* Copyright (C) 2010-2019 Andy Green <andy@warmcat.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -157,12 +157,13 @@ callback_messageboard(struct lws *wsi, enum lws_callback_reasons reason,
const struct lws_protocol_vhost_options *pvo;
struct per_vhost_data__gs_mb *vhd = (struct per_vhost_data__gs_mb *)
lws_protocol_vh_priv_get(lws_get_vhost(wsi), lws_get_protocol(wsi));
unsigned char *p, *start, *end, buffer[LWS_PRE + 256];
unsigned char *p, *start, *end, buffer[LWS_PRE + 4096];
char s[512];
int n;
switch (reason) {
case LWS_CALLBACK_PROTOCOL_INIT: /* per vhost */
vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
lws_get_protocol(wsi), sizeof(struct per_vhost_data__gs_mb));
if (!vhd)
@ -187,9 +188,8 @@ callback_messageboard(struct lws *wsi, enum lws_callback_reasons reason,
return 1;
}
if (sqlite3_open_v2(vhd->message_db, &vhd->pdb,
SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE, NULL) != SQLITE_OK) {
if (lws_struct_sq3_open(lws_get_context(wsi),
vhd->message_db, &vhd->pdb)) {
lwsl_err("Unable to open message db %s: %s\n",
vhd->message_db, sqlite3_errmsg(vhd->pdb));
@ -226,6 +226,14 @@ callback_messageboard(struct lws *wsi, enum lws_callback_reasons reason,
lws_callback_on_writable(wsi);
break;
case LWS_CALLBACK_CLOSED:
lwsl_debug("%s: LWS_CALLBACK_CLOSED\n", __func__);
if (pss && pss->pss_gs) {
free(pss->pss_gs);
pss->pss_gs = NULL;
}
break;
case LWS_CALLBACK_SERVER_WRITEABLE:
{
struct message m;
@ -279,7 +287,8 @@ callback_messageboard(struct lws *wsi, enum lws_callback_reasons reason,
pss->our_form = 0;
/* ie, it's our messageboard new message form */
if (!strcmp((const char *)in, "/msg")) {
if (!strcmp((const char *)in, "/msg") ||
!strcmp((const char *)in, "msg")) {
pss->our_form = 1;
break;
}
@ -308,9 +317,11 @@ callback_messageboard(struct lws *wsi, enum lws_callback_reasons reason,
case LWS_CALLBACK_HTTP_WRITEABLE:
if (!pss->second_http_part)
break;
goto passthru;
s[0] = '0';
n = lws_write(wsi, (unsigned char *)s, 1, LWS_WRITE_HTTP);
n = lws_write(wsi, (unsigned char *)s, 1, LWS_WRITE_HTTP|
LWS_WRITE_H2_STREAM_END);
if (n != 1)
return -1;
@ -336,18 +347,18 @@ callback_messageboard(struct lws *wsi, enum lws_callback_reasons reason,
return -1;
if (lws_finalize_http_header(wsi, &p, end))
return -1;
n = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS);
if (n != (p - start)) {
lwsl_err("_write returned %d from %ld\n", n, (long)(p - start));
return -1;
}
pss->second_http_part = 1;
lws_callback_on_writable(wsi);
break;
case LWS_CALLBACK_HTTP_BIND_PROTOCOL:
if (!pss || pss->pss_gs)
if (!pss || !vhd || pss->pss_gs)
break;
pss->pss_gs = malloc(vhd->gsp->per_session_data_size);
@ -375,6 +386,7 @@ callback_messageboard(struct lws *wsi, enum lws_callback_reasons reason,
passthru:
if (!pss || !vhd)
break;
return vhd->gsp->callback(wsi, reason, pss->pss_gs, in, len);
}

View file

@ -23,13 +23,13 @@
#include <stdlib.h>
void
sha1_to_lwsgw_hash(unsigned char *hash, lwsgw_hash *shash)
sha256_to_lwsgw_hash(unsigned char *hash, lwsgw_hash *shash)
{
static const char *hex = "0123456789abcdef";
char *p = shash->id;
int n;
for (n = 0; n < 20; n++) {
for (n = 0; n < (int)lws_genhash_size(LWS_GENHASH_TYPE_SHA256); n++) {
*p++ = hex[(hash[n] >> 4) & 0xf];
*p++ = hex[hash[n] & 15];
}
@ -48,7 +48,7 @@ lwsgw_check_admin(struct per_vhost_data__gs *vhd,
return 0;
lws_SHA1((unsigned char *)password, strlen(password), hash_bin.bin);
sha1_to_lwsgw_hash(hash_bin.bin, &pw_hash);
sha256_to_lwsgw_hash(hash_bin.bin, &pw_hash);
return !strcmp(vhd->admin_password_sha256.id, pw_hash.id);
}
@ -106,7 +106,7 @@ lwsgw_update_session(struct per_vhost_data__gs *vhd,
lwsgw_hash *hash, const char *user)
{
time_t n = lws_now_secs();
char s[200], esc[50], esc1[50];
char s[200], esc[96], esc1[96];
if (user[0])
n += vhd->timeout_absolute_secs;
@ -125,6 +125,8 @@ lwsgw_update_session(struct per_vhost_data__gs *vhd,
return 1;
}
puts(s);
return 0;
}
@ -183,7 +185,7 @@ lwsgs_get_sid_from_wsi(struct lws *wsi, lwsgw_hash *sid)
}
/* extract the sid from the cookie */
if (lwsgw_session_from_cookie(cookie, sid)) {
lwsl_info("session from cookie failed\n");
lwsl_info("%s: session from cookie failed\n", __func__);
return 1;
}
@ -218,7 +220,7 @@ lwsgs_lookup_session(struct per_vhost_data__gs *vhd,
const lwsgw_hash *sid, char *username, int len)
{
struct lla lla = { username, len, 1 };
char s[150], esc[50];
char s[150], esc[96];
lwsgw_expire_old_sessions(vhd);
@ -291,7 +293,7 @@ int
lwsgs_lookup_user(struct per_vhost_data__gs *vhd,
const char *username, struct lwsgs_user *u)
{
char s[150], esc[50];
char s[150], esc[96];
u->username[0] = '\0';
lws_snprintf(s, sizeof(s) - 1,
@ -314,17 +316,19 @@ int
lwsgs_new_session_id(struct per_vhost_data__gs *vhd,
lwsgw_hash *sid, const char *username, int exp)
{
unsigned char sid_rand[20];
unsigned char sid_rand[32];
const char *u;
char s[300], esc[50], esc1[50];
char s[300], esc[96], esc1[96];
if (username)
u = username;
else
u = "";
if (!sid)
if (!sid) {
lwsl_err("%s: NULL sid\n", __func__);
return 1;
}
memset(sid, 0, sizeof(*sid));
@ -332,7 +336,7 @@ lwsgs_new_session_id(struct per_vhost_data__gs *vhd,
sizeof(sid_rand))
return 1;
sha1_to_lwsgw_hash(sid_rand, sid);
sha256_to_lwsgw_hash(sid_rand, sid);
lws_snprintf(s, sizeof(s) - 1,
"insert into sessions(name, username, expire) "
@ -347,27 +351,28 @@ lwsgs_new_session_id(struct per_vhost_data__gs *vhd,
return 1;
}
lwsl_notice("%s: created session %s\n", __func__, sid->id);
return 0;
}
int
lwsgs_get_auth_level(struct per_vhost_data__gs *vhd,
const char *username)
lwsgs_get_auth_level(struct per_vhost_data__gs *vhd, const char *username)
{
struct lwsgs_user u;
int n = 0;
/* we are logged in as some kind of user */
if (username[0]) {
n |= LWSGS_AUTH_LOGGED_IN;
/* we are logged in as admin */
if (!strcmp(username, vhd->admin_user))
n |= LWSGS_AUTH_VERIFIED | LWSGS_AUTH_ADMIN; /* automatically verified */
/* automatically verified */
n |= LWSGS_AUTH_VERIFIED | LWSGS_AUTH_ADMIN;
}
if (!lwsgs_lookup_user(vhd, username, &u)) {
if ((u.verified & 0xff) == LWSGS_VERIFIED_ACCEPTED)
n |= LWSGS_AUTH_VERIFIED;
n |= LWSGS_AUTH_LOGGED_IN | LWSGS_AUTH_VERIFIED;
if (u.last_forgot_validated > (time_t)lws_now_secs() - 300)
n |= LWSGS_AUTH_FORGOT_FLOW;
@ -380,24 +385,31 @@ int
lwsgs_check_credentials(struct per_vhost_data__gs *vhd,
const char *username, const char *password)
{
unsigned char buffer[300];
struct lws_genhash_ctx hash_ctx;
lwsgw_hash_bin hash_bin;
struct lwsgs_user u;
lwsgw_hash hash;
int n;
if (lwsgs_lookup_user(vhd, username, &u))
return -1;
lwsl_info("user %s found, salt '%s'\n", username, u.pwsalt.id);
/* [password in ascii][salt] */
n = lws_snprintf((char *)buffer, sizeof(buffer) - 1,
"%s-%s-%s", password, vhd->confounder, u.pwsalt.id);
/* sha256sum of password + salt */
/* sha1sum of password + salt */
lws_SHA1(buffer, n, hash_bin.bin);
sha1_to_lwsgw_hash(&hash_bin.bin[0], &hash);
if (lws_genhash_init(&hash_ctx, LWS_GENHASH_TYPE_SHA256) ||
lws_genhash_update(&hash_ctx, password, strlen(password)) ||
lws_genhash_update(&hash_ctx, "-", 1) ||
lws_genhash_update(&hash_ctx, vhd->confounder, strlen(vhd->confounder)) ||
lws_genhash_update(&hash_ctx, "-", 1) ||
lws_genhash_update(&hash_ctx, u.pwsalt.id, strlen(u.pwsalt.id)) ||
lws_genhash_destroy(&hash_ctx, hash_bin.bin)) {
lws_genhash_destroy(&hash_ctx, NULL);
return 1;
}
sha256_to_lwsgw_hash(&hash_bin.bin[0], &hash);
return !!strcmp(hash.id, u.pwhash.id);
}
@ -408,11 +420,9 @@ int
lwsgs_hash_password(struct per_vhost_data__gs *vhd,
const char *password, struct lwsgs_user *u)
{
unsigned char sid_rand[32];
struct lws_genhash_ctx hash_ctx;
lwsgw_hash_bin hash_bin;
lwsgw_hash hash;
unsigned char sid_rand[20];
unsigned char buffer[150];
int n;
/* create a random salt as big as the hash */
@ -422,23 +432,31 @@ lwsgs_hash_password(struct per_vhost_data__gs *vhd,
lwsl_err("Problem getting random for salt\n");
return 1;
}
sha1_to_lwsgw_hash(sid_rand, &u->pwsalt);
sha256_to_lwsgw_hash(sid_rand, &u->pwsalt);
/*
if (lws_get_random(vhd->context, sid_rand,
sizeof(sid_rand)) !=
sizeof(sid_rand)) {
lwsl_err("Problem getting random for token\n");
return 1;
}
sha1_to_lwsgw_hash(sid_rand, &hash);
sha256_to_lwsgw_hash(sid_rand, &hash);
*/
/* sha256sum of password + salt */
/* [password in ascii][salt] */
n = lws_snprintf((char *)buffer, sizeof(buffer) - 1,
"%s-%s-%s", password, vhd->confounder, u->pwsalt.id);
if (lws_genhash_init(&hash_ctx, LWS_GENHASH_TYPE_SHA256) ||
lws_genhash_update(&hash_ctx, password, strlen(password)) ||
lws_genhash_update(&hash_ctx, "-", 1) ||
lws_genhash_update(&hash_ctx, vhd->confounder, strlen(vhd->confounder)) ||
lws_genhash_update(&hash_ctx, "-", 1) ||
lws_genhash_update(&hash_ctx, u->pwsalt.id, strlen(u->pwsalt.id)) ||
lws_genhash_destroy(&hash_ctx, hash_bin.bin)) {
lws_genhash_destroy(&hash_ctx, NULL);
/* sha1sum of password + salt */
lws_SHA1(buffer, n, hash_bin.bin);
sha1_to_lwsgw_hash(&hash_bin.bin[0], &u->pwhash);
return 1;
}
sha256_to_lwsgw_hash(&hash_bin.bin[0], &u->pwhash);
return 0;
}

View file

@ -225,8 +225,7 @@ callback_post_demo(struct lws *wsi, enum lws_callback_reasons reason,
/* first send the headers ... */
n = lws_write(wsi, start, lws_ptr_diff(p, start),
LWS_WRITE_HTTP_HEADERS |
LWS_WRITE_H2_STREAM_END);
LWS_WRITE_HTTP_HEADERS);
if (n < 0)
goto bail;

View file

@ -29,13 +29,8 @@ killall wstest 2>/dev/null
#
# 2.10 / 2.11: There is no requirement to handle multiple PING / PONG
# in flight in RFC6455. lws doesn't waste memory on it
# since it is useless.
#
# 12.3.1 / 12.3.2
# 12.4.* / 12.5.*: Autobahn has been broken for these tests since Aug 2017
# https://github.com/crossbario/autobahn-testsuite/issues/71
# in flight on a single connection in RFC6455. lws doesn't
# waste memory on supporting it since it is useless.
cat << EOF >fuzzingclient.json
{
@ -45,7 +40,7 @@ cat << EOF >fuzzingclient.json
"url": "ws://127.0.0.1:9001"
}
],
"cases": ["*"],
"cases": [ "12.2.13" ],
"exclude-cases": ["2.10", "2.11" ],
"exclude-agent-cases": {}
}