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

plugins: generalize and provide public api

Move the common plugin scanning dir stuff to be based on lws_dir, which
already builds for windows.  Previously this was done via dirent for unix
and libuv for windows.

Reduce the dl plat stuff to just wrap instantiation and destruction of
dynlibs, establish common code in lib/misc/dir.c for plugin scanning
itself.

Migrate the libuv windows dl stuff to windows-plugins.c, so that he's
available even if later libuv loop support becomes and event lib plugin.

Remove the existing api exports scheme for plugins, just export a const struct
now which has a fixed header type but then whatever you want afterwards depending
on the class / purpose of the plugin.  Place a "class" string in the header so
there can be different kinds of plugins implying different types exported.

Make the plugin apis public and add support for filter by class string, and
per instantation / destruction callbacks so the subclassed header type can
do its thing for the plugin class.  The user provides a linked-list base
for his class of plugins, so he can manage them completely separately and
in user code / user export types.

Rip out some last hangers-on from generic sessions / tables.

This is all aimed at making the plugins support general enough so it can
provide event lib plugins later.
This commit is contained in:
Andy Green 2020-08-27 09:34:35 +01:00
parent 3b9e468516
commit d98101d1e3
79 changed files with 541 additions and 5214 deletions

View file

@ -1,7 +1,7 @@
Notes about coding with lws
===========================
@section era Old lws and lws v2.0
@section era Old lws and lws v2.0+
Originally lws only supported the "manual" method of handling everything in the
user callback found in test-server.c / test-server-http.c.

View file

@ -1,373 +0,0 @@
Notes about generic-sessions Plugin
===================================
@section gseb Enabling lwsgs for build
Enable at CMake with -DLWS_WITH_GENERIC_SESSIONS=1
This also needs sqlite3 (libsqlite3-dev or similar package)
@section gsi lwsgs Introduction
The generic-sessions protocol plugin provides cookie-based login
authentication for lws web and ws connections.
The plugin handles everything about generic account registration,
email verification, lost password, account deletion, and other generic account
management.
Other code, in another eg, ws protocol handler, only needs very high-level
state information from generic-sessions, ie, which user the client is
authenticated as. Everything underneath is managed in generic-sessions.
- random 20-byte session id managed in a cookie
- all information related to the session held at the server, nothing managed clientside
- sqlite3 used at the server to manage active sessions and users
- defaults to creating anonymous sessions with no user associated
- admin account (with user-selectable username) is defined in config with a SHA-1 of the password; rest of the accounts are in sqlite3
- user account passwords stored as salted SHA-1 with additional confounder
only stored in the JSON config, not the database
- login, logout, register account + email verification built-in with examples
- in a mount, some file suffixes (ie, .js) can be associated with a protocol for the purposes of rewriting symbolnames. These are read-only copies of logged-in server state.
- When your page fetches .js or other rewritten files from that mount, "$lwsgs_user" and so on are rewritten on the fly using chunked transfer encoding
- Eliminates server-side scripting with a few rewritten symbols and
javascript on client side
- 32-bit bitfield for authentication sectoring, mounts can provide a mask on the loggin-in session's associated server-side bitfield that must be set for access.
- No code (just config) required for, eg, private URL namespace that requires login to access.
@section gsin Lwsgs Integration to HTML
Only three steps are needed to integrate lwsgs in your HTML.
1) lwsgs HTML UI is bundled with the javascript it uses in `lwsgs.js`, so
import that script file in your head section
2) define an empty div of id "lwsgs" somewhere
3) Call lwsgs_initial() in your page
That's it. An example is below
```
<html>
<head>
<script src="lwsgs.js"></script>
<style>
.body { font-size: 12 }
.gstitle { font-size: 18 }
</style>
</head>
<body style="background-image:url(seats.jpg)">
<table style="width:100%;transition: max-height 2s;">
<tr>
<td style="vertical-align:top;text-align:left;width=200px">
<img src="lwsgs-logo.png">
</td>
<td style="vertical-align:top;float:right">
<div id=lwsgs style="text-align:right;background-color: rgba(255, 255, 255, 0.8);"></div>
</td>
</tr>
</table>
</form>
<script>lwsgs_initial();</script>
</body>
</html>
```
@section gsof Lwsgs Overall Flow@
When the protocol is initialized, it gets per-vhost information from the config, such
as where the sqlite3 databases are to be stored. The admin username and sha-1 of the
admin password are also taken from here.
In the mounts using protocol-generic-sessions, a cookie is maintained against any requests; if no cookie was active on the initial request a new session is
created with no attached user.
So there should always be an active session after any transactions with the server.
In the example html going to the mount /lwsgs loads a login / register page as the default.
The <form> in the login page contains 'next url' hidden inputs that let the html 'program' where the form handler will go after a successful admin login, a successful user login and a failed login.
After a successful login, the sqlite record at the server for the current session is updated to have the logged-in username associated with it.
@section gsconf Lwsgs Configuration
"auth-mask" defines the authorization sector bits that must be enabled on the session to gain access.
"auth-mask" 0 is the default.
- b0 is set if you are logged in as a user at all.
- b1 is set if you are logged in with the user configured to be admin
- b2 is set if the account has been verified (the account configured for admin is always verified)
- b3 is set if your session just did the forgot password flow successfully
```
{
# things in here can always be served
"mountpoint": "/lwsgs",
"origin": "file:///usr/share/libwebsockets-test-server/generic-sessions",
"origin": "callback://protocol-lws-messageboard",
"default": "generic-sessions-login-example.html",
"auth-mask": "0",
"interpret": {
".js": "protocol-lws-messageboard"
}
}, {
# things in here can only be served if logged in as a user
"mountpoint": "/lwsgs/needauth",
"origin": "file:///usr/share/libwebsockets-test-server/generic-sessions/needauth",
"origin": "callback://protocol-lws-messageboard",
"default": "generic-sessions-login-example.html",
"auth-mask": "5", # logged in as a verified user
"interpret": {
".js": "protocol-lws-messageboard"
}
}, {
# things in here can only be served if logged in as admin
"mountpoint": "/lwsgs/needadmin",
"origin": "file:///usr/share/libwebsockets-test-server/generic-sessions/needadmin",
"origin": "callback://protocol-lws-messageboard",
"default": "generic-sessions-login-example.html",
"auth-mask": "7", # b2 = verified (by email / or admin), b1 = admin, b0 = logged in with any user name
"interpret": {
".js": "protocol-lws-messageboard"
}
}
```
Note that the name of the real application protocol that uses generic-sessions
is used, not generic-sessions itself.
The vhost configures the storage dir, admin credentials and session cookie lifetimes:
```
"ws-protocols": [{
"protocol-generic-sessions": {
"status": "ok",
"admin-user": "admin",
# create the pw hash like this (for the example pw, "jipdocesExunt" )
# $ echo -n "jipdocesExunt" | sha1sum
# 046ce9a9cca769e85798133be06ef30c9c0122c9 -
#
# Obviously ** change this password hash to a secret one before deploying **
#
"admin-password-sha1": "046ce9a9cca769e85798133be06ef30c9c0122c9",
"session-db": "/var/www/sessions/lws.sqlite3",
"timeout-idle-secs": "600",
"timeout-anon-idle-secs": "1200",
"timeout-absolute-secs": "6000",
# the confounder is part of the salted password hashes. If this config
# file is in a 0700 root:root dir, an attacker with apache credentials
# will have to get the confounder out of the process image to even try
# to guess the password hashes.
"confounder": "Change to <=31 chars of junk",
"email-from": "noreply@example.com",
"email-smtp-ip": "127.0.0.1",
"email-expire": "3600",
"email-helo": "myhost.com",
"email-contact-person": "Set Me <real-person@email.com>",
"email-confirm-url-base": "http://localhost:7681/lwsgs"
}
```
The email- related settings control generation of automatic emails for
registration and forgotten password.
- `email-from`: The email address automatic emails are sent from
- `email-smtp-ip`: Normally 127.0.0.1, if you have a suitable server on port
25 on your lan you can use this instead here.
- `email-expire`: Seconds that links sent in email will work before being
deleted
- `email-helo`: HELO to use when communicating with your SMTP server
- `email-contact-person`: mentioned in the automatic emails as a human who can
answer questions
- `email-confirm-url-base`: the URL to start links with in the emails, so the
recipient can get back to the web server
The real protocol that makes use of generic-sessions must also be listed and
any configuration it needs given
```
"protocol-lws-messageboard": {
"status": "ok",
"message-db": "/var/www/sessions/messageboard.sqlite3"
},
```
Notice the real application uses his own sqlite db, no details about how
generic-sessions works or how it stores data are available to it.
@section gspwc Lwsgs Password Confounder
You can also define a per-vhost confounder shown in the example above, used
when aggregating the password with the salt when it is hashed. Any attacker
will also need to get the confounder along with the database, which you can
make harder by making the config dir only eneterable / readable by root.
@section gsprep Lwsgs Preparing the db directory
You will have to prepare the db directory so it's suitable for the lwsws user to use,
that usually means apache, eg
```
# mkdir -p /var/www/sessions
# chown root:apache /var/www/sessions
# chmod 770 /var/www/sessions
```
@section gsrmail Lwsgs Email configuration
lwsgs will can send emails by talking to an SMTP server on localhost:25. That
will usually be sendmail or postfix, you should confirm that works first by
itself using the `mail` application to send on it.
lwsgs has been tested on stock Fedora sendmail and postfix.
@section gsap Lwsgs Integration with another protocol
lwsgs is designed to provide sessions and accounts in a standalone and generic way.
But it's not useful by itself, there will always be the actual application who wants
to make use of generic-sessions features.
We provide the "messageboard" plugin as an example of how to integrate with
your actual application protocol.
The basic approach is the 'real' protocol handler (usually a plugin itself)
subclasses the generic-sessions plugin and calls through to it by default.
The "real" protocol handler entirely deals with ws-related stuff itself, since
generic-sessions does not use ws. But for
- LWS_CALLBACK_HTTP
- LWS_CALLBACK_HTTP_BODY
- LWS_CALLBACK_HTTP_BODY_COMPLETION
- LWS_CALLBACK_HTTP_DROP_PROTOCOL
the "real" protocol handler checks if it recognizes the activity (eg, his own
POST form URL) and if not, passes stuff through to the generic-sessions protocol callback to handle it. To simplify matters the real protocol can just pass
through any unhandled messages to generic-sessions.
The "real" protocol can get a pointer to generic-sessions protocol on the
same vhost using
```
vhd->gsp = lws_vhost_name_to_protocol(vhd->vh, "protocol-generic-sessions");
```
The "real" protocol must also arrange generic-sessions per_session_data in his
own per-session allocation. To allow keeping generic-sessions opaque, the
real protocol must allocate that space at runtime, using the pss size
the generic-sessions protocol struct exposes
```
struct per_session_data__myapp {
void *pss_gs;
...
pss->pss_gs = malloc(vhd->gsp->per_session_data_size);
```
The allocation reserved for generic-sessions is then used as user_space when
the real protocol calls through to the generic-sessions callback
```
vhd->gsp->callback(wsi, reason, &pss->pss_gs, in, len);
```
In that way the "real" protocol can subclass generic-sessions functionality.
To ease management of these secondary allocations, there are callbacks that
occur when a wsi binds to a protocol and when the binding is dropped. These
should be used to malloc and free and kind of per-connection
secondary allocations.
```
case LWS_CALLBACK_HTTP_BIND_PROTOCOL:
if (!pss || pss->pss_gs)
break;
pss->pss_gs = malloc(vhd->gsp->per_session_data_size);
if (!pss->pss_gs)
return -1;
memset(pss->pss_gs, 0, vhd->gsp->per_session_data_size);
break;
case LWS_CALLBACK_HTTP_DROP_PROTOCOL:
if (vhd->gsp->callback(wsi, reason, pss ? pss->pss_gs : NULL, in, len))
return -1;
if (pss->pss_gs) {
free(pss->pss_gs);
pss->pss_gs = NULL;
}
break;
```
#section gsapsib Getting session-specific information from another protocol
At least at the time when someone tries to upgrade an http(s) connection to
ws(s) with your real protocol, it is necessary to confirm the cookie the http(s)
connection has with generic-sessions and find out his username and other info.
Generic sessions lets another protocol check it again by calling his callback,
and lws itself provides a generic session info struct to pass the related data
```
struct lws_session_info {
char username[32];
char email[100];
char ip[72];
unsigned int mask;
char session[42];
};
struct lws_session_info sinfo;
...
vhd->gsp->callback(wsi, LWS_CALLBACK_SESSION_INFO,
&pss->pss_gs, &sinfo, 0);
```
After the call to generic-sessions, the results can be
- all the strings will be zero-length and .mask zero, there is no usable cookie
- only .ip and .session are set: the cookie is OK but no user logged in
- all the strings contain information about the logged-in user
the real protocol can use this to reject attempts to open ws connections from
http connections that are not authenticated; afterwards there's no need to
check the ws connection auth status again.

View file

@ -1,219 +0,0 @@
Notes about generic-table
=========================
@section gtint What is generic-table?
Generic-table is a JSON schema and client-side JS file that makes it easy to
display live, table structured HTML over a ws link.
An example plugin and index.html using it are provided, but lwsgt itself doesn't
have its own plugin, it's just a JSON schema and client-side JS that other
plugins can use to simplify displaying live, table-based data without having
to reinvent the wheel each time.
The ws protocol sends JSON describing the table, and then JSON updating the table
contents when it chooses, the brower table is updated automatically, live.
\image html lwsgt-overview.png
- Example protocol plugin (displays directory contents): https://github.com/warmcat/libwebsockets/tree/master/plugins/generic-table/protocol_table_dirlisting.c
- Example HTML: https://github.com/warmcat/libwebsockets/tree/master/plugins/generic-table/assets/index.html
- lwsgt.js (client-side table rendering / ws link management): https://github.com/warmcat/libwebsockets/tree/master/plugins/generic-table/assets/lwsgt.js
@section gteb Enabling for build
Enable the demo plugin at CMake with -DLWS_WITH_PLUGINS=1
@section gtinth Integrating with your html
- In your HEAD section, include lwsgt.js
```
<script src="lwsgt.js"></script>
```
- Also in your HEAD section, style the lwsgt CSS, eg
```
<style>
.lwsgt_title { font-size: 24; text-align:center }
.lwsgt_breadcrumbs { font-size: 18; text-align:left }
.lwsgt_table { font-size: 14; padding:12px; margin: 12px; align:center }
.lwsgt_hdr { font-size: 18; text-align:center;
background-color: rgba(40, 40, 40, 0.8); color: white }
.lwsgt_tr { padding: 10px }
.lwsgt_td { padding: 3px }
</style>
```
You can skip this but the result will be less beautiful until some CSS is
provided.
- In your body section, declare a div with an id (can be whatever you want)
```
<tr><td><div id="lwsgt1" class="group1"></div></td></tr>
```
lwsgt JS will put its content there.
- Finally in a <script> at the end of your page, instantiate lwsgt and
provide a custom callback for clickable links
```
<script>
var v1 = new lwsgt_initial("Dir listing demo",
"protocol-lws-table-dirlisting",
"lwsgt1", "lwsgt_dir_click", "v1");
function lwsgt_dir_click(gt, u, col, row)
{
if (u[0] == '=') { /* change directory */
window[gt].lwsgt_ws.send(u.substring(1, u.length));
return;
}
var win = window.open(u, '_blank');
win.focus();
}
</script>
```
In the callback, you can recover the ws object by `window[gt].lwsgt_ws`.
@section gtc Lwsgt constructor
To instantiate the ws link and lwsgt instance, your HTML must call a lwsgt
constructor for each region on the page managed by lwsgt.
`var myvar = new lwsgt_initial(title, ws_protocol, div_id, click_cb, myvar);`
All of the arguments are strings.
| Parameter | Description |
|-----------------|---------------------------------------------------------|
| title | Title string to go above the table |
| ws_protocol | Protocol name string to use when making ws connection |
| div_id | HTML id of div to fill with content |
| click_cb | Callback function name string to handle clickable links |
| myvar | Name of var used to hold this instantiation globally |
Note "myvar" is needed so it can be passed to the click handling callback.
@section gtclick Lwsgt click handling function
When a clickable link produced by lwsgt is clicked, the function named in the
click_cb parameter to lwsgt_initial is called.
That function is expected to take four parameters, eg
`function lwsgt_dir_click(gt, u, col, row)`
| Parameter | Description |
|------- ---|-----------------------------------------------------------|
| gt | Name of global var holding this lwsgt context (ie, myvar) |
| u | Link "url" string |
| col | Table column number link is from |
| row | Table row number link is from |
@section gtgj Generic-table JSON
### Column layout
When the ws connection is established, the protocol should send a JSON message
describing the table columns. For example
```
"cols": [
{ "name": "Date" },
{ "name": "Size", "align": "right" },
{ "name": "Icon" },
{ "name": "Name", "href": "uri"},
{ "name": "uri", "hide": "1" }
]
}
```
- This describes 5 columns
- Only four columns (not "uri") should be visible
- "Name" should be presented as a clickable link using "uri" as the
destination, when a "uri" field is presented.
- "Size" field should be presented aligned to the right
### Breadcrumbs
When a view is hierarchical, it's useful to provide a "path" with links back
in the "path", known as "breadcrumbs".
Elements before the last one should provide a "url" member as well as the
displayable name, which is used to create the link destination.
The last element, being the current displayed page should not have a url
member and be displayed without link style.
```
"breadcrumbs":[{"name":"top", "url": "/" }, {"name":"mydir"}]
```
### Table data
The actual file data consists of an array of rows, containing the columns
mentioned in the original "cols" section.
```
"data":[
{
"Icon":" ",
"Date":"2015-Feb-06 03:08:35 +0000",
"Size":"1406",
"uri":"./serve//favicon.ico",
"Name":"favicon.ico"
}
]
```
@section gtdirl Setting up protocol-lws-table-dirlisting
The example protocol needs two mounts, one to provide the index.html, js and
the protocol itself
```
{
"mountpoint": "/dirtest",
"origin": "file:///usr/share/libwebsockets-test-server/generic-table",
"origin": "callback://protocol-lws-table-dirlisting",
"default": "index.html",
"pmo": [{
"dir": "/usr/share/libwebsockets-test-server"
}]
},
```
The protocol wants a per-mount option (PMO) to tell it the base directory it
is serving from, named "dir".
The other mount is there to simply serve items that get clicked on from the
table in a secure way
```
{
"mountpoint": "/dirtest/serve",
"origin": "file:///usr/share/libwebsockets-test-server",
"default": "index.html"
},
```
This last bit is not related to using lwsgt itself.

View file

@ -546,7 +546,6 @@ struct lws;
#include <libwebsockets/lws-ws-state.h>
#include <libwebsockets/lws-ws-ext.h>
#include <libwebsockets/lws-protocols-plugins.h>
#include <libwebsockets/lws-plugin-generic-sessions.h>
#include <libwebsockets/lws-context-vhost.h>

View file

@ -1,75 +0,0 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
/*! \defgroup generic-sessions plugin: generic-sessions
* \ingroup Protocols-and-Plugins
*
* ##Plugin Generic-sessions related
*
* generic-sessions plugin provides a reusable, generic session and login /
* register / forgot password framework including email verification.
*/
///@{
#define LWSGS_EMAIL_CONTENT_SIZE 16384
/**< Maximum size of email we might send */
/* SHA-1 binary and hexified versions */
/** typedef struct lwsgw_hash_bin */
typedef struct { unsigned char bin[32]; /**< binary representation of hash */} lwsgw_hash_bin;
/** typedef struct lwsgw_hash */
typedef struct { char id[65]; /**< ascii hex representation of hash */ } lwsgw_hash;
/** enum lwsgs_auth_bits */
enum lwsgs_auth_bits {
LWSGS_AUTH_LOGGED_IN = 1, /**< user is logged in as somebody */
LWSGS_AUTH_ADMIN = 2, /**< logged in as the admin user */
LWSGS_AUTH_VERIFIED = 4, /**< user has verified his email */
LWSGS_AUTH_FORGOT_FLOW = 8, /**< just completed "forgot password" */
};
/** struct lws_session_info - information about user session status */
struct lws_session_info {
char username[32]; /**< username logged in as, or empty string */
char email[100]; /**< email address associated with login, or empty string */
char ip[72]; /**< ip address session was started from */
unsigned int mask; /**< access rights mask associated with session
* see enum lwsgs_auth_bits */
char session[42]; /**< session id string, usable as opaque uid when not logged in */
};
/** enum lws_gs_event */
enum lws_gs_event {
LWSGSE_CREATED, /**< a new user was created */
LWSGSE_DELETED /**< an existing user was deleted */
};
/** struct lws_gs_event_args */
struct lws_gs_event_args {
enum lws_gs_event event; /**< which event happened */
const char *username; /**< which username the event happened to */
const char *email; /**< the email address of that user */
};
///@}

View file

@ -196,34 +196,107 @@ lws_protocol_init(struct lws_context *context);
#ifdef LWS_WITH_PLUGINS
/* PLUGINS implies LIBUV */
#define LWS_PLUGIN_API_MAGIC 190
#define LWS_PLUGIN_API_MAGIC 180
/*
* Abstract plugin header for any kind of plugin class, always at top of
* actual class plugin export type.
*
* The export type object must be exported with the same name as the plugin
* file, eg, libmyplugin.so must export a const one of these as the symbol
* "myplugin".
*
* That is the only expected export from the plugin.
*/
typedef struct lws_plugin_header {
const char *name;
const char *_class;
unsigned int api_magic;
/* set to LWS_PLUGIN_API_MAGIC at plugin build time */
/* plugin-class specific superclass data follows */
} lws_plugin_header_t;
/*
* "lws_protocol_plugin" class export, for lws_protocol implementations done
* as plugins
*/
typedef struct lws_plugin_protocol {
lws_plugin_header_t hdr;
/** struct lws_plugin_capability - how a plugin introduces itself to lws */
struct lws_plugin_capability {
unsigned int api_magic; /**< caller fills this in, plugin fills rest */
const struct lws_protocols *protocols; /**< array of supported protocols provided by plugin */
int count_protocols; /**< how many protocols */
const struct lws_extension *extensions; /**< array of extensions provided by plugin */
int count_protocols; /**< how many protocols */
int count_extensions; /**< how many extensions */
};
} lws_plugin_protocol_t;
typedef int (*lws_plugin_init_func)(struct lws_context *,
struct lws_plugin_capability *);
typedef int (*lws_plugin_destroy_func)(struct lws_context *);
/** struct lws_plugin */
/*
* This is the dynamic, runtime created part of the plugin instantiation.
* These are kept in a linked-list and destroyed with the context.
*/
struct lws_plugin {
struct lws_plugin *list; /**< linked list */
const lws_plugin_header_t *hdr;
union {
#if defined(LWS_WITH_LIBUV)
#if (UV_VERSION_MAJOR > 0)
uv_lib_t lib; /**< shared library pointer */
uv_lib_t lib; /**< shared library pointer */
#endif
void *l; /**< so we can compile on ancient libuv */
char name[64]; /**< name of the plugin */
struct lws_plugin_capability caps; /**< plugin capabilities */
#endif
void *l; /**< */
} u;
};
typedef int (*each_plugin_cb_t)(struct lws_plugin *p, void *user);
/**
* lws_plugins_init() - dynamically load plugins of matching class from dirs
*
* \param pplugin: pointer to linked-list for this kind of plugin
* \param d: array of directory paths to look in
* \param _class: class string that plugin must declare
* \param filter: NULL, or a string that must appear after the third char of the plugin filename
* \param each: NULL, or each_plugin_cb_t callback for each instantiated plugin
* \param each_user: pointer passed to each callback
*
* Allows you to instantiate a class of plugins to a specified linked-list.
* The each callback allows you to init each inistantiated callback and pass a
* pointer each_user to it.
*
* To take down the plugins, pass a pointer to the linked-list head to
* lws_plugins_destroy.
*
* This is used for lws protocol plugins but you can define your own plugin
* class name like "mypluginclass", declare it in your plugin headers, and load
* your own plugins to your own list using this api the same way.
*/
LWS_VISIBLE LWS_EXTERN int
lws_plugins_init(struct lws_plugin **pplugin, const char * const *d,
const char *_class, const char *filter,
each_plugin_cb_t each, void *each_user);
/**
* lws_plugins_destroy() - dynamically unload list of plugins
*
* \param pplugin: pointer to linked-list for this kind of plugin
* \param each: NULL, or each_plugin_cb_t callback for each instantiated plugin
* \param each_user: pointer passed to each callback
*
* Allows you to destroy a class of plugins from a specified linked-list
* created by a call to lws_plugins_init().
*
* The each callback allows you to deinit each inistantiated callback and pass a
* pointer each_user to it, just before its footprint is destroyed.
*/
LWS_VISIBLE LWS_EXTERN int
lws_plugins_destroy(struct lws_plugin **pplugin, each_plugin_cb_t each,
void *each_user);
#endif
///@}

View file

@ -1158,11 +1158,13 @@ lws_libuv_closehandle(struct lws *wsi);
int
lws_libuv_check_watcher_active(struct lws *wsi);
LWS_VISIBLE LWS_EXTERN int
lws_plat_plugins_init(struct lws_context * context, const char * const *d);
const lws_plugin_header_t *
lws_plat_dlopen(struct lws_plugin **pplugin, const char *libpath,
const char *sofilename, const char *_class,
each_plugin_cb_t each, void *each_user);
LWS_VISIBLE LWS_EXTERN int
lws_plat_plugins_destroy(struct lws_context * context);
int
lws_plat_destroy_dl(struct lws_plugin *p);
struct lws *
lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd);

View file

@ -685,15 +685,18 @@ lws_create_vhost(struct lws_context *context,
#ifdef LWS_WITH_PLUGINS
if (plugin) {
while (plugin) {
for (n = 0; n < plugin->caps.count_protocols; n++) {
const lws_plugin_protocol_t *plpr =
(const lws_plugin_protocol_t *)plugin->hdr;
for (n = 0; n < plpr->count_protocols; n++) {
/*
* for compatibility's sake, no pvo implies
* allow all protocols
*/
if (f || lws_vhost_protocol_options(vh,
plugin->caps.protocols[n].name)) {
plpr->protocols[n].name)) {
memcpy(&lwsp[m],
&plugin->caps.protocols[n],
&plpr->protocols[n],
sizeof(struct lws_protocols));
m++;
vh->count_protocols++;

View file

@ -111,6 +111,7 @@
#define strerror(x) ""
#endif
/*
*
* ------ private platform defines ------

View file

@ -312,170 +312,6 @@ lws_libuv_check_watcher_active(struct lws *wsi)
return uv_is_active(h);
}
#if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0)
int
lws_uv_plugins_init(struct lws_context *context, const char * const *d)
{
struct lws_plugin_capability lcaps;
struct lws_plugin *plugin;
lws_plugin_init_func initfunc;
int m, ret = 0;
void *v;
uv_dirent_t dent;
uv_fs_t req;
char path[256];
uv_lib_t lib;
int pofs = 0;
#if defined(__MINGW32__) || !defined(WIN32)
pofs = 3;
#endif
lib.errmsg = NULL;
lib.handle = NULL;
uv_loop_init(&context->uv.loop);
lwsl_notice(" Plugins:\n");
while (d && *d) {
lwsl_notice(" Scanning %s\n", *d);
m =uv_fs_scandir(&context->uv.loop, &req, *d, 0, NULL);
if (m < 1) {
lwsl_err("Scandir on %s failed\n", *d);
d++;
continue;
}
while (uv_fs_scandir_next(&req, &dent) != UV_EOF) {
if (strlen(dent.name) < 7)
continue;
lwsl_notice(" %s\n", dent.name);
lws_snprintf(path, sizeof(path) - 1, "%s/%s", *d,
dent.name);
if (uv_dlopen(path, &lib)) {
uv_dlerror(&lib);
lwsl_err("Error loading DSO: %s\n", lib.errmsg);
uv_dlclose(&lib);
goto bail;
}
/* we could open it, can we get his init function? */
#if !defined(WIN32) && !defined(__MINGW32__)
m = lws_snprintf(path, sizeof(path) - 1, "init_%s",
dent.name + pofs /* snip lib... */);
path[m - 3] = '\0'; /* snip the .so */
#else
m = lws_snprintf(path, sizeof(path) - 1, "init_%s",
dent.name + pofs);
path[m - 4] = '\0'; /* snip the .dll */
#endif
if (uv_dlsym(&lib, path, &v)) {
uv_dlerror(&lib);
lwsl_err("%s: Failed to get '%s' on %s: %s\n",
__func__, path, dent.name, lib.errmsg);
uv_dlclose(&lib);
goto bail;
}
initfunc = (lws_plugin_init_func)v;
lcaps.api_magic = LWS_PLUGIN_API_MAGIC;
m = initfunc(context, &lcaps);
if (m) {
lwsl_err("Init %s failed %d\n", dent.name, m);
goto skip;
}
plugin = lws_malloc(sizeof(*plugin), "plugin");
if (!plugin) {
uv_dlclose(&lib);
lwsl_err("OOM\n");
goto bail;
}
plugin->list = context->plugin_list;
context->plugin_list = plugin;
lws_strncpy(plugin->name, dent.name, sizeof(plugin->name));
plugin->lib = lib;
plugin->caps = lcaps;
context->plugin_protocol_count += lcaps.count_protocols;
context->plugin_extension_count += lcaps.count_extensions;
continue;
skip:
uv_dlclose(&lib);
}
bail:
uv_fs_req_cleanup(&req);
d++;
}
return ret;
}
int
lws_uv_plugins_destroy(struct lws_context *context)
{
struct lws_plugin *plugin = context->plugin_list, *p;
lws_plugin_destroy_func func;
char path[256];
int pofs = 0;
void *v;
int m;
#if defined(__MINGW32__) || !defined(WIN32)
pofs = 3;
#endif
if (!plugin)
return 0;
while (plugin) {
p = plugin;
#if !defined(WIN32) && !defined(__MINGW32__)
m = lws_snprintf(path, sizeof(path) - 1, "destroy_%s",
plugin->name + pofs);
path[m - 3] = '\0';
#else
m = lws_snprintf(path, sizeof(path) - 1, "destroy_%s",
plugin->name + pofs);
path[m - 4] = '\0';
#endif
if (uv_dlsym(&plugin->lib, path, &v)) {
uv_dlerror(&plugin->lib);
lwsl_err("Failed to get %s on %s: %s", path,
plugin->name, plugin->lib.errmsg);
} else {
func = (lws_plugin_destroy_func)v;
m = func(context);
if (m)
lwsl_err("Destroying %s failed %d\n",
plugin->name, m);
}
uv_dlclose(&p->lib);
plugin = p->list;
p->list = NULL;
free(p);
}
context->plugin_list = NULL;
while (uv_loop_close(&context->uv.loop))
;
return 0;
}
#endif
static int
elops_init_context_uv(struct lws_context *context,
const struct lws_context_creation_info *info)

View file

@ -286,3 +286,76 @@ lws_dir_rm_rf_cb(const char *dirpath, void *user, struct lws_dir_entry *lde)
#endif
#if defined(LWS_WITH_PLUGINS)
struct lws_plugins_args {
struct lws_plugin **pplugin;
const char *_class;
const char *filter;
each_plugin_cb_t each;
void *each_user;
};
static int
lws_plugins_dir_cb(const char *dirpath, void *user, struct lws_dir_entry *lde)
{
struct lws_plugins_args *pa = (struct lws_plugins_args *)user;
char path[256];
if (strlen(lde->name) < 7)
return 0;
/* if he's given a filter, only match if name + 3 matches it */
if (pa->filter && strncmp(lde->name + 3, pa->filter, strlen(pa->filter)))
return 0;
lws_snprintf(path, sizeof(path) - 1, "%s/%s", dirpath, lde->name);
lwsl_notice(" %s\n", path);
return !lws_plat_dlopen(pa->pplugin, path, lde->name + 3, pa->_class,
pa->each, pa->each_user);
}
int
lws_plugins_init(struct lws_plugin **pplugin, const char * const *d,
const char *_class, const char *filter,
each_plugin_cb_t each, void *each_user)
{
struct lws_plugins_args pa;
pa.pplugin = pplugin;
pa._class = _class;
pa.each = each;
pa.each_user = each_user;
pa.filter = filter;
while (d && *d) {
lws_dir(*d, &pa, lws_plugins_dir_cb);
d++;
}
return 0;
}
int
lws_plugins_destroy(struct lws_plugin **pplugin, each_plugin_cb_t each,
void *each_user)
{
struct lws_plugin *p = *pplugin, *p1;
while (p) {
if (each)
each(p, each_user);
lws_plat_destroy_dl(p);
p1 = p->list;
p->list = NULL;
lws_free(p);
p = p1;
}
*pplugin = NULL;
return 0;
}
#endif

View file

@ -80,6 +80,19 @@ lws_sul_plat_unix(lws_sorted_usec_list_t *sul)
}
#endif
static int
protocol_plugin_cb(struct lws_plugin *pin, void *each_user)
{
struct lws_context *context = (struct lws_context *)each_user;
const lws_plugin_protocol_t *plpr =
(const lws_plugin_protocol_t *)pin->hdr;
context->plugin_protocol_count += plpr->count_protocols;
context->plugin_extension_count += plpr->count_extensions;
return 0;
}
int
lws_plat_init(struct lws_context *context,
const struct lws_context_creation_info *info)
@ -134,7 +147,9 @@ lws_plat_init(struct lws_context *context,
#if defined(LWS_WITH_PLUGINS)
if (info->plugin_dirs)
lws_plat_plugins_init(context, info->plugin_dirs);
lws_plugins_init(&context->plugin_list, info->plugin_dirs,
"lws_protocol_plugin", NULL,
protocol_plugin_cb, context);
#endif
@ -167,9 +182,9 @@ lws_plat_context_early_destroy(struct lws_context *context)
void
lws_plat_context_late_destroy(struct lws_context *context)
{
#ifdef LWS_WITH_PLUGINS
#if defined(LWS_WITH_PLUGINS)
if (context->plugin_list)
lws_plat_plugins_destroy(context);
lws_plugins_destroy(&context->plugin_list, NULL, NULL);
#endif
#if defined(LWS_WITH_NETWORK)
if (context->lws_lookup)

View file

@ -1,7 +1,7 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
* Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@ -35,149 +35,75 @@
#endif
#include <dirent.h>
static int filter(const struct dirent *ent)
const lws_plugin_header_t *
lws_plat_dlopen(struct lws_plugin **pplugin, const char *libpath,
const char *sofilename, const char *_class,
each_plugin_cb_t each, void *each_user)
{
if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
return 0;
return 1;
}
int
lws_plat_plugins_init(struct lws_context * context, const char * const *d)
{
struct lws_plugin_capability lcaps;
struct lws_plugin *plugin;
lws_plugin_init_func initfunc;
struct dirent **namelist;
int n, i, m, ret = 0;
char path[256];
const lws_plugin_header_t *hdr;
struct lws_plugin *pin;
char sym[96];
void *l;
#if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0)
if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV))
return lws_uv_plugins_init(context, d);
#endif
lwsl_notice(" Plugins:\n");
while (d && *d) {
n = scandir(*d, &namelist, filter, alphasort);
if (n < 0) {
lwsl_err("Scandir on %s failed\n", *d);
d++;
continue;
}
for (i = 0; i < n; i++) {
if (strlen(namelist[i]->d_name) < 7)
goto inval;
lwsl_notice(" %s\n", namelist[i]->d_name);
lws_snprintf(path, sizeof(path) - 1, "%s/%s", *d,
namelist[i]->d_name);
l = dlopen(path, RTLD_NOW);
if (!l) {
lwsl_err("Error loading DSO: %s\n", dlerror());
while (i++ < n)
free(namelist[i]);
goto bail;
}
/* we could open it, can we get his init function? */
m = lws_snprintf(path, sizeof(path) - 1, "init_%s",
namelist[i]->d_name + 3 /* snip lib... */);
path[m - 3] = '\0'; /* snip the .so */
initfunc = dlsym(l, path);
if (!initfunc) {
lwsl_err("%s: Failed to get init '%s' on %s: %s\n",
__func__, path, namelist[i]->d_name, dlerror());
goto skip;
}
lcaps.api_magic = LWS_PLUGIN_API_MAGIC;
m = initfunc(context, &lcaps);
if (m) {
lwsl_err("Initializing %s failed %d\n",
namelist[i]->d_name, m);
goto skip;
}
plugin = lws_malloc(sizeof(*plugin), "plugin");
if (!plugin) {
dlclose(l);
lwsl_err("OOM\n");
goto bail;
}
plugin->list = context->plugin_list;
context->plugin_list = plugin;
lws_strncpy(plugin->name, namelist[i]->d_name,
sizeof(plugin->name));
plugin->l = l;
plugin->caps = lcaps;
context->plugin_protocol_count += lcaps.count_protocols;
context->plugin_extension_count += lcaps.count_extensions;
free(namelist[i]);
continue;
skip:
dlclose(l);
inval:
free(namelist[i]);
}
free(namelist);
d++;
}
return 0;
bail:
free(namelist);
return ret;
}
int
lws_plat_plugins_destroy(struct lws_context * context)
{
struct lws_plugin *plugin = context->plugin_list, *p;
lws_plugin_destroy_func func;
char path[256];
int m;
#if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0)
if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV))
return lws_uv_plugins_destroy(context);
#endif
if (strlen(sofilename) < 6)
/* [lib]...[.so] */
return NULL;
if (!plugin)
return 0;
l = dlopen(libpath, RTLD_NOW);
if (!l) {
lwsl_err("%s: Error loading DSO: %s\n", __func__, dlerror());
lwsl_notice("%s\n", __func__);
while (plugin) {
p = plugin;
m = lws_snprintf(path, sizeof(path) - 1, "destroy_%s",
plugin->name + 3);
path[m - 3] = '\0';
func = dlsym(plugin->l, path);
if (!func) {
lwsl_err("Failed to get destroy on %s: %s",
plugin->name, dlerror());
goto next;
}
m = func(context);
if (m)
lwsl_err("Initializing %s failed %d\n",
plugin->name, m);
next:
dlclose(p->l);
plugin = p->list;
p->list = NULL;
free(p);
return NULL;
}
context->plugin_list = NULL;
/* we could open it... can we get his export struct? */
m = lws_snprintf(sym, sizeof(sym) - 1, "%s", sofilename);
if (m < 4)
goto bail;
if (!strcmp(&sym[m - 3], ".so"))
sym[m - 3] = '\0'; /* snip the .so */
return 0;
hdr = (const lws_plugin_header_t *)dlsym(l, sym);
if (!hdr) {
lwsl_err("%s: Failed to get export '%s' from %s: %s\n",
__func__, sym, libpath, dlerror());
goto bail;
}
if (hdr->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("%s: plugin %s has outdated api %d (vs %d)\n",
__func__, libpath, hdr->api_magic,
LWS_PLUGIN_API_MAGIC);
goto bail;
}
if (strcmp(hdr->_class, _class))
goto bail;
pin = lws_malloc(sizeof(*pin), __func__);
if (!pin)
goto bail;
pin->list = *pplugin;
*pplugin = pin;
pin->u.l = l;
pin->hdr = hdr;
if (each)
each(pin, each_user);
return hdr;
bail:
dlclose(l);
return NULL;
}
int
lws_plat_destroy_dl(struct lws_plugin *p)
{
return dlclose(p->u.l);
}

View file

@ -55,6 +55,19 @@ lws_plat_context_early_init(void)
return 1;
}
static int
protocol_plugin_cb(struct lws_plugin *pin, void *each_user)
{
struct lws_context *context = (struct lws_context *)each_user;
const lws_plugin_protocol_t *plpr =
(const lws_plugin_protocol_t *)pin->hdr;
context->plugin_protocol_count += plpr->count_protocols;
context->plugin_extension_count += plpr->count_extensions;
return 0;
}
int
lws_plat_init(struct lws_context *context,
const struct lws_context_creation_info *info)
@ -81,9 +94,11 @@ lws_plat_init(struct lws_context *context,
context->fd_random = 0;
#ifdef LWS_WITH_PLUGINS
#if defined(LWS_WITH_PLUGINS)
if (info->plugin_dirs)
lws_plat_plugins_init(context, info->plugin_dirs);
lws_plat_plugins_init(&context->plugin_list, info->plugin_dirs,
"lws_protocol_plugin",
protocol_plugin_cb, context);
#endif
return 0;
@ -107,6 +122,11 @@ lws_plat_context_late_destroy(struct lws_context *context)
{
int n;
#ifdef LWS_WITH_PLUGINS
if (context->plugin_list)
lws_plugins_destroy(&context->plugin_list);
#endif
for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
if (context->fd_hashtable[n].wsi)
lws_free(context->fd_hashtable[n].wsi);

View file

@ -27,12 +27,106 @@
#endif
#include "private-lib-core.h"
#if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0)
const lws_plugin_header_t *
lws_plat_dlopen(struct lws_plugin **pplugin, const char *libpath,
const char *sofilename, const char *_class,
each_plugin_cb_t each, void *each_user)
{
const lws_plugin_header_t *hdr;
struct lws_plugin *pin;
char sym[96], *dot;
uv_lib_t lib;
void *v;
int m;
lib.errmsg = NULL;
lib.handle = NULL;
if (uv_dlopen(libpath, &lib)) {
uv_dlerror(&lib);
lwsl_err("Error loading DSO: %s\n", lib.errmsg);
uv_dlclose(&lib);
return NULL;
}
/* we could open it... can we get his export struct? */
m = lws_snprintf(sym, sizeof(sym) - 1, "%s", sofilename);
if (m < 4)
goto bail;
dot = strchr(sym, '.');
if (dot)
*dot = '\0'; /* snip the .so or .lib or what-have-you*/
if (uv_dlsym(&lib, sym, &v)) {
uv_dlerror(&lib);
lwsl_err("%s: Failed to get '%s' on %s: %s\n",
__func__, path, dent.name, lib.errmsg);
goto bail;
}
hdr = (const lws_plugin_header_t *)v;
if (hdr->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("%s: plugin %s has outdated api %d (vs %d)\n",
__func__, libpath, hdr->api_magic,
LWS_PLUGIN_API_MAGIC);
goto bail;
}
if (strcmp(hdr->_class, _class))
goto bail;
pin = lws_malloc(sizeof(*pin), __func__);
if (!pin)
goto bail;
pin->list = *pplugin;
*pplugin = pin;
pin->u.lib = lib;
pin->hdr = hdr;
if (each)
each(pin, each_user);
return hdr;
bail:
uv_dlclose(&lib);
return NULL;
}
int
lws_plat_plugins_init(struct lws_context * context, const char * const *d)
lws_plat_destroy_dl(struct lws_plugin *p)
{
return uv_dlclose(&p->u.lib);
}
static int
protocol_plugin_cb(struct lws_plugin *pin, void *each_user)
{
struct lws_context *context = (struct lws_context *)each_user;
const lws_plugin_protocol_t *plpr =
(const lws_plugin_protocol_t *)pin->hdr;
context->plugin_protocol_count += plpr->count_protocols;
context->plugin_extension_count += plpr->count_extensions;
return 0;
}
int
lws_plat_plugins_init(struct lws_context *context, const char * const *d)
{
#if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0)
if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV))
return lws_uv_plugins_init(context, d);
if (info->plugin_dirs) {
uv_loop_init(&context->uv.loop);
lws_plugins_init(&context->plugin_list, info->plugin_dirs,
"lws_protocol_plugin", NULL,
protocol_plugin_cb, context);
}
#endif
return 0;
@ -42,8 +136,12 @@ int
lws_plat_plugins_destroy(struct lws_context * context)
{
#if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0)
if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV))
return lws_uv_plugins_destroy(context);
if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV) &&
context->plugin_list) {
lws_plugins_destroy(&context->plugin_list, NULL, NULL);
while (uv_loop_close(&context->uv.loop))
;
}
#endif
return 0;

View file

@ -1967,11 +1967,14 @@ rops_init_vhost_ws(struct lws_vhost *vh,
sizeof(struct lws_extension) * m);
plugin = vh->context->plugin_list;
while (plugin) {
const lws_plugin_protocol_t *plpr =
(const lws_plugin_protocol_t *)plugin->hdr;
memcpy((struct lws_extension *)&vh->ws.extensions[m],
plugin->caps.extensions,
plpr->extensions,
sizeof(struct lws_extension) *
plugin->caps.count_extensions);
m += plugin->caps.count_extensions;
plpr->count_extensions);
m += plpr->count_extensions;
plugin = plugin->list;
}
} else

View file

@ -238,37 +238,3 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason,
128, \
0, NULL, 0 \
}
#if !defined (LWS_PLUGIN_STATIC)
/* boilerplate needed if we are built as a dynamic plugin */
static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_MINIMAL
};
int
init_protocol_minimal(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
int
destroy_protocol_minimal(struct lws_context *context)
{
return 0;
}
#endif

View file

@ -793,36 +793,3 @@ callback_minimal_dbus_wsproxy(struct lws *wsi, enum lws_callback_reasons reason,
1024, \
0, NULL, 0 \
}
#if !defined (LWS_PLUGIN_STATIC)
/* boilerplate needed if we are built as a dynamic plugin */
static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_MINIMAL_DBUS_WSPROXY
};
int
init_protocol_minimal_dbus_wsproxy(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
int
destroy_protocol_minimal_dbus_wsproxy(struct lws_context *context)
{
return 0;
}
#endif

View file

@ -1,28 +0,0 @@
project(lws-minimal-http-server-generic-sessions C)
cmake_minimum_required(VERSION 2.8)
find_package(libwebsockets CONFIG REQUIRED)
list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR})
include(CheckCSourceCompiles)
include(LwsCheckRequirements)
set(SAMP lws-minimal-http-server-generic-sessions)
set(SRCS minimal-http-server-generic-sessions.c)
set(requirements 1)
require_lws_config(LWS_ROLE_H1 1 requirements)
require_lws_config(LWS_WITH_SERVER 1 requirements)
require_lws_config(LWS_WITH_TLS 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 ${LIBWEBSOCKETS_DEP_LIBS})
add_dependencies(${SAMP} websockets_shared)
else()
target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS})
endif()
endif()

View file

@ -1,26 +0,0 @@
# 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

@ -1,34 +0,0 @@
-----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

@ -1,52 +0,0 @@
-----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

@ -1,202 +0,0 @@
/*
* 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, 0);
lws_context_destroy(context);
return 0;
}

View file

@ -1,11 +0,0 @@
<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

@ -1,5 +0,0 @@
<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

@ -1,21 +0,0 @@
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

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

View file

@ -1,57 +0,0 @@
<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

@ -1,66 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="117.26mm" height="19.676mm" version="1.1" viewBox="0 0 117.26 19.677" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<metadata>
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
</cc:Work>
</rdf:RDF>
</metadata>
<path d="m0-2.6715e-4h117.26v19.677h-117.26z" fill="none"/>
<g transform="matrix(.63895 0 0 .63895 2.5477 3.6562)">
<g transform="matrix(.9517 0 0 .9517 3.2398 -93.904)">
<path d="m9.5909 107.4h2.5567v2.649h-2.5567z"/>
<path d="m12.12 107.36a1.2625 1.2625 0 0 1-1.2625 1.262 1.2625 1.2625 0 0 1-1.2625-1.262 1.2625 1.2625 0 0 1 1.2625-1.262 1.2625 1.2625 0 0 1 1.2625 1.262" stroke-linecap="round" stroke-width="1.0365"/>
<path d="m12.127 110.05a1.2625 1.2625 0 0 1-1.2625 1.262 1.2625 1.2625 0 0 1-1.2625-1.262 1.2625 1.2625 0 0 1 1.2625-1.262 1.2625 1.2625 0 0 1 1.2625 1.262" stroke-linecap="round" stroke-width="1.0365"/>
</g>
<path d="m12.174 13.987a1.2015 1.2015 0 0 1-1.2024 1.2024 1.2015 1.2015 0 0 1-1.2006-1.2024 1.2015 1.2015 0 0 1 1.2006-1.2005 1.2015 1.2015 0 0 1 1.2024 1.2005" stroke-linecap="round" stroke-width=".98647"/>
<path d="m8.2754 5.0474h2.468v5.6755h-2.468z"/>
<path d="m16.25 13.965a1.2015 1.2015 0 0 1-1.2027 1.2005 1.2015 1.2015 0 0 1-1.2004-1.2005 1.2015 1.2015 0 0 1 1.2004-1.2025 1.2015 1.2015 0 0 1 1.2027 1.2025" stroke-linecap="round" stroke-width=".98647"/>
<path d="m19.545 13.928a1.2015 1.2015 0 0 1-1.2025 1.2026 1.2015 1.2015 0 0 1-1.2003-1.2026 1.2015 1.2015 0 0 1 1.2003-1.2005 1.2015 1.2015 0 0 1 1.2025 1.2005" stroke-linecap="round" stroke-width=".98647"/>
<path d="m23.75 13.902a1.2015 1.2015 0 0 1-1.2005 1.2024 1.2015 1.2015 0 0 1-1.2025-1.2024 1.2015 1.2015 0 0 1 1.2025-1.2005 1.2015 1.2015 0 0 1 1.2005 1.2005" stroke-linecap="round" stroke-width=".98647"/>
<path d="m26.249 5.0292a1.2015 1.2015 0 0 1-1.2027 1.2004 1.2015 1.2015 0 0 1-1.2004-1.2004 1.2015 1.2015 0 0 1 1.2004-1.2026 1.2015 1.2015 0 0 1 1.2027 1.2026" stroke-linecap="round" stroke-width=".98647"/>
<g transform="matrix(.9517 0 0 .9517 6.3252 -93.961)">
<path d="m9.5909 107.4h2.5567v2.649h-2.5567z"/>
<path d="m12.12 107.36a1.2625 1.2625 0 0 1-1.2625 1.262 1.2625 1.2625 0 0 1-1.2625-1.262 1.2625 1.2625 0 0 1 1.2625-1.262 1.2625 1.2625 0 0 1 1.2625 1.262" stroke-linecap="round" stroke-width="1.0365"/>
<path d="m12.127 110.05a1.2625 1.2625 0 0 1-1.2625 1.262 1.2625 1.2625 0 0 1-1.2625-1.262 1.2625 1.2625 0 0 1 1.2625-1.262 1.2625 1.2625 0 0 1 1.2625 1.262" stroke-linecap="round" stroke-width="1.0365"/>
</g>
<g transform="matrix(.9517 0 0 .9517 9.3806 -93.988)">
<path d="m9.5909 107.4h2.5567v2.649h-2.5567z"/>
<path d="m12.12 107.36a1.2625 1.2625 0 0 1-1.2625 1.262 1.2625 1.2625 0 0 1-1.2625-1.262 1.2625 1.2625 0 0 1 1.2625-1.262 1.2625 1.2625 0 0 1 1.2625 1.262" stroke-linecap="round" stroke-width="1.0365"/>
<path d="m12.127 110.05a1.2625 1.2625 0 0 1-1.2625 1.262 1.2625 1.2625 0 0 1-1.2625-1.262 1.2625 1.2625 0 0 1 1.2625-1.262 1.2625 1.2625 0 0 1 1.2625 1.262" stroke-linecap="round" stroke-width="1.0365"/>
</g>
<g transform="matrix(.9517 0 0 .9517 13.506 -94.006)">
<path d="m9.5909 107.4h2.5567v2.649h-2.5567z"/>
<path d="m12.12 107.36a1.2625 1.2625 0 0 1-1.2625 1.262 1.2625 1.2625 0 0 1-1.2625-1.262 1.2625 1.2625 0 0 1 1.2625-1.262 1.2625 1.2625 0 0 1 1.2625 1.262" stroke-linecap="round" stroke-width="1.0365"/>
<path d="m12.127 110.05a1.2625 1.2625 0 0 1-1.2625 1.262 1.2625 1.2625 0 0 1-1.2625-1.262 1.2625 1.2625 0 0 1 1.2625-1.262 1.2625 1.2625 0 0 1 1.2625 1.262" stroke-linecap="round" stroke-width="1.0365"/>
</g>
<g transform="matrix(.9517 0 0 .9517 -.82062 -93.74)">
<path d="m9.5909 107.4h2.5567v2.649h-2.5567z"/>
<path d="m12.12 107.36a1.2625 1.2625 0 0 1-1.2625 1.262 1.2625 1.2625 0 0 1-1.2625-1.262 1.2625 1.2625 0 0 1 1.2625-1.262 1.2625 1.2625 0 0 1 1.2625 1.262" stroke-linecap="round" stroke-width="1.0365"/>
<path d="m12.127 110.05a1.2625 1.2625 0 0 1-1.2625 1.262 1.2625 1.2625 0 0 1-1.2625-1.262 1.2625 1.2625 0 0 1 1.2625-1.262 1.2625 1.2625 0 0 1 1.2625 1.262" stroke-linecap="round" stroke-width="1.0365"/>
</g>
<path d="m10.703 5.0413a1.2015 1.2015 0 0 1-1.2006 1.2025 1.2015 1.2015 0 0 1-1.2025-1.2025 1.2015 1.2015 0 0 1 1.2025-1.2004 1.2015 1.2015 0 0 1 1.2006 1.2004" stroke-linecap="round" stroke-width=".98647"/>
</g>
<g transform="matrix(2.6825 0 0 2.6825 -289.72 -275.57)" dominant-baseline="auto" stroke-width=".29098" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal" aria-label="libwebsockets.org">
<path d="m117.05 105.01v2.752h0.224v-2.752z"/>
<path d="m117.95 105.71v2.057h0.223v-2.057zm-0.04-0.695v0.318h0.297v-0.318z"/>
<path d="m118.8 105.01v2.752h0.203l0.02-0.251c0.101 0.157 0.244 0.279 0.649 0.279 0.601 0 0.81-0.307 0.81-1.083 0-0.541-0.09-1.03-0.81-1.03-0.468 0-0.594 0.196-0.649 0.283v-0.95zm0.845 0.87c0.552 0 0.618 0.339 0.618 0.855 0 0.486-0.05 0.852-0.611 0.852-0.426 0-0.632-0.181-0.632-0.852 0-0.597 0.15-0.855 0.625-0.855z"/>
<path d="m120.79 105.71 0.555 2.057h0.314l0.479-1.858 0.482 1.858h0.314l0.551-2.057h-0.23l-0.482 1.879-0.482-1.879h-0.303l-0.486 1.879-0.478-1.879z"/>
<path d="m125.54 106.8v-0.157c0-0.433-0.06-0.964-0.869-0.964-0.824 0-0.891 0.566-0.891 1.079 0 0.688 0.196 1.034 0.926 1.034 0.495 0 0.792-0.178 0.831-0.663h-0.224c-0.01 0.377-0.262 0.464-0.628 0.464-0.611 0-0.688-0.314-0.685-0.793zm-1.54-0.195c0.02-0.374 0.08-0.727 0.667-0.727 0.493 0 0.653 0.21 0.65 0.727z"/>
<path d="m126.04 105.01v2.752h0.203l0.02-0.251c0.101 0.157 0.244 0.279 0.649 0.279 0.601 0 0.81-0.307 0.81-1.083 0-0.541-0.09-1.03-0.81-1.03-0.468 0-0.593 0.196-0.649 0.283v-0.95zm0.845 0.87c0.552 0 0.618 0.339 0.618 0.855 0 0.486-0.05 0.852-0.611 0.852-0.426 0-0.632-0.181-0.632-0.852 0-0.597 0.151-0.855 0.625-0.855z"/>
<path d="m129.86 106.28c0-0.24-0.06-0.604-0.799-0.604-0.426 0-0.814 0.109-0.814 0.601 0 0.381 0.241 0.471 0.489 0.503l0.576 0.08c0.273 0.04 0.381 0.08 0.381 0.338 0 0.315-0.224 0.391-0.618 0.391-0.646 0-0.646-0.223-0.646-0.481h-0.224c0 0.279 0.04 0.684 0.852 0.684 0.37 0 0.856-0.05 0.856-0.608 0-0.415-0.294-0.492-0.486-0.516l-0.607-0.08c-0.234-0.03-0.356-0.07-0.356-0.297 0-0.192 0.06-0.408 0.593-0.408 0.583 0 0.58 0.237 0.58 0.401z"/>
<path d="m130.35 106.74c0 0.594 0.06 1.058 0.908 1.058 0.883 0 0.904-0.51 0.904-1.103 0-0.601-0.108-1.01-0.904-1.01-0.852 0-0.908 0.475-0.908 1.055zm0.908-0.852c0.569 0 0.684 0.213 0.684 0.803 0 0.636-0.05 0.904-0.684 0.904-0.584 0-0.688-0.223-0.688-0.824 0-0.6 0.04-0.883 0.688-0.883z"/>
<path d="m134.12 107.03c0 0.471-0.22 0.565-0.656 0.565-0.496 0-0.667-0.181-0.667-0.838 0-0.782 0.272-0.869 0.677-0.869 0.283 0 0.625 0.06 0.625 0.531h0.22c0.01-0.734-0.639-0.734-0.845-0.734-0.632 0-0.897 0.245-0.897 1.058 0 0.793 0.248 1.055 0.908 1.055 0.468 0 0.834-0.115 0.859-0.768z"/>
<path d="m135.05 106.64v-1.624h-0.22v2.752h0.22v-1.072l1.076 1.072h0.321l-1.149-1.1 1.041-0.957h-0.318z"/>
<path d="m138.48 106.8v-0.157c0-0.433-0.06-0.964-0.87-0.964-0.824 0-0.89 0.566-0.89 1.079 0 0.688 0.195 1.034 0.925 1.034 0.496 0 0.793-0.178 0.831-0.663h-0.223c-0.01 0.377-0.262 0.464-0.629 0.464-0.611 0-0.688-0.314-0.684-0.793zm-1.54-0.195c0.02-0.374 0.08-0.727 0.667-0.727 0.492 0 0.653 0.21 0.649 0.727z"/>
<path d="m139.29 105.71h-0.457v0.206h0.457v1.348c0 0.335 0.07 0.531 0.664 0.531 0.09 0 0.139 0 0.181-0.01v-0.209c-0.06 0-0.136 0.01-0.251 0.01-0.374 0-0.374-0.129-0.374-0.381v-1.292h0.541v-0.206h-0.541v-0.488h-0.22z"/>
<path d="m142.15 106.28c0-0.24-0.06-0.604-0.799-0.604-0.426 0-0.814 0.109-0.814 0.601 0 0.381 0.241 0.471 0.489 0.503l0.576 0.08c0.272 0.04 0.381 0.08 0.381 0.338 0 0.315-0.224 0.391-0.618 0.391-0.646 0-0.646-0.223-0.646-0.481h-0.224c0 0.279 0.04 0.684 0.852 0.684 0.37 0 0.856-0.05 0.856-0.608 0-0.415-0.294-0.492-0.486-0.516l-0.607-0.08c-0.234-0.03-0.356-0.07-0.356-0.297 0-0.192 0.06-0.408 0.593-0.408 0.583 0 0.58 0.237 0.58 0.401z"/>
<path d="m142.76 107.44v0.321h0.293v-0.321z"/>
<path d="m143.54 106.74c0 0.594 0.06 1.058 0.908 1.058 0.883 0 0.904-0.51 0.904-1.103 0-0.601-0.108-1.01-0.904-1.01-0.852 0-0.908 0.475-0.908 1.055zm0.908-0.852c0.569 0 0.684 0.213 0.684 0.803 0 0.636-0.05 0.904-0.684 0.904-0.583 0-0.688-0.223-0.688-0.824 0-0.6 0.04-0.883 0.688-0.883z"/>
<path d="m145.81 105.71v2.057h0.22v-1.337c0-0.542 0.419-0.542 0.569-0.542h0.206v-0.213c-0.37 0-0.576 0-0.775 0.259l-0.01-0.231z"/>
<path d="m149.11 105.62c-0.331 0.01-0.391 0.136-0.429 0.217-0.143-0.14-0.44-0.158-0.646-0.158-0.503 0-0.821 0.14-0.821 0.601 0 0.119 0.02 0.272 0.126 0.398-0.175 0.02-0.265 0.157-0.265 0.325 0 0.1 0.04 0.258 0.22 0.311-0.07 0.03-0.245 0.132-0.245 0.408 0 0.412 0.374 0.51 1.006 0.51 0.593 0 0.971-0.09 0.971-0.541 0-0.297-0.175-0.465-0.601-0.489l-0.922-0.06c-0.105 0-0.223-0.05-0.223-0.182 0-0.08 0.04-0.132 0.153-0.195 0.123 0.09 0.322 0.126 0.629 0.126 0.384 0 0.82-0.05 0.82-0.625 0-0.172-0.04-0.227-0.08-0.297 0.06-0.112 0.108-0.133 0.307-0.143zm-1.065 0.258c0.535 0 0.622 0.182 0.622 0.388 0 0.339-0.178 0.426-0.611 0.426-0.423 0-0.622-0.07-0.622-0.384 0-0.356 0.192-0.43 0.611-0.43zm0.206 1.512c0.36 0.02 0.556 0.06 0.556 0.308 0 0.216-0.147 0.331-0.751 0.331-0.674 0-0.8-0.1-0.8-0.345 0-0.304 0.318-0.336 0.328-0.336z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 9.4 KiB

View file

@ -1,125 +0,0 @@
/*
* 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)
{
return new WebSocket(urlpath, protocol);
}
function lws_san(s)
{
if (s.search("<") !== -1)
return "invalid string";
return s;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

View file

@ -1,144 +0,0 @@
.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

@ -1,634 +0,0 @@
<!-- 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, op;
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, op;
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) {
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

@ -1,2 +0,0 @@
!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

@ -1,5 +0,0 @@
<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

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

View file

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

View file

@ -1,6 +0,0 @@
<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

@ -1,27 +0,0 @@
<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

@ -1,20 +0,0 @@
<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

@ -1,25 +0,0 @@
<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.

Before

Width:  |  Height:  |  Size: 120 KiB

View file

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

View file

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

View file

@ -1,53 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 12 KiB

View file

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

View file

@ -281,36 +281,3 @@ callback_minimal_client_echo(struct lws *wsi, enum lws_callback_reasons reason,
1024, \
0, NULL, 0 \
}
#if !defined (LWS_PLUGIN_STATIC)
/* boilerplate needed if we are built as a dynamic plugin */
static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_MINIMAL_CLIENT_ECHO
};
int
init_protocol_minimal_client_echo(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
int
destroy_protocol_minimal_client_echo(struct lws_context *context)
{
return 0;
}
#endif

View file

@ -280,36 +280,3 @@ callback_minimal_pmd_bulk(struct lws *wsi, enum lws_callback_reasons reason,
4096, \
0, NULL, 0 \
}
#if !defined (LWS_PLUGIN_STATIC)
/* boilerplate needed if we are built as a dynamic plugin */
static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_MINIMAL_PMD_BULK
};
int
init_protocol_minimal_pmd_bulk(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
int
destroy_protocol_minimal_pmd_bulk(struct lws_context *context)
{
return 0;
}
#endif

View file

@ -215,36 +215,3 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason,
128, \
0, NULL, 0 \
}
#if !defined (LWS_PLUGIN_STATIC)
/* boilerplate needed if we are built as a dynamic plugin */
static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_MINIMAL
};
int
init_protocol_minimal(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
int
destroy_protocol_minimal(struct lws_context *context)
{
return 0;
}
#endif

View file

@ -230,36 +230,3 @@ callback_minimal_server_echo(struct lws *wsi, enum lws_callback_reasons reason,
1024, \
0, NULL, 0 \
}
#if !defined (LWS_PLUGIN_STATIC)
/* boilerplate needed if we are built as a dynamic plugin */
static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_MINIMAL_SERVER_ECHO
};
int
init_protocol_minimal_server_echo(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
int
destroy_protocol_minimal_server_echo(struct lws_context *context)
{
return 0;
}
#endif

View file

@ -221,36 +221,3 @@ callback_minimal_pmd_bulk(struct lws *wsi, enum lws_callback_reasons reason,
4096, \
0, NULL, 0 \
}
#if !defined (LWS_PLUGIN_STATIC)
/* boilerplate needed if we are built as a dynamic plugin */
static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_MINIMAL_PMD_BULK
};
int
init_protocol_minimal_pmd_bulk(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
int
destroy_protocol_minimal_pmd_bulk(struct lws_context *context)
{
return 0;
}
#endif

View file

@ -269,36 +269,3 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason,
2048, \
0, NULL, 0 \
}
#if !defined (LWS_PLUGIN_STATIC)
/* boilerplate needed if we are built as a dynamic plugin */
static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_MINIMAL
};
int
init_protocol_minimal(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
int
destroy_protocol_minimal(struct lws_context *context)
{
return 0;
}
#endif

View file

@ -158,36 +158,3 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason,
128, \
0, NULL, 0 \
}
#if !defined (LWS_PLUGIN_STATIC)
/* boilerplate needed if we are built as a dynamic plugin */
static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_MINIMAL
};
int
init_protocol_minimal(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
int
destroy_protocol_minimal(struct lws_context *context)
{
return 0;
}
#endif

View file

@ -279,36 +279,3 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason,
0, \
0, NULL, 0 \
}
#if !defined (LWS_PLUGIN_STATIC)
/* boilerplate needed if we are built as a dynamic plugin */
static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_MINIMAL
};
int
init_protocol_minimal(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
int
destroy_protocol_minimal(struct lws_context *context)
{
return 0;
}
#endif

View file

@ -322,36 +322,3 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason,
128, \
0, NULL, 0 \
}
#if !defined (LWS_PLUGIN_STATIC)
/* boilerplate needed if we are built as a dynamic plugin */
static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_MINIMAL
};
int
init_protocol_minimal(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
int
destroy_protocol_minimal(struct lws_context *context)
{
return 0;
}
#endif

View file

@ -300,36 +300,3 @@ init_fail:
128, \
0, NULL, 0 \
}
#if !defined (LWS_PLUGIN_STATIC)
/* boilerplate needed if we are built as a dynamic plugin */
static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_MINIMAL
};
int
init_protocol_minimal(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
int
destroy_protocol_minimal(struct lws_context *context)
{
return 0;
}
#endif

View file

@ -295,36 +295,3 @@ init_fail:
128, \
0, NULL, 0 \
}
#if !defined (LWS_PLUGIN_STATIC)
/* boilerplate needed if we are built as a dynamic plugin */
static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_MINIMAL
};
int
init_protocol_minimal(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
int
destroy_protocol_minimal(struct lws_context *context)
{
return 0;
}
#endif

View file

@ -152,36 +152,3 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason,
128, \
0, NULL, 0 \
}
#if !defined (LWS_PLUGIN_STATIC)
/* boilerplate needed if we are built as a dynamic plugin */
static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_MINIMAL
};
int
init_protocol_minimal(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
int
destroy_protocol_minimal(struct lws_context *context)
{
return 0;
}
#endif

View file

@ -127,26 +127,15 @@ static const struct lws_protocols protocols[] = {
},
};
LWS_VISIBLE int
init_protocol_example_standalone(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
LWS_VISIBLE const lws_plugin_protocol_t protocol_example_standalone = {
.hdr = {
"standalone",
"lws_protocol_plugin",
LWS_PLUGIN_API_MAGIC
},
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
LWS_VISIBLE int
destroy_protocol_example_standalone(struct lws_context *context)
{
return 0;
}
.protocols = protocols,
.count_protocols = LWS_ARRAY_SIZE(protocols),
.extensions = NULL,
.count_extensions = 0,
};

View file

@ -1630,28 +1630,17 @@ static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_LWS_ACME_CLIENT
};
LWS_VISIBLE int
init_protocol_lws_acme_client(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
LWS_VISIBLE const lws_plugin_protocol_t protocol_lws_acme_client = {
.hdr = {
"acme client",
"lws_protocol_plugin",
LWS_PLUGIN_API_MAGIC
},
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
LWS_VISIBLE int
destroy_protocol_lws_acme_client(struct lws_context *context)
{
return 0;
}
.protocols = protocols,
.count_protocols = LWS_ARRAY_SIZE(protocols),
.extensions = NULL,
.count_extensions = 0,
};
#endif

View file

@ -689,28 +689,17 @@ static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_DEADDROP
};
LWS_VISIBLE int
init_protocol_deaddrop(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
LWS_VISIBLE const lws_plugin_protocol_t protocol_deaddrop = {
.hdr = {
"deaddrop",
"lws_protocol_plugin",
LWS_PLUGIN_API_MAGIC
},
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
LWS_VISIBLE int
destroy_protocol_deaddrop(struct lws_context *context)
{
return 0;
}
.protocols = protocols,
.count_protocols = LWS_ARRAY_SIZE(protocols),
.extensions = NULL,
.count_extensions = 0,
};
#endif

View file

@ -173,26 +173,15 @@ static const struct lws_protocols protocols[] = {
},
};
LWS_VISIBLE int
init_protocol_client_loopback_test(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
LWS_VISIBLE const lws_plugin_protocol_t protocol_client_loopback_test = {
.hdr = {
"client loopback test",
"lws_protocol_plugin",
LWS_PLUGIN_API_MAGIC
},
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
LWS_VISIBLE int
destroy_protocol_client_loopback_test(struct lws_context *context)
{
return 0;
}
.protocols = protocols,
.count_protocols = LWS_ARRAY_SIZE(protocols),
.extensions = NULL,
.count_extensions = 0,
};

View file

@ -121,28 +121,17 @@ static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_DUMB_INCREMENT
};
LWS_VISIBLE int
init_protocol_dumb_increment(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
LWS_VISIBLE const lws_plugin_protocol_t protocol_dumb_increment = {
.hdr = {
"dumb increment",
"lws_protocol_plugin",
LWS_PLUGIN_API_MAGIC
},
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
LWS_VISIBLE int
destroy_protocol_dumb_increment(struct lws_context *context)
{
return 0;
}
.protocols = protocols,
.count_protocols = LWS_ARRAY_SIZE(protocols),
.extensions = NULL,
.count_extensions = 0,
};
#endif

View file

@ -1,242 +0,0 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <string.h>
#include <nvs.h>
#include <esp_ota_ops.h>
typedef enum {
GROUP_STATE_NONE,
GROUP_STATE_INITIAL,
GROUP_STATE_MEMBERS,
GROUP_STATE_FINAL
} group_state;
struct per_session_data__lws_group {
struct per_session_data__lws_group *next;
group_state group_state;
struct lws_group_member *member;
unsigned char subsequent:1;
unsigned char changed_partway:1;
};
struct per_vhost_data__lws_group {
struct per_session_data__lws_group *live_pss_list;
struct lws_context *context;
struct lws_vhost *vhost;
const struct lws_protocols *protocol;
int count_live_pss;
};
static void render_ip4(char *dest, int len, uint8_t *ip)
{
snprintf(dest, len, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
}
static int
callback_lws_group(struct lws *wsi, enum lws_callback_reasons reason,
void *user, void *in, size_t len)
{
struct per_session_data__lws_group *pss =
(struct per_session_data__lws_group *)user;
struct per_vhost_data__lws_group *vhd =
(struct per_vhost_data__lws_group *)
lws_protocol_vh_priv_get(lws_get_vhost(wsi),
lws_get_protocol(wsi));
char buffer[1024 + LWS_PRE], ipv4[20];
char *start = buffer + LWS_PRE - 1, *p = start,
*end = buffer + sizeof(buffer) - 1;
struct lws_group_member *mbr;
int n, m;
switch (reason) {
case LWS_CALLBACK_PROTOCOL_INIT:
vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
lws_get_protocol(wsi),
sizeof(struct per_vhost_data__lws_group));
vhd->context = lws_get_context(wsi);
vhd->protocol = lws_get_protocol(wsi);
vhd->vhost = lws_get_vhost(wsi);
break;
case LWS_CALLBACK_PROTOCOL_DESTROY:
if (!vhd)
break;
break;
case LWS_CALLBACK_ESTABLISHED:
lwsl_notice("%s: ESTABLISHED\n", __func__);
vhd->count_live_pss++;
pss->next = vhd->live_pss_list;
vhd->live_pss_list = pss;
pss->group_state = GROUP_STATE_INITIAL;
lws_callback_on_writable(wsi);
break;
case LWS_CALLBACK_SERVER_WRITEABLE:
switch (pss->group_state) {
case GROUP_STATE_NONE:
/* fallthru */
case GROUP_STATE_INITIAL:
p += snprintf((char *)p, end - p,
"{\n"
" \"group\":\"%s\","
" \"members\":[\n",
lws_esp32.group);
n = LWS_WRITE_TEXT | LWS_WRITE_NO_FIN;
pss->group_state = GROUP_STATE_MEMBERS;
pss->subsequent = 0;
pss->changed_partway = 0;
pss->member = lws_esp32.first;
break;
case GROUP_STATE_MEMBERS:
/* confirm pss->member is still in the list... */
mbr = lws_esp32.first;
while (mbr && mbr != pss->member)
mbr = mbr->next;
if (!mbr) { /* no longer exists... */
if (lws_esp32.first || pss->member)
pss->changed_partway = 1;
*p++ = ' ';
pss->member = NULL;
/*
* finish the list where we got to, then
* immediately reissue it
*/
}
while (end - p > 100 && pss->member) {
if (pss->subsequent)
*p++ = ',';
pss->subsequent = 1;
render_ip4(ipv4, sizeof(ipv4), (uint8_t *)&pss->member->addr);
p += snprintf((char *)p, end - p,
" {\n"
" \"mac\":\"%s\",\n"
" \"model\":\"%s\",\n"
" \"role\":\"%s\",\n"
" \"width\":\"%d\",\n"
" \"height\":\"%d\",\n"
" \"ipv4\":\"%s\"\n"
" }\n",
pss->member->mac,
pss->member->model,
pss->member->role,
pss->member->width,
pss->member->height,
ipv4
);
pss->member = pss->member->next;
}
lwsl_notice("%s\n", p);
n = LWS_WRITE_CONTINUATION | LWS_WRITE_NO_FIN;
if (!pss->member)
pss->group_state = GROUP_STATE_FINAL;
break;
case GROUP_STATE_FINAL:
n = LWS_WRITE_CONTINUATION;
p += sprintf((char *)p, "],\n \"discard\":\"%d\"}\n",
pss->changed_partway);
if (pss->changed_partway)
pss->group_state = GROUP_STATE_INITIAL;
else
pss->group_state = GROUP_STATE_NONE;
break;
default:
return 0;
}
// lwsl_notice("issue: %d (%d)\n", p - start, n);
m = lws_write(wsi, (unsigned char *)start, p - start, n);
if (m < 0) {
lwsl_err("ERROR %d writing to di socket\n", m);
return -1;
}
if (pss->group_state != GROUP_STATE_NONE)
lws_callback_on_writable(wsi);
break;
case LWS_CALLBACK_RECEIVE:
{
break;
}
case LWS_CALLBACK_CLOSED:
{
struct per_session_data__lws_group **p = &vhd->live_pss_list;
while (*p) {
if ((*p) == pss) {
*p = pss->next;
continue;
}
p = &((*p)->next);
}
vhd->count_live_pss--;
}
break;
case LWS_CALLBACK_HTTP_DROP_PROTOCOL:
/* called when our wsi user_space is going to be destroyed */
break;
default:
break;
}
return 0;
}
#define LWS_PLUGIN_PROTOCOL_LWS_GROUP \
{ \
"lws-group", \
callback_lws_group, \
sizeof(struct per_session_data__lws_group), \
1024, 0, NULL, 900 \
}

View file

@ -1,291 +0,0 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <string.h>
#include <esp_partition.h>
#include <esp_ota_ops.h>
#include <nvs.h>
struct per_session_data__esplws_ota {
struct lws_spa *spa;
char filename[32];
char result[LWS_PRE + 512];
int result_len;
int filename_length;
esp_ota_handle_t otahandle;
const esp_partition_t *part;
long file_length;
long last_rep;
nvs_handle nvh;
TimerHandle_t reboot_timer;
};
struct per_vhost_data__esplws_ota {
struct lws_context *context;
struct lws_vhost *vhost;
const struct lws_protocols *protocol;
};
static const char * const ota_param_names[] = {
"upload",
};
enum enum_ota_param_names {
EPN_UPLOAD,
};
static void ota_reboot_timer_cb(TimerHandle_t t)
{
esp_restart();
}
const esp_partition_t *
ota_choose_part(void)
{
const esp_partition_t *bootpart, *part = NULL;
esp_partition_iterator_t i;
bootpart = lws_esp_ota_get_boot_partition();
i = esp_partition_find(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, NULL);
while (i) {
part = esp_partition_get(i);
/* cannot update ourselves */
if (part == bootpart)
goto next;
/* OTA Partition numbering is from _OTA_MIN to less than _OTA_MAX */
if (part->subtype < ESP_PARTITION_SUBTYPE_APP_OTA_MIN ||
part->subtype >= ESP_PARTITION_SUBTYPE_APP_OTA_MAX)
goto next;
break;
next:
i = esp_partition_next(i);
}
if (!i) {
lwsl_err("Can't find good OTA part\n");
return NULL;
}
lwsl_notice("Directing OTA to part type %d/%d start 0x%x\n",
part->type, part->subtype,
(uint32_t)part->address);
return part;
}
static int
ota_file_upload_cb(void *data, const char *name, const char *filename,
char *buf, int len, enum lws_spa_fileupload_states state)
{
struct per_session_data__esplws_ota *pss =
(struct per_session_data__esplws_ota *)data;
switch (state) {
case LWS_UFS_OPEN:
lwsl_notice("LWS_UFS_OPEN Filename %s\n", filename);
lws_strncpy(pss->filename, filename, sizeof(pss->filename));
if (strcmp(name, "ota"))
return 1;
pss->part = ota_choose_part();
if (!pss->part)
return 1;
if (esp_ota_begin(pss->part, OTA_SIZE_UNKNOWN, &pss->otahandle) != ESP_OK) {
lwsl_err("OTA: Failed to begin\n");
return 1;
}
pss->file_length = 0;
pss->last_rep = -1;
break;
case LWS_UFS_FINAL_CONTENT:
case LWS_UFS_CONTENT:
if (pss->file_length + len > pss->part->size) {
lwsl_err("OTA: incoming file too large\n");
return 1;
}
if ((pss->file_length & ~0xffff) != (pss->last_rep & ~0xffff)) {
lwsl_notice("writing 0x%lx...\n",
pss->part->address + pss->file_length);
pss->last_rep = pss->file_length;
}
if (esp_ota_write(pss->otahandle, buf, len) != ESP_OK) {
lwsl_err("OTA: Failed to write\n");
return 1;
}
pss->file_length += len;
if (state == LWS_UFS_CONTENT)
break;
lwsl_notice("LWS_UFS_FINAL_CONTENT\n");
if (esp_ota_end(pss->otahandle) != ESP_OK) {
lwsl_err("OTA: end failed\n");
return 1;
}
if (esp_ota_set_boot_partition(pss->part) != ESP_OK) {
lwsl_err("OTA: set boot part failed\n");
return 1;
}
pss->reboot_timer = xTimerCreate("x", pdMS_TO_TICKS(250), 0, NULL,
ota_reboot_timer_cb);
xTimerStart(pss->reboot_timer, 0);
break;
}
return 0;
}
static int
callback_esplws_ota(struct lws *wsi, enum lws_callback_reasons reason,
void *user, void *in, size_t len)
{
struct per_session_data__esplws_ota *pss =
(struct per_session_data__esplws_ota *)user;
struct per_vhost_data__esplws_ota *vhd =
(struct per_vhost_data__esplws_ota *)
lws_protocol_vh_priv_get(lws_get_vhost(wsi),
lws_get_protocol(wsi));
unsigned char buf[LWS_PRE + 384], *start = buf + LWS_PRE - 1, *p = start,
*end = buf + sizeof(buf) - 1;
int n;
switch (reason) {
case LWS_CALLBACK_PROTOCOL_INIT:
vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
lws_get_protocol(wsi),
sizeof(struct per_vhost_data__esplws_ota));
vhd->context = lws_get_context(wsi);
vhd->protocol = lws_get_protocol(wsi);
vhd->vhost = lws_get_vhost(wsi);
break;
case LWS_CALLBACK_PROTOCOL_DESTROY:
if (!vhd)
break;
break;
/* OTA POST handling */
case LWS_CALLBACK_HTTP_BODY:
/* create the POST argument parser if not already existing */
// lwsl_notice("LWS_CALLBACK_HTTP_BODY (ota) %d %d %p\n", (int)pss->file_length, (int)len, pss->spa);
lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT, 30);
if (!pss->spa) {
pss->spa = lws_spa_create(wsi, ota_param_names,
LWS_ARRAY_SIZE(ota_param_names), 4096,
ota_file_upload_cb, pss);
if (!pss->spa)
return -1;
pss->filename[0] = '\0';
pss->file_length = 0;
}
lws_esp32.upload = 1;
/* let it parse the POST data */
if (lws_spa_process(pss->spa, in, len))
return -1;
break;
case LWS_CALLBACK_HTTP_BODY_COMPLETION:
lwsl_notice("LWS_CALLBACK_HTTP_BODY_COMPLETION (ota)\n");
/* call to inform no more payload data coming */
lws_spa_finalize(pss->spa);
pss->result_len = snprintf(pss->result + LWS_PRE, sizeof(pss->result) - LWS_PRE - 1,
"Rebooting after OTA update");
if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end))
goto bail;
if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
(unsigned char *)"text/html", 9, &p, end))
goto bail;
if (lws_add_http_header_content_length(wsi, pss->result_len, &p, end))
goto bail;
if (lws_finalize_http_header(wsi, &p, end))
goto bail;
n = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS | LWS_WRITE_H2_STREAM_END);
if (n < 0)
goto bail;
lws_callback_on_writable(wsi);
break;
case LWS_CALLBACK_HTTP_WRITEABLE:
if (!pss->result_len)
break;
lwsl_debug("LWS_CALLBACK_HTTP_WRITEABLE: sending %d\n",
pss->result_len);
n = lws_write(wsi, (unsigned char *)pss->result + LWS_PRE,
pss->result_len, LWS_WRITE_HTTP);
if (n < 0)
return 1;
if (lws_http_transaction_completed(wsi))
return 1;
/* stop further service so we don't serve the probe GET to see if we rebooted */
while (1);
break;
case LWS_CALLBACK_HTTP_DROP_PROTOCOL:
/* called when our wsi user_space is going to be destroyed */
if (pss->spa) {
lws_spa_destroy(pss->spa);
pss->spa = NULL;
}
lws_esp32.upload = 0;
break;
default:
break;
}
return 0;
bail:
return 1;
}
#define LWS_PLUGIN_PROTOCOL_ESPLWS_OTA \
{ \
"esplws-ota", \
callback_esplws_ota, \
sizeof(struct per_session_data__esplws_ota), \
4096, 0, NULL, 900 \
}

View file

@ -1,61 +0,0 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* This is intended to be mounted somewhere in your ESP32 user app... if the
* client touched the mount, the plugin hangs up and reboots into the
* factory mode one second later.
*
* The factory mode will reassociate with the same IP with the same MAC
* shortly afterwards and be accessible by the same IP / mDNS name.
*/
#include <string.h>
#include <esp_partition.h>
#include <esp_ota_ops.h>
#include <nvs.h>
static int
callback_esplws_rtf(struct lws *wsi, enum lws_callback_reasons reason,
void *user, void *in, size_t len)
{
switch (reason) {
case LWS_CALLBACK_HTTP:
lws_esp32_restart_guided(LWS_MAGIC_REBOOT_TYPE_REQ_FACTORY);
return 1;
default:
break;
}
return 0;
}
#define LWS_PLUGIN_PROTOCOL_ESPLWS_RTF \
{ \
"esplws-rtf", \
callback_esplws_rtf, \
0, \
10, 0, NULL, 0 \
}

File diff suppressed because it is too large Load diff

View file

@ -266,28 +266,17 @@ static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_FULLTEXT_DEMO
};
LWS_VISIBLE int
init_protocol_fulltext_demo(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
LWS_VISIBLE const lws_plugin_protocol_t protocol_fulltext_demo = {
.hdr = {
"fulltext demo",
"lws_protocol_plugin",
LWS_PLUGIN_API_MAGIC
},
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
LWS_VISIBLE int
destroy_protocol_fulltext_demo(struct lws_context *context)
{
return 0;
}
.protocols = protocols,
.count_protocols = LWS_ARRAY_SIZE(protocols),
.extensions = NULL,
.count_extensions = 0,
};
#endif

View file

@ -482,27 +482,17 @@ static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_MIRROR
};
LWS_VISIBLE int
init_protocol_lws_mirror(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
LWS_VISIBLE const lws_plugin_protocol_t protocol_lws_mirror = {
.hdr = {
"lws mirror",
"lws_protocol_plugin",
LWS_PLUGIN_API_MAGIC
},
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
.protocols = protocols,
.count_protocols = LWS_ARRAY_SIZE(protocols),
.extensions = NULL,
.count_extensions = 0,
};
return 0;
}
LWS_VISIBLE int
destroy_protocol_lws_mirror(struct lws_context *context)
{
return 0;
}
#endif

View file

@ -278,28 +278,17 @@ static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_RAW_TEST
};
LWS_VISIBLE int
init_protocol_lws_raw_test(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
LWS_VISIBLE const lws_plugin_protocol_t protocol_lws_raw_test = {
.hdr = {
"lws raw test",
"lws_protocol_plugin",
LWS_PLUGIN_API_MAGIC
},
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
LWS_VISIBLE int
destroy_protocol_lws_raw_test(struct lws_context *context)
{
return 0;
}
.protocols = protocols,
.count_protocols = LWS_ARRAY_SIZE(protocols),
.extensions = NULL,
.count_extensions = 0,
};
#endif

View file

@ -204,26 +204,15 @@ static const struct lws_protocols protocols[] = {
},
};
LWS_VISIBLE int
init_protocol_lws_server_status(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d",
LWS_PLUGIN_API_MAGIC, c->api_magic);
return 1;
}
LWS_VISIBLE const lws_plugin_protocol_t protocol_lws_server_status = {
.hdr = {
"lws server status",
"lws_protocol_plugin",
LWS_PLUGIN_API_MAGIC
},
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
LWS_VISIBLE int
destroy_protocol_lws_server_status(struct lws_context *context)
{
return 0;
}
.protocols = protocols,
.count_protocols = LWS_ARRAY_SIZE(protocols),
.extensions = NULL,
.count_extensions = 0,
};

View file

@ -455,28 +455,17 @@ static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_LWS_SSHD_DEMO
};
LWS_VISIBLE int
init_protocol_lws_sshd_demo(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
LWS_VISIBLE const lws_plugin_protocol_t protocol_lws_sshd_demo = {
.hdr = {
"lws sshd demo",
"lws_protocol_plugin",
LWS_PLUGIN_API_MAGIC
},
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
LWS_VISIBLE int
destroy_protocol_lws_sshd_demo(struct lws_context *context)
{
return 0;
}
.protocols = protocols,
.count_protocols = LWS_ARRAY_SIZE(protocols),
.extensions = NULL,
.count_extensions = 0,
};
#endif

View file

@ -245,29 +245,17 @@ static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_LWS_STATUS
};
LWS_VISIBLE const lws_plugin_protocol_t protocol_lws_status = {
.hdr = {
"lws status",
"lws_protocol_plugin",
LWS_PLUGIN_API_MAGIC
},
LWS_VISIBLE int
init_protocol_lws_status(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
LWS_VISIBLE int
destroy_protocol_lws_status(struct lws_context *context)
{
return 0;
}
.protocols = protocols,
.count_protocols = LWS_ARRAY_SIZE(protocols),
.extensions = NULL,
.count_extensions = 0,
};
#endif

View file

@ -287,28 +287,17 @@ static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_POST_DEMO
};
LWS_VISIBLE int
init_protocol_post_demo(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
LWS_VISIBLE const lws_plugin_protocol_t protocol_post_demo = {
.hdr = {
"post demo",
"lws_protocol_plugin",
LWS_PLUGIN_API_MAGIC
},
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
LWS_VISIBLE int
destroy_protocol_post_demo(struct lws_context *context)
{
return 0;
}
.protocols = protocols,
.count_protocols = LWS_ARRAY_SIZE(protocols),
.extensions = NULL,
.count_extensions = 0,
};
#endif

View file

@ -562,29 +562,18 @@ static const struct lws_protocols protocols[] = {
LWS_PLUGIN_PROTOCOL_RAW_PROXY
};
LWS_VISIBLE int
init_protocol_lws_raw_proxy(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
LWS_VISIBLE const lws_plugin_protocol_t protocol_lws_raw_proxy = {
.hdr = {
"raw proxy",
"lws_protocol_plugin",
LWS_PLUGIN_API_MAGIC
},
c->protocols = protocols;
c->count_protocols = LWS_ARRAY_SIZE(protocols);
c->extensions = NULL;
c->count_extensions = 0;
return 0;
}
LWS_VISIBLE int
destroy_protocol_lws_raw_proxy(struct lws_context *context)
{
return 0;
}
.protocols = protocols,
.count_protocols = LWS_ARRAY_SIZE(protocols),
.extensions = NULL,
.count_extensions = 0,
};
#endif

View file

@ -2565,27 +2565,17 @@ const struct lws_protocols protocols_sshd[] = {
#if !defined (LWS_PLUGIN_STATIC)
LWS_VISIBLE int
init_protocol_lws_ssh_base(struct lws_context *context,
struct lws_plugin_capability *c)
{
if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
c->api_magic);
return 1;
}
LWS_VISIBLE const lws_plugin_protocol_t protocol_lws_ssh_base = {
.hdr = {
"ssh base",
"lws_protocol_plugin",
LWS_PLUGIN_API_MAGIC
},
c->protocols = protocols_sshd;
c->count_protocols = LWS_ARRAY_SIZE(protocols_sshd);
c->extensions = NULL;
c->count_extensions = 0;
.protocols = protocols_sshd,
.count_protocols = LWS_ARRAY_SIZE(protocols_sshd),
.extensions = NULL,
.count_extensions = 0,
};
return 0;
}
LWS_VISIBLE int
destroy_protocol_lws_ssh_base(struct lws_context *context)
{
return 0;
}
#endif