mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
remove: generic sessions
As far as I know there are no users of this, although it worked it's basically unmaintainable due to handling the sql and JSON manually. Gradually better capabilities have appeared in lws, like lws_struct abstracting out the sql and JSON, and now generic JWT... these have been used in Sai to great effect and displaced the only organic would-be user of this. There is a better path to do this stuff now and no point keeping this around.
This commit is contained in:
parent
f1f34a7d4b
commit
52a8c87838
28 changed files with 0 additions and 4257 deletions
|
@ -134,7 +134,6 @@ if (NOT LWS_WITH_NETWORK)
|
|||
set(LWS_WITH_CGI 0)
|
||||
set(LWS_ROLE_RAW_PROXY 0)
|
||||
set(LWS_WITH_PEER_LIMITS 0)
|
||||
set(LWS_WITH_GENERIC_SESSIONS 0)
|
||||
set(LWS_WITH_HTTP_STREAM_COMPRESSION 0)
|
||||
set(LWS_WITH_HTTP_BROTLI 0)
|
||||
set(LWS_WITH_POLL 0)
|
||||
|
@ -228,12 +227,6 @@ if (LWS_WITH_PLUGINS OR LWS_WITH_CGI)
|
|||
set(LWS_WITH_GENCRYPTO 1)
|
||||
endif()
|
||||
|
||||
if (LWS_WITH_GENERIC_SESSIONS)
|
||||
set(LWS_WITH_SQLITE3 1)
|
||||
# set(LWS_WITH_SMTP 1)
|
||||
set(LWS_WITH_STRUCT_SQLITE3 1)
|
||||
endif()
|
||||
|
||||
if (LWS_PLAT_FREERTOS)
|
||||
set(LWS_WITH_SHARED OFF)
|
||||
set(LWS_WITH_MBEDTLS ON)
|
||||
|
|
|
@ -96,7 +96,6 @@ option(LWS_WITH_PLUGINS "Support plugins for protocols and extensions" OFF)
|
|||
option(LWS_WITH_HTTP_PROXY "Support for active HTTP proxying" OFF)
|
||||
option(LWS_WITH_ZIP_FOPS "Support serving pre-zipped files" OFF)
|
||||
option(LWS_WITH_SOCKS5 "Allow use of SOCKS5 proxy on client connections" OFF)
|
||||
option(LWS_WITH_GENERIC_SESSIONS "With the Generic Sessions plugin" OFF)
|
||||
option(LWS_WITH_PEER_LIMITS "Track peers and restrict resources a single peer can allocate" OFF)
|
||||
option(LWS_WITH_ACCESS_LOG "Support generating Apache-compatible access logs" OFF)
|
||||
option(LWS_WITH_RANGES "Support http ranges (RFC7233)" OFF)
|
||||
|
|
|
@ -90,8 +90,6 @@ if (LWS_ROLE_WS)
|
|||
"protocol_lws_mirror.c" "" "")
|
||||
create_plugin(protocol_lws_status ""
|
||||
"protocol_lws_status.c" "" "")
|
||||
create_plugin(protocol_lws_table_dirlisting ""
|
||||
"generic-table/protocol_table_dirlisting.c" "" "")
|
||||
if (NOT WIN32)
|
||||
create_plugin(protocol_lws_raw_test ""
|
||||
"protocol_lws_raw_test.c" "" "")
|
||||
|
@ -143,29 +141,6 @@ if (LWS_WITH_ACME)
|
|||
"acme-client/protocol_lws_acme_client.c" "" "")
|
||||
endif()
|
||||
|
||||
if (LWS_WITH_GENERIC_SESSIONS AND LWS_ROLE_WS AND LWS_WITH_TLS)
|
||||
create_plugin(protocol_generic_sessions ""
|
||||
"generic-sessions/protocol_generic_sessions.c"
|
||||
"generic-sessions/utils.c"
|
||||
"generic-sessions/handlers.c")
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(protocol_generic_sessions ${LWS_SQLITE3_LIBRARIES})
|
||||
else()
|
||||
target_link_libraries(protocol_generic_sessions sqlite3 )
|
||||
endif(WIN32)
|
||||
|
||||
create_plugin(protocol_lws_messageboard ""
|
||||
"generic-sessions/protocol_lws_messageboard.c" "" "")
|
||||
if (WIN32)
|
||||
target_link_libraries(protocol_lws_messageboard ${LWS_SQLITE3_LIBRARIES})
|
||||
else()
|
||||
target_link_libraries(protocol_lws_messageboard sqlite3 )
|
||||
endif(WIN32)
|
||||
|
||||
endif(LWS_WITH_GENERIC_SESSIONS AND LWS_ROLE_WS AND LWS_WITH_TLS)
|
||||
|
||||
|
||||
endif(LWS_WITH_PLUGINS AND LWS_WITH_SHARED)
|
||||
|
||||
|
||||
|
@ -189,36 +164,4 @@ if (LWS_WITH_SERVER_STATUS)
|
|||
DESTINATION share/libwebsockets-test-server/server-status
|
||||
COMPONENT examples)
|
||||
endif()
|
||||
if (LWS_WITH_GENERIC_SESSIONS)
|
||||
install(FILES
|
||||
generic-sessions/assets/lwsgs-logo.png
|
||||
generic-sessions/assets/seats.jpg
|
||||
generic-sessions/assets/failed-login.html
|
||||
generic-sessions/assets/lwsgs.js
|
||||
generic-sessions/assets/lwsgs.css
|
||||
generic-sessions/assets/post-register-fail.html
|
||||
generic-sessions/assets/post-register-ok.html
|
||||
generic-sessions/assets/post-verify-ok.html
|
||||
generic-sessions/assets/post-verify-fail.html
|
||||
generic-sessions/assets/sent-forgot-ok.html
|
||||
generic-sessions/assets/sent-forgot-fail.html
|
||||
generic-sessions/assets/post-forgot-ok.html
|
||||
generic-sessions/assets/post-forgot-fail.html
|
||||
generic-sessions/assets/index.html
|
||||
DESTINATION share/libwebsockets-test-server/generic-sessions
|
||||
COMPONENT examples)
|
||||
install(FILES generic-sessions/assets/successful-login.html
|
||||
DESTINATION share/libwebsockets-test-server/generic-sessions/needauth
|
||||
COMPONENT examples)
|
||||
install(FILES generic-sessions/assets/admin-login.html
|
||||
DESTINATION share/libwebsockets-test-server/generic-sessions/needadmin
|
||||
COMPONENT examples)
|
||||
endif()
|
||||
|
||||
install(FILES
|
||||
generic-table/assets/lwsgt.js
|
||||
generic-table/assets/index.html
|
||||
DESTINATION share/libwebsockets-test-server/generic-table
|
||||
COMPONENT examples)
|
||||
|
||||
endif()
|
||||
|
|
|
@ -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>
|
|
@ -1,3 +0,0 @@
|
|||
<html>
|
||||
This is an example destination that will appear after a failed login
|
||||
</html>
|
|
@ -1,56 +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-logo.png">
|
||||
</td>
|
||||
<td class="">
|
||||
<div id=lwsgs class="lwsgs"></div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr><td colspan=2 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>
|
||||
</form>
|
||||
<iframe name="hidden" class="hidden"></iframe>
|
||||
</body>
|
||||
</html>
|
Binary file not shown.
Before Width: | Height: | Size: 9.5 KiB |
|
@ -1,134 +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:none;
|
||||
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.seats {
|
||||
background-image:url(seats.jpg)
|
||||
}
|
||||
|
||||
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.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;
|
||||
}
|
||||
|
||||
.green {
|
||||
color: green;
|
||||
}
|
|
@ -1,627 +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">\
|
||||
<input type="submit" id="forgot" name="forgot" value="Forgot password">\
|
||||
<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><span id=grav></span></td>\
|
||||
<td class="tac"><table><tr><td class="tac">\
|
||||
<a href="#" id="clink">\
|
||||
<span id="curuser"></span></a></td></tr><tr>\
|
||||
<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" <span id=uchk></span></td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td align=right>Password:</td>\
|
||||
<td><input type="password" size="10" id="rpassword" name="password"> <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"> <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" <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"\
|
||||
> <span id=cuchk></span></td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td align=right>Password:</td>\
|
||||
<td><input type="password" size="10" id="cpassword" name="password"\
|
||||
<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"\
|
||||
> <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="?" \
|
||||
<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 \
|
||||
<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 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 + "<";
|
||||
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);
|
||||
|
||||
q.innerHTML = "<br><div class=\"group2\"><table class=\"fixed\"><tr><td>" +
|
||||
"<img 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>" + d.toTimeString() + "</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);
|
2
plugins/generic-sessions/assets/md5.min.js
vendored
2
plugins/generic-sessions/assets/md5.min.js
vendored
|
@ -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
|
|
@ -1,5 +0,0 @@
|
|||
<html>
|
||||
Sorry, something went wrong.
|
||||
|
||||
Click <a href="../">here</a> to continue.
|
||||
</html>
|
|
@ -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>
|
||||
|
|
@ -1 +0,0 @@
|
|||
Registration failed, sorry
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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 |
|
@ -1,5 +0,0 @@
|
|||
<html>
|
||||
Sorry, something went wrong.
|
||||
|
||||
Click <a href="../">here</a> to continue.
|
||||
</html>
|
|
@ -1,4 +0,0 @@
|
|||
An email has been sent to your registered address.
|
||||
|
||||
Please follow the instructions to reset your password.
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
<html>
|
||||
This is an example destination that will appear after successful non-Admin login
|
||||
</html>
|
||||
|
|
@ -1,663 +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 "private-lwsgs.h"
|
||||
|
||||
#if defined(LWS_WITH_SMTP)
|
||||
|
||||
static int
|
||||
lwsgs_smtp_client_done(struct lws_smtp_email *e, void *buf, size_t len)
|
||||
{
|
||||
free(e);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
lwsgs_smtp_client_done_sentvfy(struct lws_smtp_email *e, void *buf, size_t len)
|
||||
{
|
||||
struct per_vhost_data__gs *vhd = (struct per_vhost_data__gs *)e->data;
|
||||
const char *username = (const char *)e->extra;
|
||||
char s[200], esc[96];
|
||||
|
||||
lwsl_notice("%s: registration email sent: %s\n", __func__, username);
|
||||
|
||||
/* mark the user as having sent the verification email */
|
||||
lws_snprintf(s, sizeof(s) - 1,
|
||||
"update users set verified=1 where username='%s' and verified==0;",
|
||||
lws_sql_purify(esc, username, sizeof(esc) - 1));
|
||||
if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) {
|
||||
lwsl_err("%s: Unable to update user: %s\n", __func__,
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
return 1;
|
||||
}
|
||||
|
||||
free(e);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* handle account confirmation links */
|
||||
|
||||
int
|
||||
lwsgs_handler_confirm(struct per_vhost_data__gs *vhd, struct lws *wsi,
|
||||
struct per_session_data__gs *pss)
|
||||
{
|
||||
char cookie[1024], s[256], esc[90];
|
||||
struct lws_gs_event_args a;
|
||||
struct lwsgs_user u;
|
||||
|
||||
if (lws_hdr_copy_fragment(wsi, cookie, sizeof(cookie),
|
||||
WSI_TOKEN_HTTP_URI_ARGS, 0) < 0) {
|
||||
lwsl_err("%s: missing URI_ARGS\n", __func__);
|
||||
goto verf_fail;
|
||||
}
|
||||
|
||||
if (strncmp(cookie, "token=", 6)) {
|
||||
lwsl_err("%s: missing URI_ARGS token=\n", __func__);
|
||||
goto verf_fail;
|
||||
}
|
||||
|
||||
u.username[0] = '\0';
|
||||
u.verified = -1;
|
||||
lws_snprintf(s, sizeof(s) - 1,
|
||||
"select username,email,verified from users where token = '%s';",
|
||||
lws_sql_purify(esc, &cookie[6], sizeof(esc) - 1));
|
||||
puts(s);
|
||||
if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) !=
|
||||
SQLITE_OK) {
|
||||
lwsl_err("Unable to lookup token: %s\n",
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
goto verf_fail;
|
||||
}
|
||||
|
||||
if (!u.username[0] || u.verified != 1) {
|
||||
lwsl_notice("verify token %s doesn't map to unverified user (user='%s', verified=%d)\n",
|
||||
&cookie[6], u.username, u.verified);
|
||||
goto verf_fail;
|
||||
}
|
||||
|
||||
lwsl_notice("Verifying %s\n", u.username);
|
||||
lws_snprintf(s, sizeof(s) - 1,
|
||||
"update users set verified=%d where username='%s';",
|
||||
LWSGS_VERIFIED_ACCEPTED,
|
||||
lws_sql_purify(esc, u.username, sizeof(esc) - 1));
|
||||
if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) !=
|
||||
SQLITE_OK) {
|
||||
lwsl_err("Unable to lookup token: %s\n",
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
|
||||
goto verf_fail;
|
||||
}
|
||||
|
||||
lwsl_notice("deleting account\n");
|
||||
|
||||
a.event = LWSGSE_CREATED;
|
||||
a.username = u.username;
|
||||
a.email = u.email;
|
||||
lws_callback_vhost_protocols_vhost(lws_get_vhost(wsi),
|
||||
LWS_CALLBACK_GS_EVENT, &a, 0);
|
||||
|
||||
lws_snprintf(pss->onward, sizeof(pss->onward),
|
||||
"%s/post-verify-ok.html", vhd->email_confirm_url);
|
||||
|
||||
pss->login_expires = lws_now_secs() + vhd->timeout_absolute_secs;
|
||||
|
||||
pss->delete_session.id[0] = '\0';
|
||||
lwsgs_get_sid_from_wsi(wsi, &pss->delete_session);
|
||||
|
||||
/* we need to create a new, authorized session */
|
||||
|
||||
if (lwsgs_new_session_id(vhd, &pss->login_session, u.username,
|
||||
pss->login_expires))
|
||||
goto verf_fail;
|
||||
|
||||
lwsl_notice("Creating new session: %s, redir to %s\n",
|
||||
pss->login_session.id, pss->onward);
|
||||
|
||||
return 0;
|
||||
|
||||
verf_fail:
|
||||
pss->delete_session.id[0] = '\0';
|
||||
lwsgs_get_sid_from_wsi(wsi, &pss->delete_session);
|
||||
pss->login_expires = 0;
|
||||
|
||||
lws_snprintf(pss->onward, sizeof(pss->onward), "%s/post-verify-fail.html",
|
||||
vhd->email_confirm_url);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* handle forgot password confirmation links */
|
||||
|
||||
int
|
||||
lwsgs_handler_forgot(struct per_vhost_data__gs *vhd, struct lws *wsi,
|
||||
struct per_session_data__gs *pss)
|
||||
{
|
||||
char cookie[1024], s[256], esc[96];
|
||||
struct lwsgs_user u;
|
||||
const char *a;
|
||||
|
||||
a = lws_get_urlarg_by_name(wsi, "token=", cookie, sizeof(cookie));
|
||||
if (!a)
|
||||
goto forgot_fail;
|
||||
|
||||
u.username[0] = '\0';
|
||||
lws_snprintf(s, sizeof(s) - 1,
|
||||
"select username,verified from users where verified=%d and "
|
||||
"token = '%s' and token_time != 0;",
|
||||
LWSGS_VERIFIED_ACCEPTED,
|
||||
lws_sql_purify(esc, &cookie[6], sizeof(esc) - 1));
|
||||
if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) !=
|
||||
SQLITE_OK) {
|
||||
lwsl_err("Unable to lookup token: %s\n",
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
|
||||
goto forgot_fail;
|
||||
}
|
||||
|
||||
if (!u.username[0]) {
|
||||
puts(s);
|
||||
lwsl_notice("forgot token doesn't map to verified user\n");
|
||||
goto forgot_fail;
|
||||
}
|
||||
|
||||
/* mark user as having validated forgot flow just now */
|
||||
|
||||
lws_snprintf(s, sizeof(s) - 1,
|
||||
"update users set token_time=0,last_forgot_validated=%lu "
|
||||
"where username='%s';",
|
||||
(unsigned long)lws_now_secs(),
|
||||
lws_sql_purify(esc, u.username, sizeof(esc) - 1));
|
||||
|
||||
if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) !=
|
||||
SQLITE_OK) {
|
||||
lwsl_err("Unable to lookup token: %s\n",
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
goto forgot_fail;
|
||||
}
|
||||
|
||||
a = lws_get_urlarg_by_name(wsi, "good=", cookie, sizeof(cookie));
|
||||
if (!a)
|
||||
a = "broken-forget-post-good-url";
|
||||
|
||||
lws_snprintf(pss->onward, sizeof(pss->onward),
|
||||
"%s/%s", vhd->email_confirm_url, a);
|
||||
|
||||
pss->login_expires = lws_now_secs() + vhd->timeout_absolute_secs;
|
||||
|
||||
pss->delete_session.id[0] = '\0';
|
||||
lwsgs_get_sid_from_wsi(wsi, &pss->delete_session);
|
||||
|
||||
/* we need to create a new, authorized session */
|
||||
if (lwsgs_new_session_id(vhd, &pss->login_session,
|
||||
u.username,
|
||||
pss->login_expires))
|
||||
goto forgot_fail;
|
||||
|
||||
lwsl_notice("Creating new session: %s, redir to %s\n",
|
||||
pss->login_session.id, pss->onward);
|
||||
|
||||
return 0;
|
||||
|
||||
forgot_fail:
|
||||
pss->delete_session.id[0] = '\0';
|
||||
lwsgs_get_sid_from_wsi(wsi, &pss->delete_session);
|
||||
pss->login_expires = 0;
|
||||
|
||||
a = lws_get_urlarg_by_name(wsi, "bad=", cookie, sizeof(cookie));
|
||||
if (!a)
|
||||
a = "broken-forget-post-bad-url";
|
||||
|
||||
lws_snprintf(pss->onward, sizeof(pss->onward), "%s/%s",
|
||||
vhd->email_confirm_url, a);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* support dynamic username / email checking */
|
||||
|
||||
int
|
||||
lwsgs_handler_check(struct per_vhost_data__gs *vhd,
|
||||
struct lws *wsi, struct per_session_data__gs *pss,
|
||||
const char *in)
|
||||
{
|
||||
static const char * const colname[] = { "username", "email" };
|
||||
char s[256], esc[96], *pc;
|
||||
unsigned char *p, *start, *end, buffer[LWS_PRE + 1024];
|
||||
struct lwsgs_user u;
|
||||
int n;
|
||||
|
||||
/*
|
||||
* either /check/email=xxx@yyy or: /check/username=xxx
|
||||
* returns '0' if not already registered, else '1'
|
||||
*/
|
||||
|
||||
u.username[0] = '\0';
|
||||
|
||||
n = !strncmp(in, "email=", 6);
|
||||
pc = strchr(in, '=');
|
||||
if (!pc) {
|
||||
lwsl_notice("cookie has no =\n");
|
||||
goto reply;
|
||||
}
|
||||
pc++;
|
||||
|
||||
/* admin user cannot be registered in user db */
|
||||
if (!strcmp(vhd->admin_user, pc)) {
|
||||
u.username[0] = 'a';
|
||||
goto reply;
|
||||
}
|
||||
|
||||
lws_snprintf(s, sizeof(s) - 1,
|
||||
"select username, email from users where %s = '%s';",
|
||||
colname[n], lws_sql_purify(esc, pc, sizeof(esc) - 1));
|
||||
if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) !=
|
||||
SQLITE_OK) {
|
||||
lwsl_err("Unable to lookup token: %s\n",
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
goto reply;
|
||||
}
|
||||
|
||||
reply:
|
||||
s[0] = '0' + !!u.username[0];
|
||||
p = buffer + LWS_PRE;
|
||||
start = p;
|
||||
end = p + sizeof(buffer) - LWS_PRE;
|
||||
|
||||
if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end))
|
||||
return -1;
|
||||
if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
|
||||
(unsigned char *)"text/plain", 10,
|
||||
&p, end))
|
||||
return -1;
|
||||
|
||||
if (lws_add_http_header_content_length(wsi, 1, &p, end))
|
||||
return -1;
|
||||
|
||||
if (lws_finalize_http_header(wsi, &p, end))
|
||||
return -1;
|
||||
|
||||
n = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS);
|
||||
if (n != (p - start)) {
|
||||
lwsl_err("_write returned %d from %ld\n", n, (long)(p - start));
|
||||
return -1;
|
||||
}
|
||||
|
||||
pss->check_response_value = s[0];
|
||||
pss->check_response = 1;
|
||||
|
||||
lws_callback_on_writable(wsi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* handle forgot password confirmation links */
|
||||
|
||||
int
|
||||
lwsgs_handler_change_password(struct per_vhost_data__gs *vhd, struct lws *wsi,
|
||||
struct per_session_data__gs *pss)
|
||||
{
|
||||
char s[256], esc[96], username[96];
|
||||
struct lwsgs_user u;
|
||||
lwsgw_hash sid;
|
||||
int n = 0;
|
||||
|
||||
/* see if he's logged in */
|
||||
username[0] = '\0';
|
||||
if (!lwsgs_get_sid_from_wsi(wsi, &sid)) {
|
||||
u.username[0] = '\0';
|
||||
if (!lwsgs_lookup_session(vhd, &sid, username, sizeof(username))) {
|
||||
n = 1; /* yes, logged in */
|
||||
if (lwsgs_lookup_user(vhd, username, &u))
|
||||
return 1;
|
||||
|
||||
/* did a forgot pw ? */
|
||||
if (u.last_forgot_validated > (time_t)lws_now_secs() - 300) {
|
||||
n |= LWSGS_AUTH_FORGOT_FLOW;
|
||||
lwsl_debug("within forgot password flow\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lwsl_debug("auth value %d\n", n);
|
||||
|
||||
/* if he just did forgot pw flow, don't need old pw */
|
||||
if ((n & (LWSGS_AUTH_FORGOT_FLOW | 1)) != (LWSGS_AUTH_FORGOT_FLOW | 1)) {
|
||||
/* otherwise user:pass must be right */
|
||||
lwsl_debug("checking pw\n");
|
||||
if (lwsgs_check_credentials(vhd,
|
||||
lws_spa_get_string(pss->spa, FGS_USERNAME),
|
||||
lws_spa_get_string(pss->spa, FGS_CURPW))) {
|
||||
lwsl_notice("credentials bad\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
lwsl_debug("current pw checks out\n");
|
||||
|
||||
lws_strncpy(u.username, lws_spa_get_string(pss->spa, FGS_USERNAME),
|
||||
sizeof(u.username));
|
||||
}
|
||||
|
||||
/* does he want to delete his account? */
|
||||
|
||||
if (lws_spa_get_length(pss->spa, FGS_DELETE)) {
|
||||
struct lws_gs_event_args a;
|
||||
|
||||
lwsl_notice("deleting account\n");
|
||||
|
||||
a.event = LWSGSE_DELETED;
|
||||
a.username = u.username;
|
||||
a.email = "";
|
||||
lws_callback_vhost_protocols_vhost(lws_get_vhost(wsi),
|
||||
LWS_CALLBACK_GS_EVENT, &a, 0);
|
||||
|
||||
lws_snprintf(s, sizeof(s) - 1,
|
||||
"delete from users where username='%s';"
|
||||
"delete from sessions where username='%s';",
|
||||
lws_sql_purify(esc, u.username, sizeof(esc) - 1),
|
||||
lws_sql_purify(esc, u.username, sizeof(esc) - 1));
|
||||
goto sql;
|
||||
}
|
||||
|
||||
if (lwsgs_hash_password(vhd, lws_spa_get_string(pss->spa, FGS_PASSWORD), &u))
|
||||
return 1;
|
||||
|
||||
lwsl_notice("updating password hash\n");
|
||||
|
||||
lws_snprintf(s, sizeof(s) - 1,
|
||||
"update users set pwhash='%s', pwsalt='%s', "
|
||||
"last_forgot_validated=0 where username='%s';",
|
||||
u.pwhash.id, u.pwsalt.id,
|
||||
lws_sql_purify(esc, u.username, sizeof(esc) - 1));
|
||||
|
||||
sql:
|
||||
if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) {
|
||||
lwsl_err("Unable to update pw hash: %s\n",
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
lwsgs_handler_forgot_pw_form(struct per_vhost_data__gs *vhd,
|
||||
struct lws *wsi, struct per_session_data__gs *pss)
|
||||
{
|
||||
char esc[96], esc1[96], esc2[96], esc3[96], esc4[96];
|
||||
char s[LWSGS_EMAIL_CONTENT_SIZE];
|
||||
unsigned char sid_rand[32];
|
||||
#if defined(LWS_WITH_SMTP)
|
||||
lws_smtp_email_t *em;
|
||||
#endif
|
||||
struct lwsgs_user u;
|
||||
lwsgw_hash hash;
|
||||
int n;
|
||||
|
||||
lwsl_notice("FORGOT %s %s\n",
|
||||
lws_spa_get_string(pss->spa, FGS_USERNAME),
|
||||
lws_spa_get_string(pss->spa, FGS_EMAIL));
|
||||
|
||||
if (!lws_spa_get_string(pss->spa, FGS_USERNAME) &&
|
||||
!lws_spa_get_string(pss->spa, FGS_EMAIL)) {
|
||||
lwsl_err("Form must provide either "
|
||||
"username or email\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!lws_spa_get_string(pss->spa, FGS_FORGOT_GOOD) ||
|
||||
!lws_spa_get_string(pss->spa, FGS_FORGOT_BAD) ||
|
||||
!lws_spa_get_string(pss->spa, FGS_FORGOT_POST_GOOD) ||
|
||||
!lws_spa_get_string(pss->spa, FGS_FORGOT_POST_BAD)) {
|
||||
lwsl_err("Form must provide reg-good "
|
||||
"and reg-bad (and post-*)"
|
||||
"targets\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
u.username[0] = '\0';
|
||||
if (lws_spa_get_string(pss->spa, FGS_USERNAME))
|
||||
lws_snprintf(s, sizeof(s) - 1,
|
||||
"select username,email "
|
||||
"from users where username = '%s';",
|
||||
lws_sql_purify(esc, lws_spa_get_string(pss->spa, FGS_USERNAME),
|
||||
sizeof(esc) - 1));
|
||||
else
|
||||
lws_snprintf(s, sizeof(s) - 1,
|
||||
"select username,email "
|
||||
"from users where email = '%s';",
|
||||
lws_sql_purify(esc, lws_spa_get_string(pss->spa, FGS_EMAIL), sizeof(esc) - 1));
|
||||
if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) !=
|
||||
SQLITE_OK) {
|
||||
lwsl_err("Unable to lookup token: %s\n",
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
return 1;
|
||||
}
|
||||
if (!u.username[0]) {
|
||||
lwsl_err("No match found %s\n", s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lws_get_peer_simple(wsi, pss->ip, sizeof(pss->ip));
|
||||
if (lws_get_random(vhd->context, sid_rand,
|
||||
sizeof(sid_rand)) !=
|
||||
sizeof(sid_rand)) {
|
||||
lwsl_err("Problem getting random for token\n");
|
||||
return 1;
|
||||
}
|
||||
sha256_to_lwsgw_hash(sid_rand, &hash);
|
||||
|
||||
lws_snprintf(s, sizeof(s) - 1,
|
||||
"update users set token='%s',token_time='%ld' where username='%s';",
|
||||
hash.id, (long)lws_now_secs(),
|
||||
lws_sql_purify(esc, u.username, sizeof(esc) - 1));
|
||||
if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) !=
|
||||
SQLITE_OK) {
|
||||
lwsl_err("Unable to set token: %s\n",
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
return 1;
|
||||
}
|
||||
|
||||
n = lws_snprintf(s, sizeof(s),
|
||||
"From: Forgot Password Assistant Noreply <%s>\n"
|
||||
"To: %s <%s>\n"
|
||||
"Subject: Password reset request\n"
|
||||
"\n"
|
||||
"Hello, %s\n\n"
|
||||
"We received a password reset request from IP %s for this email,\n"
|
||||
"to confirm you want to do that, please click the link below.\n\n",
|
||||
lws_sql_purify(esc, vhd->email_from, sizeof(esc) - 1),
|
||||
lws_sql_purify(esc1, u.username, sizeof(esc1) - 1),
|
||||
lws_sql_purify(esc2, u.email, sizeof(esc2) - 1),
|
||||
lws_sql_purify(esc3, u.username, sizeof(esc3) - 1),
|
||||
lws_sql_purify(esc4, pss->ip, sizeof(esc4) - 1));
|
||||
lws_snprintf(s + n, sizeof(s) - n,
|
||||
"%s/lwsgs-forgot?token=%s"
|
||||
"&good=%s"
|
||||
"&bad=%s\n\n"
|
||||
"If this request is unexpected, please ignore it and\n"
|
||||
"no further action will be taken.\n\n"
|
||||
"If you have any questions or concerns about this\n"
|
||||
"automated email, you can contact a real person at\n"
|
||||
"%s.\n"
|
||||
"\n.\n",
|
||||
vhd->email_confirm_url, hash.id,
|
||||
lws_urlencode(esc1,
|
||||
lws_spa_get_string(pss->spa, FGS_FORGOT_POST_GOOD),
|
||||
sizeof(esc1) - 1),
|
||||
lws_urlencode(esc3,
|
||||
lws_spa_get_string(pss->spa, FGS_FORGOT_POST_BAD),
|
||||
sizeof(esc3) - 1),
|
||||
vhd->email_contact_person);
|
||||
|
||||
puts(s);
|
||||
#if defined(LWS_WITH_SMTP)
|
||||
|
||||
em = lws_smtpc_alloc_email_helper(s, n, vhd->email_from, u.email,
|
||||
u.username, strlen(u.username),
|
||||
vhd, lwsgs_smtp_client_done);
|
||||
if (!em)
|
||||
return 1;
|
||||
if (lws_smtpc_add_email(vhd->smtp_client, em))
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
lwsgs_handler_register_form(struct per_vhost_data__gs *vhd,
|
||||
struct lws *wsi,
|
||||
struct per_session_data__gs *pss)
|
||||
{
|
||||
unsigned char buffer[LWS_PRE + LWSGS_EMAIL_CONTENT_SIZE];
|
||||
char esc[96], esc1[96], esc2[96], esc3[96], esc4[96];
|
||||
char s[LWSGS_EMAIL_CONTENT_SIZE];
|
||||
unsigned char sid_rand[32];
|
||||
#if defined(LWS_WITH_SMTP)
|
||||
lws_smtp_email_t *em;
|
||||
#endif
|
||||
struct lwsgs_user u;
|
||||
lwsgw_hash hash;
|
||||
size_t n;
|
||||
|
||||
lwsl_notice("REGISTER %s %s %s\n",
|
||||
lws_spa_get_string(pss->spa, FGS_USERNAME),
|
||||
lws_spa_get_string(pss->spa, FGS_PASSWORD),
|
||||
lws_spa_get_string(pss->spa, FGS_EMAIL));
|
||||
if (lwsgs_get_sid_from_wsi(wsi,
|
||||
&pss->login_session))
|
||||
return 1;
|
||||
|
||||
lws_get_peer_simple(wsi, pss->ip, sizeof(pss->ip));
|
||||
lwsl_notice("IP=%s\n", pss->ip);
|
||||
|
||||
if (!lws_spa_get_string(pss->spa, FGS_REG_GOOD) ||
|
||||
!lws_spa_get_string(pss->spa, FGS_REG_BAD)) {
|
||||
lwsl_info("Form must provide reg-good and reg-bad targets\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* admin user cannot be registered in user db */
|
||||
if (!strcmp(vhd->admin_user,
|
||||
lws_spa_get_string(pss->spa, FGS_USERNAME)))
|
||||
return 1;
|
||||
|
||||
if (!lwsgs_lookup_user(vhd,
|
||||
lws_spa_get_string(pss->spa, FGS_USERNAME), &u)) {
|
||||
lwsl_notice("user %s already registered\n",
|
||||
lws_spa_get_string(pss->spa, FGS_USERNAME));
|
||||
return 1;
|
||||
}
|
||||
|
||||
u.username[0] = '\0';
|
||||
lws_snprintf(s, sizeof(s) - 1, "select username, email from users where email = '%s';",
|
||||
lws_sql_purify(esc, lws_spa_get_string(pss->spa, FGS_EMAIL),
|
||||
sizeof(esc) - 1));
|
||||
|
||||
if (sqlite3_exec(vhd->pdb, s,
|
||||
lwsgs_lookup_callback_user, &u, NULL) != SQLITE_OK) {
|
||||
lwsl_err("Unable to lookup token: %s\n",
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (u.username[0]) {
|
||||
lwsl_notice("email %s already in use\n",
|
||||
lws_spa_get_string(pss->spa, FGS_USERNAME));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (lwsgs_hash_password(vhd, lws_spa_get_string(pss->spa, FGS_PASSWORD),
|
||||
&u)) {
|
||||
lwsl_err("Password hash failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (lws_get_random(vhd->context, sid_rand, sizeof(sid_rand)) !=
|
||||
sizeof(sid_rand)) {
|
||||
lwsl_err("Problem getting random for token\n");
|
||||
return 1;
|
||||
}
|
||||
sha256_to_lwsgw_hash(sid_rand, &hash);
|
||||
|
||||
lws_snprintf((char *)buffer, sizeof(buffer) - 1,
|
||||
"insert into users(username,"
|
||||
" creation_time, ip, email, verified,"
|
||||
" pwhash, pwsalt, token, last_forgot_validated)"
|
||||
" values ('%s', %lu, '%s', '%s', 0,"
|
||||
" '%s', '%s', '%s', 0);",
|
||||
lws_sql_purify(esc, lws_spa_get_string(pss->spa, FGS_USERNAME), sizeof(esc) - 1),
|
||||
(unsigned long)lws_now_secs(),
|
||||
lws_sql_purify(esc1, pss->ip, sizeof(esc1) - 1),
|
||||
lws_sql_purify(esc2, lws_spa_get_string(pss->spa, FGS_EMAIL), sizeof(esc2) - 1),
|
||||
u.pwhash.id, u.pwsalt.id, hash.id);
|
||||
|
||||
if (sqlite3_exec(vhd->pdb, (char *)buffer, NULL, NULL, NULL) != SQLITE_OK) {
|
||||
lwsl_err("Unable to insert user: %s\n",
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
return 1;
|
||||
}
|
||||
|
||||
n = lws_snprintf(s, sizeof(s),
|
||||
"From: Noreply <%s>\n"
|
||||
"To: %s <%s>\n"
|
||||
"Subject: Registration verification\n"
|
||||
"\n"
|
||||
"Hello, %s\n\n"
|
||||
"We received a registration from IP %s using this email,\n"
|
||||
"to confirm it is legitimate, please click the link below.\n\n"
|
||||
"%s/lwsgs-confirm?token=%s\n\n"
|
||||
"If this request is unexpected, please ignore it and\n"
|
||||
"no further action will be taken.\n\n"
|
||||
"If you have any questions or concerns about this\n"
|
||||
"automated email, you can contact a real person at\n"
|
||||
"%s.\n"
|
||||
"\n.\n",
|
||||
lws_sql_purify(esc, vhd->email_from, sizeof(esc) - 1),
|
||||
lws_sql_purify(esc1, lws_spa_get_string(pss->spa, FGS_USERNAME), sizeof(esc1) - 1),
|
||||
lws_sql_purify(esc2, lws_spa_get_string(pss->spa, FGS_EMAIL), sizeof(esc2) - 1),
|
||||
lws_sql_purify(esc3, lws_spa_get_string(pss->spa, FGS_USERNAME), sizeof(esc3) - 1),
|
||||
lws_sql_purify(esc4, pss->ip, sizeof(esc4) - 1),
|
||||
vhd->email_confirm_url, hash.id,
|
||||
vhd->email_contact_person);
|
||||
|
||||
#if defined(LWS_WITH_SMTP)
|
||||
em = lws_smtpc_alloc_email_helper(s, n, vhd->email_from,
|
||||
lws_spa_get_string(pss->spa, FGS_EMAIL),
|
||||
lws_spa_get_string(pss->spa, FGS_USERNAME),
|
||||
strlen(lws_spa_get_string(pss->spa, FGS_USERNAME)),
|
||||
vhd, lwsgs_smtp_client_done_sentvfy);
|
||||
if (!em)
|
||||
return 1;
|
||||
|
||||
if (lws_smtpc_add_email(vhd->smtp_client, em))
|
||||
return 1;
|
||||
#else
|
||||
(void)n;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,171 +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.
|
||||
*/
|
||||
|
||||
#define LWS_DLL
|
||||
#define LWS_INTERNAL
|
||||
#include <libwebsockets.h>
|
||||
|
||||
#include <sqlite3.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LWSGS_VERIFIED_ACCEPTED 100
|
||||
|
||||
enum {
|
||||
FGS_USERNAME,
|
||||
FGS_PASSWORD,
|
||||
FGS_PASSWORD2,
|
||||
FGS_EMAIL,
|
||||
FGS_REGISTER,
|
||||
FGS_GOOD,
|
||||
FGS_BAD,
|
||||
FGS_REG_GOOD,
|
||||
FGS_REG_BAD,
|
||||
FGS_ADMIN,
|
||||
FGS_FORGOT,
|
||||
FGS_FORGOT_GOOD,
|
||||
FGS_FORGOT_BAD,
|
||||
FGS_FORGOT_POST_GOOD,
|
||||
FGS_FORGOT_POST_BAD,
|
||||
FGS_CHANGE,
|
||||
FGS_CURPW,
|
||||
FGS_DELETE,
|
||||
};
|
||||
|
||||
struct lwsgs_user {
|
||||
char username[32];
|
||||
char ip[16];
|
||||
lwsgw_hash pwhash;
|
||||
lwsgw_hash pwsalt;
|
||||
lwsgw_hash token;
|
||||
time_t created;
|
||||
time_t last_forgot_validated;
|
||||
char email[100];
|
||||
int verified;
|
||||
};
|
||||
|
||||
struct per_vhost_data__gs {
|
||||
lws_abs_t *smtp_client;
|
||||
struct lwsgs_user u;
|
||||
lws_token_map_t transport_tokens[3];
|
||||
lws_token_map_t protocol_tokens[2];
|
||||
char helo[64], ip[64];
|
||||
struct lws_context *context;
|
||||
char session_db[256];
|
||||
char admin_user[32];
|
||||
char urlroot[48];
|
||||
char confounder[32];
|
||||
char email_contact_person[128];
|
||||
char email_title[128];
|
||||
char email_template[128];
|
||||
char email_confirm_url[128];
|
||||
char email_from[128];
|
||||
lwsgw_hash admin_password_sha256;
|
||||
sqlite3 *pdb;
|
||||
int timeout_idle_secs;
|
||||
int timeout_absolute_secs;
|
||||
int timeout_anon_absolute_secs;
|
||||
int timeout_email_secs;
|
||||
time_t last_session_expire;
|
||||
};
|
||||
|
||||
struct per_session_data__gs {
|
||||
struct lws_spa *spa;
|
||||
lwsgw_hash login_session;
|
||||
lwsgw_hash delete_session;
|
||||
unsigned int login_expires;
|
||||
char onward[256];
|
||||
char result[500 + LWS_PRE];
|
||||
char urldec[500 + LWS_PRE];
|
||||
int result_len;
|
||||
char ip[46];
|
||||
struct lws_process_html_state phs;
|
||||
int spos;
|
||||
char check_response_value;
|
||||
|
||||
unsigned int logging_out:1;
|
||||
unsigned int check_response:1;
|
||||
};
|
||||
|
||||
/* utils.c */
|
||||
|
||||
int
|
||||
lwsgs_lookup_callback_user(void *priv, int cols, char **col_val,
|
||||
char **col_name);
|
||||
void
|
||||
lwsgw_cookie_from_session(lwsgw_hash *sid, time_t expires, char **p, char *end);
|
||||
int
|
||||
lwsgs_get_sid_from_wsi(struct lws *wsi, lwsgw_hash *sid);
|
||||
int
|
||||
lwsgs_lookup_session(struct per_vhost_data__gs *vhd,
|
||||
const lwsgw_hash *sid, char *username, int len);
|
||||
int
|
||||
lwsgs_get_auth_level(struct per_vhost_data__gs *vhd,
|
||||
const char *username);
|
||||
int
|
||||
lwsgs_check_credentials(struct per_vhost_data__gs *vhd,
|
||||
const char *username, const char *password);
|
||||
void
|
||||
sha256_to_lwsgw_hash(unsigned char *hash, lwsgw_hash *shash);
|
||||
unsigned int
|
||||
lwsgs_now_secs(void);
|
||||
int
|
||||
lwsgw_check_admin(struct per_vhost_data__gs *vhd,
|
||||
const char *username, const char *password);
|
||||
int
|
||||
lwsgs_hash_password(struct per_vhost_data__gs *vhd,
|
||||
const char *password, struct lwsgs_user *u);
|
||||
int
|
||||
lwsgs_new_session_id(struct per_vhost_data__gs *vhd,
|
||||
lwsgw_hash *sid, const char *username, int exp);
|
||||
int
|
||||
lwsgs_lookup_user(struct per_vhost_data__gs *vhd,
|
||||
const char *username, struct lwsgs_user *u);
|
||||
int
|
||||
lwsgw_update_session(struct per_vhost_data__gs *vhd,
|
||||
lwsgw_hash *hash, const char *user);
|
||||
int
|
||||
lwsgw_expire_old_sessions(struct per_vhost_data__gs *vhd);
|
||||
|
||||
|
||||
/* handlers.c */
|
||||
|
||||
int
|
||||
lwsgs_handler_confirm(struct per_vhost_data__gs *vhd, struct lws *wsi,
|
||||
struct per_session_data__gs *pss);
|
||||
int
|
||||
lwsgs_handler_forgot(struct per_vhost_data__gs *vhd, struct lws *wsi,
|
||||
struct per_session_data__gs *pss);
|
||||
int
|
||||
lwsgs_handler_check(struct per_vhost_data__gs *vhd, struct lws *wsi,
|
||||
struct per_session_data__gs *pss, const char *in);
|
||||
int
|
||||
lwsgs_handler_change_password(struct per_vhost_data__gs *vhd, struct lws *wsi,
|
||||
struct per_session_data__gs *pss);
|
||||
int
|
||||
lwsgs_handler_forgot_pw_form(struct per_vhost_data__gs *vhd, struct lws *wsi,
|
||||
struct per_session_data__gs *pss);
|
||||
int
|
||||
lwsgs_handler_register_form(struct per_vhost_data__gs *vhd, struct lws *wsi,
|
||||
struct per_session_data__gs *pss);
|
||||
|
|
@ -1,920 +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 "private-lwsgs.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* keep changes in sync with the enum in lwsgs.h */
|
||||
static const char * const param_names[] = {
|
||||
"username",
|
||||
"password",
|
||||
"password2",
|
||||
"email",
|
||||
"register",
|
||||
"good",
|
||||
"bad",
|
||||
"reg-good",
|
||||
"reg-bad",
|
||||
"admin",
|
||||
"forgot",
|
||||
"forgot-good",
|
||||
"forgot-bad",
|
||||
"forgot-post-good",
|
||||
"forgot-post-bad",
|
||||
"change",
|
||||
"curpw",
|
||||
"delete"
|
||||
};
|
||||
|
||||
struct lwsgs_fill_args {
|
||||
char *buf;
|
||||
int len;
|
||||
};
|
||||
|
||||
static const struct lws_protocols protocols[];
|
||||
|
||||
struct lwsgs_subst_args
|
||||
{
|
||||
struct per_session_data__gs *pss;
|
||||
struct per_vhost_data__gs *vhd;
|
||||
struct lws *wsi;
|
||||
};
|
||||
|
||||
static const char *
|
||||
lwsgs_subst(void *data, int index)
|
||||
{
|
||||
struct lwsgs_subst_args *a = (struct lwsgs_subst_args *)data;
|
||||
struct lwsgs_user u;
|
||||
lwsgw_hash sid;
|
||||
char esc[96], s[100];
|
||||
int n;
|
||||
|
||||
a->pss->result[0] = '\0';
|
||||
u.email[0] = '\0';
|
||||
if (!lwsgs_get_sid_from_wsi(a->wsi, &sid)) {
|
||||
if (lwsgs_lookup_session(a->vhd, &sid, a->pss->result, 31)) {
|
||||
lwsl_notice("sid lookup for %s failed\n", sid.id);
|
||||
a->pss->delete_session = sid;
|
||||
return NULL;
|
||||
}
|
||||
lws_snprintf(s, sizeof(s) - 1, "select username,email "
|
||||
"from users where username = '%s';",
|
||||
lws_sql_purify(esc, a->pss->result, sizeof(esc) - 1));
|
||||
if (sqlite3_exec(a->vhd->pdb, s, lwsgs_lookup_callback_user,
|
||||
&u, NULL) != SQLITE_OK) {
|
||||
lwsl_err("Unable to lookup token: %s\n",
|
||||
sqlite3_errmsg(a->vhd->pdb));
|
||||
a->pss->delete_session = sid;
|
||||
return NULL;
|
||||
}
|
||||
} else
|
||||
lwsl_notice("no sid\n");
|
||||
|
||||
lws_strncpy(a->pss->result + 32, u.email, 100);
|
||||
|
||||
switch (index) {
|
||||
case 0:
|
||||
return a->pss->result;
|
||||
|
||||
case 1:
|
||||
n = lwsgs_get_auth_level(a->vhd, a->pss->result);
|
||||
sprintf(a->pss->result, "%d", n);
|
||||
return a->pss->result;
|
||||
case 2:
|
||||
return a->pss->result + 32;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
lws_get_effective_host(struct lws *wsi, char *buf, size_t buflen)
|
||||
{
|
||||
#if defined(LWS_ROLE_H2)
|
||||
/* h2 */
|
||||
if (lws_hdr_copy(wsi, buf, buflen - 1,
|
||||
WSI_TOKEN_HTTP_COLON_AUTHORITY) > 0)
|
||||
return 0;
|
||||
#endif
|
||||
/* h1 */
|
||||
if (lws_hdr_copy(wsi, buf, buflen - 1, WSI_TOKEN_HOST) > 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
callback_generic_sessions(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
struct per_session_data__gs *pss = (struct per_session_data__gs *)user;
|
||||
const struct lws_protocol_vhost_options *pvo;
|
||||
struct per_vhost_data__gs *vhd = (struct per_vhost_data__gs *)
|
||||
lws_protocol_vh_priv_get(lws_get_vhost(wsi),
|
||||
lws_vhost_name_to_protocol(lws_get_vhost(wsi),
|
||||
"protocol-generic-sessions"));
|
||||
char cookie[1024], username[32], *pc = cookie;
|
||||
unsigned char buffer[LWS_PRE + LWSGS_EMAIL_CONTENT_SIZE];
|
||||
struct lws_process_html_args *args = in;
|
||||
struct lws_session_info *sinfo;
|
||||
char s[LWSGS_EMAIL_CONTENT_SIZE];
|
||||
unsigned char *p, *start, *end;
|
||||
const char *cp, *cp1;
|
||||
sqlite3_stmt *sm;
|
||||
lwsgw_hash sid;
|
||||
#if defined(LWS_WITH_SMTP)
|
||||
lws_abs_t abs;
|
||||
#endif
|
||||
int n;
|
||||
|
||||
switch (reason) {
|
||||
case LWS_CALLBACK_PROTOCOL_INIT: /* per vhost */
|
||||
|
||||
vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
|
||||
lws_get_protocol(wsi), sizeof(struct per_vhost_data__gs));
|
||||
if (!vhd)
|
||||
return 1;
|
||||
vhd->context = lws_get_context(wsi);
|
||||
|
||||
/* defaults */
|
||||
vhd->timeout_idle_secs = 600;
|
||||
vhd->timeout_absolute_secs = 36000;
|
||||
vhd->timeout_anon_absolute_secs = 1200;
|
||||
vhd->timeout_email_secs = 24 * 3600;
|
||||
|
||||
|
||||
strcpy(vhd->helo, "unconfigured.com");
|
||||
strcpy(vhd->ip, "127.0.0.1");
|
||||
strcpy(vhd->email_from, "noreply@unconfigured.com");
|
||||
strcpy(vhd->email_title, "Registration Email from unconfigured");
|
||||
vhd->urlroot[0] = '\0';
|
||||
|
||||
pvo = (const struct lws_protocol_vhost_options *)in;
|
||||
while (pvo) {
|
||||
if (!strcmp(pvo->name, "admin-user"))
|
||||
lws_strncpy(vhd->admin_user, pvo->value,
|
||||
sizeof(vhd->admin_user));
|
||||
if (!strcmp(pvo->name, "urlroot"))
|
||||
lws_strncpy(vhd->urlroot, pvo->value,
|
||||
sizeof(vhd->urlroot));
|
||||
if (!strcmp(pvo->name, "admin-password-sha256"))
|
||||
lws_strncpy(vhd->admin_password_sha256.id, pvo->value,
|
||||
sizeof(vhd->admin_password_sha256.id));
|
||||
if (!strcmp(pvo->name, "session-db"))
|
||||
lws_strncpy(vhd->session_db, pvo->value,
|
||||
sizeof(vhd->session_db));
|
||||
if (!strcmp(pvo->name, "confounder"))
|
||||
lws_strncpy(vhd->confounder, pvo->value,
|
||||
sizeof(vhd->confounder));
|
||||
if (!strcmp(pvo->name, "email-from"))
|
||||
lws_strncpy(vhd->email_from, pvo->value,
|
||||
sizeof(vhd->email_from));
|
||||
if (!strcmp(pvo->name, "email-helo"))
|
||||
lws_strncpy(vhd->helo, pvo->value, sizeof(vhd->helo));
|
||||
if (!strcmp(pvo->name, "email-template"))
|
||||
lws_strncpy(vhd->email_template, pvo->value,
|
||||
sizeof(vhd->email_template));
|
||||
if (!strcmp(pvo->name, "email-title"))
|
||||
lws_strncpy(vhd->email_title, pvo->value,
|
||||
sizeof(vhd->email_title));
|
||||
if (!strcmp(pvo->name, "email-contact-person"))
|
||||
lws_strncpy(vhd->email_contact_person, pvo->value,
|
||||
sizeof(vhd->email_contact_person));
|
||||
if (!strcmp(pvo->name, "email-confirm-url-base"))
|
||||
lws_strncpy(vhd->email_confirm_url, pvo->value,
|
||||
sizeof(vhd->email_confirm_url));
|
||||
if (!strcmp(pvo->name, "email-server-ip"))
|
||||
lws_strncpy(vhd->ip, pvo->value, sizeof(vhd->ip));
|
||||
|
||||
if (!strcmp(pvo->name, "timeout-idle-secs"))
|
||||
vhd->timeout_idle_secs = atoi(pvo->value);
|
||||
if (!strcmp(pvo->name, "timeout-absolute-secs"))
|
||||
vhd->timeout_absolute_secs = atoi(pvo->value);
|
||||
if (!strcmp(pvo->name, "timeout-anon-absolute-secs"))
|
||||
vhd->timeout_anon_absolute_secs = atoi(pvo->value);
|
||||
if (!strcmp(pvo->name, "email-expire"))
|
||||
vhd->timeout_email_secs = atoi(pvo->value);
|
||||
pvo = pvo->next;
|
||||
}
|
||||
if (!vhd->admin_user[0] ||
|
||||
!vhd->admin_password_sha256.id[0] ||
|
||||
!vhd->session_db[0]) {
|
||||
lwsl_err("generic-sessions: "
|
||||
"You must give \"admin-user\", "
|
||||
"\"admin-password-sha256\", "
|
||||
"and \"session_db\" per-vhost options\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (lws_struct_sq3_open(lws_get_context(wsi),
|
||||
vhd->session_db, 1, &vhd->pdb)) {
|
||||
lwsl_err("Unable to open session db %s: %s\n",
|
||||
vhd->session_db, sqlite3_errmsg(vhd->pdb));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (sqlite3_prepare(vhd->pdb,
|
||||
"create table if not exists sessions ("
|
||||
" name char(65),"
|
||||
" username varchar(32),"
|
||||
" expire integer"
|
||||
");",
|
||||
-1, &sm, NULL) != SQLITE_OK) {
|
||||
lwsl_err("Unable to prepare session table init: %s\n",
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (sqlite3_step(sm) != SQLITE_DONE) {
|
||||
lwsl_err("Unable to run session table init: %s\n",
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
|
||||
return 1;
|
||||
}
|
||||
sqlite3_finalize(sm);
|
||||
|
||||
if (sqlite3_exec(vhd->pdb,
|
||||
"create table if not exists users ("
|
||||
" username varchar(32),"
|
||||
" creation_time integer,"
|
||||
" ip varchar(46),"
|
||||
" email varchar(100),"
|
||||
" pwhash varchar(65),"
|
||||
" pwsalt varchar(65),"
|
||||
" pwchange_time integer,"
|
||||
" token varchar(65),"
|
||||
" verified integer,"
|
||||
" token_time integer,"
|
||||
" last_forgot_validated integer,"
|
||||
" primary key (username)"
|
||||
");",
|
||||
NULL, NULL, NULL) != SQLITE_OK) {
|
||||
lwsl_err("Unable to create user table: %s\n",
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if defined(LWS_WITH_SMTP)
|
||||
|
||||
memset(&abs, 0, sizeof(abs));
|
||||
abs.vh = lws_get_vhost(wsi);
|
||||
|
||||
/* select the protocol and bind its tokens */
|
||||
|
||||
abs.ap = lws_abs_protocol_get_by_name("smtp");
|
||||
if (!abs.ap)
|
||||
return 1;
|
||||
|
||||
vhd->protocol_tokens[0].name_index = LTMI_PSMTP_V_HELO;
|
||||
vhd->protocol_tokens[0].u.value = vhd->helo;
|
||||
|
||||
abs.ap_tokens = vhd->protocol_tokens;
|
||||
|
||||
/* select the transport and bind its tokens */
|
||||
|
||||
abs.at = lws_abs_transport_get_by_name("raw_skt");
|
||||
if (!abs.at)
|
||||
return 1;
|
||||
|
||||
vhd->transport_tokens[0].name_index = LTMI_PEER_V_DNS_ADDRESS;
|
||||
vhd->transport_tokens[0].u.value = vhd->ip;
|
||||
vhd->transport_tokens[1].name_index = LTMI_PEER_LV_PORT;
|
||||
vhd->transport_tokens[1].u.lvalue = 25;
|
||||
|
||||
abs.at_tokens = vhd->transport_tokens;
|
||||
|
||||
vhd->smtp_client = lws_abs_bind_and_create_instance(&abs);
|
||||
if (!vhd->smtp_client)
|
||||
return 1;
|
||||
|
||||
lwsl_notice("%s: created SMTP client\n", __func__);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_PROTOCOL_DESTROY:
|
||||
// lwsl_notice("gs: LWS_CALLBACK_PROTOCOL_DESTROY: v=%p, ctx=%p\n", vhd, vhd->context);
|
||||
if (vhd->pdb) {
|
||||
sqlite3_close(vhd->pdb);
|
||||
vhd->pdb = NULL;
|
||||
}
|
||||
#if defined(LWS_WITH_SMTP)
|
||||
if (vhd->smtp_client)
|
||||
lws_abs_destroy_instance(&vhd->smtp_client);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_HTTP_WRITEABLE:
|
||||
if (!pss->check_response)
|
||||
break;
|
||||
pss->check_response = 0;
|
||||
n = lws_write(wsi, (unsigned char *)&pss->check_response_value,
|
||||
1, LWS_WRITE_HTTP | LWS_WRITE_H2_STREAM_END);
|
||||
if (n != 1)
|
||||
return -1;
|
||||
goto try_to_reuse;
|
||||
|
||||
case LWS_CALLBACK_HTTP:
|
||||
if (!pss) {
|
||||
lwsl_err("%s: no valid pss\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pss->login_session.id[0] = '\0';
|
||||
pss->phs.pos = 0;
|
||||
|
||||
cp = in;
|
||||
if ((*(const char *)in == '/'))
|
||||
cp++;
|
||||
|
||||
if (lws_get_effective_host(wsi, cookie, sizeof(cookie))) {
|
||||
lwsl_err("%s: HTTP: no effective host\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lwsl_notice("LWS_CALLBACK_HTTP: %s, HOST '%s'\n",
|
||||
(const char *)in, cookie);
|
||||
|
||||
n = strlen(cp);
|
||||
|
||||
lws_snprintf(pss->onward, sizeof(pss->onward),
|
||||
"%s%s", vhd->urlroot, (const char *)in);
|
||||
|
||||
if (n >= 12 &&
|
||||
!strcmp(cp + n - 12, "lwsgs-forgot")) {
|
||||
lwsgs_handler_forgot(vhd, wsi, pss);
|
||||
goto redirect_with_cookie;
|
||||
}
|
||||
|
||||
if (n >= 13 &&
|
||||
!strcmp(cp + n - 13, "lwsgs-confirm")) {
|
||||
lwsgs_handler_confirm(vhd, wsi, pss);
|
||||
goto redirect_with_cookie;
|
||||
}
|
||||
cp1 = strstr(cp, "lwsgs-check/");
|
||||
if (cp1) {
|
||||
lwsgs_handler_check(vhd, wsi, pss, cp1 + 12);
|
||||
/* second, async part will complete transaction */
|
||||
break;
|
||||
}
|
||||
|
||||
if (n >= 11 && cp && !strcmp(cp + n - 11, "lwsgs-login"))
|
||||
break;
|
||||
if (n >= 12 && cp && !strcmp(cp + n - 12, "lwsgs-logout"))
|
||||
break;
|
||||
if (n >= 12 && cp && !strcmp(cp + n - 12, "lwsgs-forgot"))
|
||||
break;
|
||||
if (n >= 12 && cp && !strcmp(cp + n - 12, "lwsgs-change"))
|
||||
break;
|
||||
|
||||
/* if no legitimate url for GET, return 404 */
|
||||
|
||||
lwsl_err("%s: http doing 404 on %s\n", __func__, cp ? cp : "null");
|
||||
lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL);
|
||||
|
||||
return -1;
|
||||
//goto try_to_reuse;
|
||||
|
||||
case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
|
||||
args = (struct lws_process_html_args *)in;
|
||||
if (!args->chunked)
|
||||
break;
|
||||
case LWS_CALLBACK_CHECK_ACCESS_RIGHTS:
|
||||
n = 0;
|
||||
username[0] = '\0';
|
||||
sid.id[0] = '\0';
|
||||
args = (struct lws_process_html_args *)in;
|
||||
lwsl_notice("%s: LWS_CALLBACK_CHECK_ACCESS_RIGHTS: need 0x%x\n",
|
||||
__func__, args->max_len);
|
||||
if (!lwsgs_get_sid_from_wsi(wsi, &sid)) {
|
||||
if (lwsgs_lookup_session(vhd, &sid, username,
|
||||
sizeof(username))) {
|
||||
|
||||
/*
|
||||
* if we're authenticating for ws, we don't
|
||||
* want to redirect it or gain a cookie on that,
|
||||
* he'll need to get the cookie from http
|
||||
* interactions outside of this.
|
||||
*/
|
||||
if (args->chunked) {
|
||||
lwsl_notice("%s: ws auth failed\n",
|
||||
__func__);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
lwsl_notice("session lookup for %s failed, "
|
||||
"probably expired\n", sid.id);
|
||||
pss->delete_session = sid;
|
||||
args->final = 1; /* signal we dealt with it */
|
||||
lws_snprintf(pss->onward, sizeof(pss->onward) - 1,
|
||||
"%s%s", vhd->urlroot, args->p);
|
||||
lwsl_notice("redirecting to ourselves with "
|
||||
"cookie refresh\n");
|
||||
/* we need a redirect to ourselves,
|
||||
* session cookie is expired */
|
||||
goto redirect_with_cookie;
|
||||
}
|
||||
} else
|
||||
lwsl_notice("%s: failed to get sid from wsi\n", __func__);
|
||||
|
||||
n = lwsgs_get_auth_level(vhd, username);
|
||||
lwsl_notice("%s: lwsgs_get_auth_level '%s' says %d\n", __func__, username, n);
|
||||
|
||||
if ((args->max_len & n) != args->max_len) {
|
||||
lwsl_notice("Access rights fail 0x%X vs 0x%X (cookie %s)\n",
|
||||
args->max_len, n, sid.id);
|
||||
return 1;
|
||||
}
|
||||
lwsl_debug("Access rights OK\n");
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_SESSION_INFO:
|
||||
{
|
||||
struct lwsgs_user u;
|
||||
sinfo = (struct lws_session_info *)in;
|
||||
sinfo->username[0] = '\0';
|
||||
sinfo->email[0] = '\0';
|
||||
sinfo->ip[0] = '\0';
|
||||
sinfo->session[0] = '\0';
|
||||
sinfo->mask = 0;
|
||||
|
||||
sid.id[0] = '\0';
|
||||
lwsl_debug("LWS_CALLBACK_SESSION_INFO\n");
|
||||
if (lwsgs_get_sid_from_wsi(wsi, &sid))
|
||||
break;
|
||||
if (lwsgs_lookup_session(vhd, &sid, username, sizeof(username)))
|
||||
break;
|
||||
|
||||
lws_snprintf(s, sizeof(s) - 1,
|
||||
"select username, email from users where username='%s';",
|
||||
username);
|
||||
if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, &u, NULL) !=
|
||||
SQLITE_OK) {
|
||||
lwsl_err("Unable to lookup token: %s\n",
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
break;
|
||||
}
|
||||
lws_strncpy(sinfo->username, u.username, sizeof(sinfo->username));
|
||||
lws_strncpy(sinfo->email, u.email, sizeof(sinfo->email));
|
||||
lws_strncpy(sinfo->session, sid.id, sizeof(sinfo->session));
|
||||
sinfo->mask = lwsgs_get_auth_level(vhd, username);
|
||||
lws_get_peer_simple(wsi, sinfo->ip, sizeof(sinfo->ip));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_PROCESS_HTML:
|
||||
|
||||
args = (struct lws_process_html_args *)in;
|
||||
{
|
||||
static const char * const vars[] = {
|
||||
"$lwsgs_user",
|
||||
"$lwsgs_auth",
|
||||
"$lwsgs_email"
|
||||
};
|
||||
struct lwsgs_subst_args a;
|
||||
|
||||
a.vhd = vhd;
|
||||
a.pss = pss;
|
||||
a.wsi = wsi;
|
||||
|
||||
pss->phs.vars = vars;
|
||||
pss->phs.count_vars = LWS_ARRAY_SIZE(vars);
|
||||
pss->phs.replace = lwsgs_subst;
|
||||
pss->phs.data = &a;
|
||||
|
||||
if (lws_chunked_html_process(args, &pss->phs))
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_HTTP_BODY:
|
||||
if (len < 2) {
|
||||
lwsl_err("%s: HTTP_BODY: len %d < 2\n", __func__, (int)len);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!pss->spa) {
|
||||
pss->spa = lws_spa_create(wsi, param_names,
|
||||
LWS_ARRAY_SIZE(param_names), 1024,
|
||||
NULL, NULL);
|
||||
if (!pss->spa)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lws_spa_process(pss->spa, in, len)) {
|
||||
lwsl_notice("spa process blew\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_HTTP_BODY_COMPLETION:
|
||||
|
||||
lwsl_debug("%s: LWS_CALLBACK_HTTP_BODY_COMPLETION\n", __func__);
|
||||
|
||||
if (!pss->spa)
|
||||
break;
|
||||
|
||||
cp1 = (const char *)pss->onward;
|
||||
if (*cp1 == '/')
|
||||
cp1++;
|
||||
|
||||
|
||||
lws_spa_finalize(pss->spa);
|
||||
n = strlen(cp1);
|
||||
|
||||
if (lws_get_effective_host(wsi, cookie, sizeof(cookie)))
|
||||
return 1;
|
||||
|
||||
if (!strcmp(cp1 + n - 12, "lwsgs-change")) {
|
||||
if (!lwsgs_handler_change_password(vhd, wsi, pss)) {
|
||||
cp = lws_spa_get_string(pss->spa, FGS_GOOD);
|
||||
goto pass;
|
||||
}
|
||||
|
||||
cp = lws_spa_get_string(pss->spa, FGS_BAD);
|
||||
lwsl_notice("user/password no good %s\n",
|
||||
lws_spa_get_string(pss->spa, FGS_USERNAME));
|
||||
lws_snprintf(pss->onward, sizeof(pss->onward),
|
||||
"%s%s", vhd->urlroot, cp);
|
||||
|
||||
pss->onward[sizeof(pss->onward) - 1] = '\0';
|
||||
goto completion_flow;
|
||||
}
|
||||
|
||||
if (!strcmp(cp1 + n - 11, "lwsgs-login")) {
|
||||
lwsl_err("%s: lwsgs-login\n", __func__);
|
||||
if (lws_spa_get_string(pss->spa, FGS_FORGOT) &&
|
||||
lws_spa_get_string(pss->spa, FGS_FORGOT)[0]) {
|
||||
if (lwsgs_handler_forgot_pw_form(vhd, wsi, pss)) {
|
||||
n = FGS_FORGOT_BAD;
|
||||
goto reg_done;
|
||||
}
|
||||
#if defined(LWS_WITH_SMTP)
|
||||
/* get the email monitor to take a look */
|
||||
lws_smtpc_kick(vhd->smtp_client);
|
||||
#endif
|
||||
n = FGS_FORGOT_GOOD;
|
||||
goto reg_done;
|
||||
}
|
||||
|
||||
if (!lws_spa_get_string(pss->spa, FGS_USERNAME) ||
|
||||
!lws_spa_get_string(pss->spa, FGS_PASSWORD)) {
|
||||
lwsl_notice("username '%s' or pw '%s' missing\n",
|
||||
lws_spa_get_string(pss->spa, FGS_USERNAME),
|
||||
lws_spa_get_string(pss->spa, FGS_PASSWORD));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lws_spa_get_string(pss->spa, FGS_REGISTER) &&
|
||||
lws_spa_get_string(pss->spa, FGS_REGISTER)[0]) {
|
||||
|
||||
if (lwsgs_handler_register_form(vhd, wsi, pss))
|
||||
n = FGS_REG_BAD;
|
||||
else {
|
||||
n = FGS_REG_GOOD;
|
||||
#if defined(LWS_WITH_SMTP)
|
||||
/* get the email monitor to take a look */
|
||||
lws_smtpc_kick(vhd->smtp_client);
|
||||
#endif
|
||||
}
|
||||
reg_done:
|
||||
lws_snprintf(pss->onward, sizeof(pss->onward),
|
||||
"%s%s", vhd->urlroot,
|
||||
lws_spa_get_string(pss->spa, n));
|
||||
|
||||
pss->login_expires = 0;
|
||||
pss->logging_out = 1;
|
||||
goto completion_flow;
|
||||
}
|
||||
|
||||
/* we have the username and password... check if admin */
|
||||
if (lwsgw_check_admin(vhd, lws_spa_get_string(pss->spa, FGS_USERNAME),
|
||||
lws_spa_get_string(pss->spa, FGS_PASSWORD))) {
|
||||
if (lws_spa_get_string(pss->spa, FGS_ADMIN))
|
||||
cp = lws_spa_get_string(pss->spa, FGS_ADMIN);
|
||||
else
|
||||
if (lws_spa_get_string(pss->spa, FGS_GOOD))
|
||||
cp = lws_spa_get_string(pss->spa, FGS_GOOD);
|
||||
else {
|
||||
lwsl_info("No admin or good target url in form\n");
|
||||
return -1;
|
||||
}
|
||||
lwsl_debug("admin\n");
|
||||
goto pass;
|
||||
}
|
||||
|
||||
/* check users in database */
|
||||
|
||||
if (!lwsgs_check_credentials(vhd,
|
||||
lws_spa_get_string(pss->spa, FGS_USERNAME),
|
||||
lws_spa_get_string(pss->spa, FGS_PASSWORD))) {
|
||||
lwsl_notice("pw hash check met\n");
|
||||
cp = lws_spa_get_string(pss->spa, FGS_GOOD);
|
||||
goto pass;
|
||||
} else
|
||||
lwsl_notice("user/password no good %s %s\n",
|
||||
lws_spa_get_string(pss->spa, FGS_USERNAME),
|
||||
lws_spa_get_string(pss->spa, FGS_PASSWORD));
|
||||
|
||||
if (!lws_spa_get_string(pss->spa, FGS_BAD)) {
|
||||
lwsl_info("No admin or good target url in form\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
lws_snprintf(pss->onward, sizeof(pss->onward),
|
||||
"%s%s", vhd->urlroot,
|
||||
lws_spa_get_string(pss->spa, FGS_BAD));
|
||||
|
||||
lwsl_notice("failed: %s\n", pss->onward);
|
||||
|
||||
goto completion_flow;
|
||||
}
|
||||
|
||||
if (!strcmp(cp1 + n - 12, "lwsgs-logout")) {
|
||||
|
||||
lwsl_notice("/logout\n");
|
||||
|
||||
if (lwsgs_get_sid_from_wsi(wsi, &pss->login_session)) {
|
||||
lwsl_notice("not logged in...\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* We keep the same session, but mark it as not
|
||||
* being associated to any authenticated user
|
||||
*/
|
||||
|
||||
lwsgw_update_session(vhd, &pss->login_session, "");
|
||||
|
||||
if (!lws_spa_get_string(pss->spa, FGS_GOOD)) {
|
||||
lwsl_info("No admin or good target url in form\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
lws_snprintf(pss->onward, sizeof(pss->onward),
|
||||
"%s%s", vhd->urlroot,
|
||||
lws_spa_get_string(pss->spa, FGS_GOOD));
|
||||
|
||||
pss->login_expires = 0;
|
||||
pss->logging_out = 1;
|
||||
|
||||
goto completion_flow;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
pass:
|
||||
lws_snprintf(pss->onward, sizeof(pss->onward),
|
||||
"%s%s", vhd->urlroot, cp);
|
||||
|
||||
if (lwsgs_get_sid_from_wsi(wsi, &sid))
|
||||
sid.id[0] = '\0';
|
||||
|
||||
pss->login_expires = lws_now_secs() +
|
||||
vhd->timeout_absolute_secs;
|
||||
|
||||
if (!sid.id[0]) {
|
||||
/* we need to create a new, authorized session */
|
||||
|
||||
if (lwsgs_new_session_id(vhd, &pss->login_session,
|
||||
lws_spa_get_string(pss->spa, FGS_USERNAME),
|
||||
pss->login_expires))
|
||||
goto try_to_reuse;
|
||||
|
||||
lwsl_notice("%s: Creating new session: %s\n", __func__,
|
||||
pss->login_session.id);
|
||||
} else {
|
||||
/*
|
||||
* we can just update the existing session to be
|
||||
* authorized
|
||||
*/
|
||||
lwsl_notice("%s: Authorizing existing session %s, name %s\n",
|
||||
__func__, sid.id,
|
||||
lws_spa_get_string(pss->spa, FGS_USERNAME));
|
||||
lwsgw_update_session(vhd, &sid,
|
||||
lws_spa_get_string(pss->spa, FGS_USERNAME));
|
||||
pss->login_session = sid;
|
||||
}
|
||||
|
||||
completion_flow:
|
||||
lwsgw_expire_old_sessions(vhd);
|
||||
goto redirect_with_cookie;
|
||||
|
||||
case LWS_CALLBACK_HTTP_DROP_PROTOCOL:
|
||||
if (pss && pss->spa) {
|
||||
lws_spa_destroy(pss->spa);
|
||||
pss->spa = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_ADD_HEADERS:
|
||||
lwsgw_expire_old_sessions(vhd);
|
||||
|
||||
lwsl_warn("ADD_HEADERS\n");
|
||||
|
||||
args = (struct lws_process_html_args *)in;
|
||||
if (!pss)
|
||||
return 1;
|
||||
if (pss->delete_session.id[0]) {
|
||||
pc = cookie;
|
||||
lwsgw_cookie_from_session(&pss->delete_session, 0, &pc,
|
||||
cookie + sizeof(cookie) - 1);
|
||||
|
||||
lwsl_notice("deleting cookie '%s'\n", cookie);
|
||||
|
||||
if (lws_add_http_header_by_name(wsi,
|
||||
(unsigned char *)"set-cookie:",
|
||||
(unsigned char *)cookie, pc - cookie,
|
||||
(unsigned char **)&args->p,
|
||||
(unsigned char *)args->p + args->max_len))
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!pss->login_session.id[0])
|
||||
lwsgs_get_sid_from_wsi(wsi, &pss->login_session);
|
||||
|
||||
if (!pss->login_session.id[0] && !pss->logging_out) {
|
||||
|
||||
pss->login_expires = lws_now_secs() +
|
||||
vhd->timeout_anon_absolute_secs;
|
||||
if (lwsgs_new_session_id(vhd, &pss->login_session, "",
|
||||
pss->login_expires))
|
||||
goto try_to_reuse;
|
||||
pc = cookie;
|
||||
lwsgw_cookie_from_session(&pss->login_session,
|
||||
pss->login_expires, &pc,
|
||||
cookie + sizeof(cookie) - 1);
|
||||
|
||||
lwsl_info("LWS_CALLBACK_ADD_HEADERS: setting cookie '%s'\n", cookie);
|
||||
if (lws_add_http_header_by_name(wsi,
|
||||
(unsigned char *)"set-cookie:",
|
||||
(unsigned char *)cookie, pc - cookie,
|
||||
(unsigned char **)&args->p,
|
||||
(unsigned char *)args->p + args->max_len))
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
redirect_with_cookie:
|
||||
p = buffer + LWS_PRE;
|
||||
start = p;
|
||||
end = p + sizeof(buffer) - LWS_PRE;
|
||||
|
||||
lwsl_warn("%s: redirect_with_cookie\n", __func__);
|
||||
|
||||
if (lws_add_http_header_status(wsi, HTTP_STATUS_SEE_OTHER, &p, end))
|
||||
return 1;
|
||||
|
||||
{
|
||||
char loc[1024], uria[128];
|
||||
|
||||
uria[0] = '\0';
|
||||
lws_hdr_copy_fragment(wsi, uria, sizeof(uria),
|
||||
WSI_TOKEN_HTTP_URI_ARGS, 0);
|
||||
n = lws_snprintf(loc, sizeof(loc), "%s?%s",
|
||||
pss->onward, uria);
|
||||
lwsl_notice("%s: redirect to '%s'\n", __func__, loc);
|
||||
if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_LOCATION,
|
||||
(unsigned char *)loc, n, &p, end))
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
|
||||
(unsigned char *)"text/html", 9, &p, end))
|
||||
return 1;
|
||||
if (lws_add_http_header_content_length(wsi, 0, &p, end))
|
||||
return 1;
|
||||
|
||||
if (pss->delete_session.id[0]) {
|
||||
lwsgw_cookie_from_session(&pss->delete_session, 0, &pc,
|
||||
cookie + sizeof(cookie) - 1);
|
||||
|
||||
lwsl_notice("deleting cookie '%s'\n", cookie);
|
||||
|
||||
if (lws_add_http_header_by_name(wsi,
|
||||
(unsigned char *)"set-cookie:",
|
||||
(unsigned char *)cookie, pc - cookie,
|
||||
&p, end)) {
|
||||
lwsl_err("fail0\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pss->login_session.id[0]) {
|
||||
pss->login_expires = lws_now_secs() +
|
||||
vhd->timeout_anon_absolute_secs;
|
||||
if (lwsgs_new_session_id(vhd, &pss->login_session, "",
|
||||
pss->login_expires)) {
|
||||
lwsl_err("fail1\n");
|
||||
return 1;
|
||||
}
|
||||
} else
|
||||
pss->login_expires = lws_now_secs() +
|
||||
vhd->timeout_absolute_secs;
|
||||
|
||||
if (pss->login_session.id[0] || pss->logging_out) {
|
||||
/*
|
||||
* we succeeded to login, we must issue a login
|
||||
* cookie with the prepared data
|
||||
*/
|
||||
pc = cookie;
|
||||
|
||||
lwsgw_cookie_from_session(&pss->login_session,
|
||||
pss->login_expires, &pc,
|
||||
cookie + sizeof(cookie) - 1);
|
||||
|
||||
lwsl_err("%s: setting cookie '%s'\n", __func__, cookie);
|
||||
|
||||
pss->logging_out = 0;
|
||||
|
||||
if (lws_add_http_header_by_name(wsi,
|
||||
(unsigned char *)"set-cookie:",
|
||||
(unsigned char *)cookie, pc - cookie,
|
||||
&p, end)) {
|
||||
lwsl_err("fail2\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (lws_finalize_http_header(wsi, &p, end))
|
||||
return 1;
|
||||
|
||||
// lwsl_hexdump_notice(start, p - start);
|
||||
|
||||
n = lws_write(wsi, start, p - start, LWS_WRITE_H2_STREAM_END |
|
||||
LWS_WRITE_HTTP_HEADERS);
|
||||
if (n < 0)
|
||||
return 1;
|
||||
|
||||
/* fallthru */
|
||||
|
||||
try_to_reuse:
|
||||
if (lws_http_transaction_completed(wsi))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[] = {
|
||||
{
|
||||
"protocol-generic-sessions",
|
||||
callback_generic_sessions,
|
||||
sizeof(struct per_session_data__gs),
|
||||
1024,
|
||||
},
|
||||
};
|
||||
|
||||
LWS_VISIBLE int
|
||||
init_protocol_generic_sessions(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_generic_sessions(struct lws_context *context)
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -1,438 +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.
|
||||
*/
|
||||
|
||||
|
||||
#define LWS_DLL
|
||||
#define LWS_INTERNAL
|
||||
#include <libwebsockets.h>
|
||||
|
||||
#include <sqlite3.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct per_vhost_data__gs_mb {
|
||||
struct lws_vhost *vh;
|
||||
const struct lws_protocols *gsp;
|
||||
sqlite3 *pdb;
|
||||
char message_db[256];
|
||||
unsigned long last_idx;
|
||||
};
|
||||
|
||||
struct per_session_data__gs_mb {
|
||||
void *pss_gs; /* for use by generic-sessions */
|
||||
struct lws_session_info sinfo;
|
||||
struct lws_spa *spa;
|
||||
unsigned long last_idx;
|
||||
unsigned int our_form:1;
|
||||
char second_http_part;
|
||||
};
|
||||
|
||||
static const char * const param_names[] = {
|
||||
"send",
|
||||
"msg",
|
||||
};
|
||||
enum {
|
||||
MBSPA_SUBMIT,
|
||||
MBSPA_MSG,
|
||||
};
|
||||
|
||||
#define MAX_MSG_LEN 512
|
||||
|
||||
struct message {
|
||||
unsigned long idx;
|
||||
unsigned long time;
|
||||
char username[32];
|
||||
char email[100];
|
||||
char ip[72];
|
||||
char content[MAX_MSG_LEN];
|
||||
};
|
||||
|
||||
static int
|
||||
lookup_cb(void *priv, int cols, char **col_val, char **col_name)
|
||||
{
|
||||
struct message *m = (struct message *)priv;
|
||||
int n;
|
||||
|
||||
for (n = 0; n < cols; n++) {
|
||||
|
||||
if (!strcmp(col_name[n], "idx") ||
|
||||
!strcmp(col_name[n], "MAX(idx)")) {
|
||||
if (!col_val[n])
|
||||
m->idx = 0;
|
||||
else
|
||||
m->idx = atol(col_val[n]);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(col_name[n], "time")) {
|
||||
m->time = atol(col_val[n]);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(col_name[n], "username")) {
|
||||
lws_strncpy(m->username, col_val[n], sizeof(m->username));
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(col_name[n], "email")) {
|
||||
lws_strncpy(m->email, col_val[n], sizeof(m->email));
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(col_name[n], "ip")) {
|
||||
lws_strncpy(m->ip, col_val[n], sizeof(m->ip));
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(col_name[n], "content")) {
|
||||
lws_strncpy(m->content, col_val[n], sizeof(m->content));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
get_last_idx(struct per_vhost_data__gs_mb *vhd)
|
||||
{
|
||||
struct message m;
|
||||
|
||||
if (sqlite3_exec(vhd->pdb, "SELECT MAX(idx) FROM msg;",
|
||||
lookup_cb, &m, NULL) != SQLITE_OK) {
|
||||
lwsl_err("Unable to lookup token: %s\n",
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m.idx;
|
||||
}
|
||||
|
||||
static int
|
||||
post_message(struct lws *wsi, struct per_vhost_data__gs_mb *vhd,
|
||||
struct per_session_data__gs_mb *pss)
|
||||
{
|
||||
struct lws_session_info sinfo;
|
||||
char s[MAX_MSG_LEN + 512];
|
||||
char esc[MAX_MSG_LEN + 256];
|
||||
|
||||
vhd->gsp->callback(wsi, LWS_CALLBACK_SESSION_INFO,
|
||||
pss->pss_gs, &sinfo, 0);
|
||||
|
||||
lws_snprintf((char *)s, sizeof(s) - 1,
|
||||
"insert into msg(time, username, email, ip, content)"
|
||||
" values (%lu, '%s', '%s', '%s', '%s');",
|
||||
(unsigned long)lws_now_secs(), sinfo.username, sinfo.email, sinfo.ip,
|
||||
lws_sql_purify(esc, lws_spa_get_string(pss->spa, MBSPA_MSG),
|
||||
sizeof(esc) - 1));
|
||||
if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) {
|
||||
lwsl_err("Unable to insert msg: %s\n", sqlite3_errmsg(vhd->pdb));
|
||||
return 1;
|
||||
}
|
||||
vhd->last_idx = get_last_idx(vhd);
|
||||
|
||||
/* let everybody connected by this protocol on this vhost know */
|
||||
lws_callback_on_writable_all_protocol_vhost(lws_get_vhost(wsi),
|
||||
lws_get_protocol(wsi));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
callback_messageboard(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
struct per_session_data__gs_mb *pss = (struct per_session_data__gs_mb *)user;
|
||||
const struct lws_protocol_vhost_options *pvo;
|
||||
struct per_vhost_data__gs_mb *vhd = (struct per_vhost_data__gs_mb *)
|
||||
lws_protocol_vh_priv_get(lws_get_vhost(wsi), lws_get_protocol(wsi));
|
||||
unsigned char *p, *start, *end, buffer[LWS_PRE + 4096];
|
||||
char s[512];
|
||||
int n;
|
||||
|
||||
switch (reason) {
|
||||
case LWS_CALLBACK_PROTOCOL_INIT: /* per vhost */
|
||||
|
||||
vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
|
||||
lws_get_protocol(wsi), sizeof(struct per_vhost_data__gs_mb));
|
||||
if (!vhd)
|
||||
return 1;
|
||||
vhd->vh = lws_get_vhost(wsi);
|
||||
vhd->gsp = lws_vhost_name_to_protocol(vhd->vh,
|
||||
"protocol-generic-sessions");
|
||||
if (!vhd->gsp) {
|
||||
lwsl_err("messageboard: requires generic-sessions\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pvo = (const struct lws_protocol_vhost_options *)in;
|
||||
while (pvo) {
|
||||
if (!strcmp(pvo->name, "message-db"))
|
||||
strncpy(vhd->message_db, pvo->value,
|
||||
sizeof(vhd->message_db) - 1);
|
||||
pvo = pvo->next;
|
||||
}
|
||||
if (!vhd->message_db[0]) {
|
||||
lwsl_err("messageboard: \"message-db\" pvo missing\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (lws_struct_sq3_open(lws_get_context(wsi),
|
||||
vhd->message_db, 1, &vhd->pdb)) {
|
||||
lwsl_err("Unable to open message db %s: %s\n",
|
||||
vhd->message_db, sqlite3_errmsg(vhd->pdb));
|
||||
|
||||
return 1;
|
||||
}
|
||||
if (sqlite3_exec(vhd->pdb, "create table if not exists msg ("
|
||||
" idx integer primary key, time integer,"
|
||||
" username varchar(32), email varchar(100),"
|
||||
" ip varchar(80), content blob);",
|
||||
NULL, NULL, NULL) != SQLITE_OK) {
|
||||
lwsl_err("Unable to create msg table: %s\n",
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
vhd->last_idx = get_last_idx(vhd);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_PROTOCOL_DESTROY:
|
||||
if (vhd && vhd->pdb)
|
||||
sqlite3_close(vhd->pdb);
|
||||
goto passthru;
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED:
|
||||
vhd->gsp->callback(wsi, LWS_CALLBACK_SESSION_INFO,
|
||||
pss->pss_gs, &pss->sinfo, 0);
|
||||
if (!pss->sinfo.username[0]) {
|
||||
lwsl_notice("messageboard ws attempt with no session\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
lws_callback_on_writable(wsi);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLOSED:
|
||||
lwsl_debug("%s: LWS_CALLBACK_CLOSED\n", __func__);
|
||||
if (pss && pss->pss_gs) {
|
||||
free(pss->pss_gs);
|
||||
pss->pss_gs = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||
{
|
||||
struct message m;
|
||||
char j[MAX_MSG_LEN + 512], e[MAX_MSG_LEN + 512],
|
||||
*p = j + LWS_PRE, *start = p,
|
||||
*end = j + sizeof(j) - LWS_PRE;
|
||||
|
||||
if (pss->last_idx == vhd->last_idx)
|
||||
break;
|
||||
|
||||
/* restrict to last 10 */
|
||||
if (!pss->last_idx)
|
||||
if (vhd->last_idx >= 10)
|
||||
pss->last_idx = vhd->last_idx - 10;
|
||||
|
||||
sprintf(s, "select idx, time, username, email, ip, content "
|
||||
"from msg where idx > %lu order by idx limit 1;",
|
||||
pss->last_idx);
|
||||
if (sqlite3_exec(vhd->pdb, s, lookup_cb, &m, NULL) != SQLITE_OK) {
|
||||
lwsl_err("Unable to lookup msg: %s\n",
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* format in JSON */
|
||||
p += lws_snprintf(p, end - p,
|
||||
"{\"idx\":\"%lu\",\"time\":\"%lu\",",
|
||||
m.idx, m.time);
|
||||
p += lws_snprintf(p, end - p, " \"username\":\"%s\",",
|
||||
lws_json_purify(e, m.username, sizeof(e), NULL));
|
||||
p += lws_snprintf(p, end - p, " \"email\":\"%s\",",
|
||||
lws_json_purify(e, m.email, sizeof(e), NULL));
|
||||
p += lws_snprintf(p, end - p, " \"ip\":\"%s\",",
|
||||
lws_json_purify(e, m.ip, sizeof(e), NULL));
|
||||
p += lws_snprintf(p, end - p, " \"content\":\"%s\"}",
|
||||
lws_json_purify(e, m.content, sizeof(e), NULL));
|
||||
|
||||
if (lws_write(wsi, (unsigned char *)start, p - start,
|
||||
LWS_WRITE_TEXT) < 0)
|
||||
return -1;
|
||||
|
||||
pss->last_idx = m.idx;
|
||||
if (pss->last_idx == vhd->last_idx)
|
||||
break;
|
||||
|
||||
lws_callback_on_writable(wsi); /* more to do */
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_HTTP:
|
||||
pss->our_form = 0;
|
||||
|
||||
/* ie, it's our messageboard new message form */
|
||||
if (!strcmp((const char *)in, "/msg") ||
|
||||
!strcmp((const char *)in, "msg")) {
|
||||
pss->our_form = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
goto passthru;
|
||||
|
||||
case LWS_CALLBACK_HTTP_BODY:
|
||||
if (!pss->our_form)
|
||||
goto passthru;
|
||||
|
||||
if (len < 2)
|
||||
break;
|
||||
if (!pss->spa) {
|
||||
pss->spa = lws_spa_create(wsi, param_names,
|
||||
LWS_ARRAY_SIZE(param_names),
|
||||
MAX_MSG_LEN + 1024, NULL, NULL);
|
||||
if (!pss->spa)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lws_spa_process(pss->spa, in, len)) {
|
||||
lwsl_notice("spa process blew\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_HTTP_WRITEABLE:
|
||||
if (!pss->second_http_part)
|
||||
goto passthru;
|
||||
|
||||
s[0] = '0';
|
||||
n = lws_write(wsi, (unsigned char *)s, 1, LWS_WRITE_HTTP|
|
||||
LWS_WRITE_H2_STREAM_END);
|
||||
if (n != 1)
|
||||
return -1;
|
||||
|
||||
goto try_to_reuse;
|
||||
|
||||
case LWS_CALLBACK_HTTP_BODY_COMPLETION:
|
||||
if (!pss->our_form)
|
||||
goto passthru;
|
||||
|
||||
if (post_message(wsi, vhd, pss))
|
||||
return -1;
|
||||
|
||||
p = buffer + LWS_PRE;
|
||||
start = p;
|
||||
end = p + sizeof(buffer) - LWS_PRE;
|
||||
|
||||
if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end))
|
||||
return -1;
|
||||
if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
|
||||
(unsigned char *)"text/plain", 10, &p, end))
|
||||
return -1;
|
||||
if (lws_add_http_header_content_length(wsi, 1, &p, end))
|
||||
return -1;
|
||||
if (lws_finalize_http_header(wsi, &p, end))
|
||||
return -1;
|
||||
|
||||
n = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS);
|
||||
if (n != (p - start)) {
|
||||
lwsl_err("_write returned %d from %ld\n", n, (long)(p - start));
|
||||
return -1;
|
||||
}
|
||||
pss->second_http_part = 1;
|
||||
lws_callback_on_writable(wsi);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_HTTP_BIND_PROTOCOL:
|
||||
if (!pss || !vhd || 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->spa) {
|
||||
lws_spa_destroy(pss->spa);
|
||||
pss->spa = NULL;
|
||||
}
|
||||
if (pss && pss->pss_gs) {
|
||||
free(pss->pss_gs);
|
||||
pss->pss_gs = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
passthru:
|
||||
if (!pss || !vhd)
|
||||
break;
|
||||
|
||||
return vhd->gsp->callback(wsi, reason, pss->pss_gs, in, len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
try_to_reuse:
|
||||
if (lws_http_transaction_completed(wsi))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[] = {
|
||||
{
|
||||
"protocol-lws-messageboard",
|
||||
callback_messageboard,
|
||||
sizeof(struct per_session_data__gs_mb),
|
||||
4096,
|
||||
},
|
||||
};
|
||||
|
||||
LWS_VISIBLE int
|
||||
init_protocol_lws_messageboard(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_messageboard(struct lws_context *context)
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -1,465 +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 "private-lwsgs.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void
|
||||
sha256_to_lwsgw_hash(unsigned char *hash, lwsgw_hash *shash)
|
||||
{
|
||||
static const char *hex = "0123456789abcdef";
|
||||
char *p = shash->id;
|
||||
int n;
|
||||
|
||||
for (n = 0; n < (int)lws_genhash_size(LWS_GENHASH_TYPE_SHA256); n++) {
|
||||
*p++ = hex[(hash[n] >> 4) & 0xf];
|
||||
*p++ = hex[hash[n] & 15];
|
||||
}
|
||||
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
int
|
||||
lwsgw_check_admin(struct per_vhost_data__gs *vhd,
|
||||
const char *username, const char *password)
|
||||
{
|
||||
lwsgw_hash_bin hash_bin;
|
||||
lwsgw_hash pw_hash;
|
||||
|
||||
if (strcmp(vhd->admin_user, username))
|
||||
return 0;
|
||||
|
||||
lws_SHA1((unsigned char *)password, strlen(password), hash_bin.bin);
|
||||
sha256_to_lwsgw_hash(hash_bin.bin, &pw_hash);
|
||||
|
||||
return !strcmp(vhd->admin_password_sha256.id, pw_hash.id);
|
||||
}
|
||||
|
||||
/*
|
||||
* secure cookie: it can only be passed over https where it cannot be
|
||||
* snooped in transit
|
||||
* HttpOnly: it can only be accessed via http[s] transport, it cannot be
|
||||
* gotten at by JS
|
||||
*/
|
||||
void
|
||||
lwsgw_cookie_from_session(lwsgw_hash *sid, time_t expires, char **p, char *end)
|
||||
{
|
||||
struct tm *tm = gmtime(&expires);
|
||||
time_t n = lws_now_secs();
|
||||
|
||||
*p += lws_snprintf(*p, end - *p, "id=%s;Expires=", sid->id);
|
||||
#ifdef WIN32
|
||||
*p += strftime(*p, end - *p, "%Y %H:%M %Z", tm);
|
||||
#else
|
||||
*p += strftime(*p, end - *p, "%F %H:%M %Z", tm);
|
||||
#endif
|
||||
*p += lws_snprintf(*p, end - *p, ";path=/");
|
||||
*p += lws_snprintf(*p, end - *p, ";Max-Age=%lu", (unsigned long)(expires - n));
|
||||
// *p += lws_snprintf(*p, end - *p, ";secure");
|
||||
*p += lws_snprintf(*p, end - *p, ";HttpOnly");
|
||||
}
|
||||
|
||||
int
|
||||
lwsgw_expire_old_sessions(struct per_vhost_data__gs *vhd)
|
||||
{
|
||||
time_t n = lws_now_secs();
|
||||
char s[200];
|
||||
|
||||
if (n - vhd->last_session_expire < 5)
|
||||
return 0;
|
||||
|
||||
vhd->last_session_expire = n;
|
||||
|
||||
lws_snprintf(s, sizeof(s) - 1,
|
||||
"delete from sessions where "
|
||||
"expire <= %lu;", (unsigned long)n);
|
||||
|
||||
if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) {
|
||||
lwsl_err("Unable to expire sessions: %s\n",
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
lwsgw_update_session(struct per_vhost_data__gs *vhd,
|
||||
lwsgw_hash *hash, const char *user)
|
||||
{
|
||||
time_t n = lws_now_secs();
|
||||
char s[200], esc[96], esc1[96];
|
||||
|
||||
if (user[0])
|
||||
n += vhd->timeout_absolute_secs;
|
||||
else
|
||||
n += vhd->timeout_anon_absolute_secs;
|
||||
|
||||
lws_snprintf(s, sizeof(s) - 1,
|
||||
"update sessions set expire=%lu,username='%s' where name='%s';",
|
||||
(unsigned long)n,
|
||||
lws_sql_purify(esc, user, sizeof(esc)),
|
||||
lws_sql_purify(esc1, hash->id, sizeof(esc1)));
|
||||
|
||||
if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) {
|
||||
lwsl_err("Unable to update session: %s\n",
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
return 1;
|
||||
}
|
||||
|
||||
puts(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
lwsgw_session_from_cookie(const char *cookie, lwsgw_hash *sid)
|
||||
{
|
||||
const char *p = cookie;
|
||||
int n;
|
||||
|
||||
while (*p) {
|
||||
if (p[0] == 'i' && p[1] == 'd' && p[2] == '=') {
|
||||
p += 3;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
if (!*p) {
|
||||
lwsl_info("no id= in cookie\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (n = 0; n < (int)sizeof(sid->id) - 1 && *p; n++) {
|
||||
/* our SID we issue only has these chars */
|
||||
if ((*p >= '0' && *p <= '9') ||
|
||||
(*p >= 'a' && *p <= 'f'))
|
||||
sid->id[n] = *p++;
|
||||
else {
|
||||
lwsl_info("bad chars in cookie id %c\n", *p);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (n < (int)sizeof(sid->id) - 1) {
|
||||
lwsl_info("cookie id too short\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
sid->id[sizeof(sid->id) - 1] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
lwsgs_get_sid_from_wsi(struct lws *wsi, lwsgw_hash *sid)
|
||||
{
|
||||
char cookie[1024];
|
||||
|
||||
/* fail it on no cookie */
|
||||
if (!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COOKIE)) {
|
||||
lwsl_info("%s: no cookie\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
if (lws_hdr_copy(wsi, cookie, sizeof cookie, WSI_TOKEN_HTTP_COOKIE) < 0) {
|
||||
lwsl_info("cookie copy failed\n");
|
||||
return 1;
|
||||
}
|
||||
/* extract the sid from the cookie */
|
||||
if (lwsgw_session_from_cookie(cookie, sid)) {
|
||||
lwsl_info("%s: session from cookie failed\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct lla {
|
||||
char *username;
|
||||
int len;
|
||||
int results;
|
||||
};
|
||||
|
||||
static int
|
||||
lwsgs_lookup_callback(void *priv, int cols, char **col_val, char **col_name)
|
||||
{
|
||||
struct lla *lla = (struct lla *)priv;
|
||||
|
||||
//lwsl_err("%s: %d\n", __func__, cols);
|
||||
|
||||
if (cols)
|
||||
lla->results = 0;
|
||||
if (col_val && col_val[0]) {
|
||||
lws_strncpy(lla->username, col_val[0], lla->len + 1);
|
||||
lwsl_info("%s: %s\n", __func__, lla->username);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
lwsgs_lookup_session(struct per_vhost_data__gs *vhd,
|
||||
const lwsgw_hash *sid, char *username, int len)
|
||||
{
|
||||
struct lla lla = { username, len, 1 };
|
||||
char s[150], esc[96];
|
||||
|
||||
lwsgw_expire_old_sessions(vhd);
|
||||
|
||||
lws_snprintf(s, sizeof(s) - 1,
|
||||
"select username from sessions where name = '%s';",
|
||||
lws_sql_purify(esc, sid->id, sizeof(esc) - 1));
|
||||
|
||||
if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback, &lla, NULL) != SQLITE_OK) {
|
||||
lwsl_err("Unable to create user table: %s\n",
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 0 if found */
|
||||
return lla.results;
|
||||
}
|
||||
|
||||
int
|
||||
lwsgs_lookup_callback_user(void *priv, int cols, char **col_val, char **col_name)
|
||||
{
|
||||
struct lwsgs_user *u = (struct lwsgs_user *)priv;
|
||||
int n;
|
||||
|
||||
for (n = 0; n < cols; n++) {
|
||||
if (!strcmp(col_name[n], "username")) {
|
||||
lws_strncpy(u->username, col_val[n], sizeof(u->username));
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(col_name[n], "ip")) {
|
||||
lws_strncpy(u->ip, col_val[n], sizeof(u->ip));
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(col_name[n], "creation_time")) {
|
||||
u->created = atol(col_val[n]);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(col_name[n], "last_forgot_validated")) {
|
||||
if (col_val[n])
|
||||
u->last_forgot_validated = atol(col_val[n]);
|
||||
else
|
||||
u->last_forgot_validated = 0;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(col_name[n], "email")) {
|
||||
lws_strncpy(u->email, col_val[n], sizeof(u->email));
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(col_name[n], "verified")) {
|
||||
u->verified = atoi(col_val[n]);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(col_name[n], "pwhash")) {
|
||||
lws_strncpy(u->pwhash.id, col_val[n], sizeof(u->pwhash.id));
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(col_name[n], "pwsalt")) {
|
||||
lws_strncpy(u->pwsalt.id, col_val[n], sizeof(u->pwsalt.id));
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(col_name[n], "token")) {
|
||||
lws_strncpy(u->token.id, col_val[n], sizeof(u->token.id));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
lwsgs_lookup_user(struct per_vhost_data__gs *vhd,
|
||||
const char *username, struct lwsgs_user *u)
|
||||
{
|
||||
char s[150], esc[96];
|
||||
|
||||
u->username[0] = '\0';
|
||||
lws_snprintf(s, sizeof(s) - 1,
|
||||
"select username,creation_time,ip,email,verified,pwhash,pwsalt,last_forgot_validated "
|
||||
"from users where username = '%s';",
|
||||
lws_sql_purify(esc, username, sizeof(esc) - 1));
|
||||
|
||||
if (sqlite3_exec(vhd->pdb, s, lwsgs_lookup_callback_user, u, NULL) !=
|
||||
SQLITE_OK) {
|
||||
lwsl_err("Unable to lookup user: %s\n",
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return !u->username[0];
|
||||
}
|
||||
|
||||
int
|
||||
lwsgs_new_session_id(struct per_vhost_data__gs *vhd,
|
||||
lwsgw_hash *sid, const char *username, int exp)
|
||||
{
|
||||
unsigned char sid_rand[32];
|
||||
const char *u;
|
||||
char s[300], esc[96], esc1[96];
|
||||
|
||||
if (username)
|
||||
u = username;
|
||||
else
|
||||
u = "";
|
||||
|
||||
if (!sid) {
|
||||
lwsl_err("%s: NULL sid\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(sid, 0, sizeof(*sid));
|
||||
|
||||
if (lws_get_random(vhd->context, sid_rand, sizeof(sid_rand)) !=
|
||||
sizeof(sid_rand))
|
||||
return 1;
|
||||
|
||||
sha256_to_lwsgw_hash(sid_rand, sid);
|
||||
|
||||
lws_snprintf(s, sizeof(s) - 1,
|
||||
"insert into sessions(name, username, expire) "
|
||||
"values ('%s', '%s', %u);",
|
||||
lws_sql_purify(esc, sid->id, sizeof(esc) - 1),
|
||||
lws_sql_purify(esc1, u, sizeof(esc1) - 1), exp);
|
||||
|
||||
if (sqlite3_exec(vhd->pdb, s, NULL, NULL, NULL) != SQLITE_OK) {
|
||||
lwsl_err("Unable to insert session: %s\n",
|
||||
sqlite3_errmsg(vhd->pdb));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
lwsl_notice("%s: created session %s\n", __func__, sid->id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
lwsgs_get_auth_level(struct per_vhost_data__gs *vhd, const char *username)
|
||||
{
|
||||
struct lwsgs_user u;
|
||||
int n = 0;
|
||||
|
||||
/* we are logged in as some kind of user */
|
||||
if (username[0]) {
|
||||
/* we are logged in as admin */
|
||||
if (!strcmp(username, vhd->admin_user))
|
||||
/* automatically verified */
|
||||
n |= LWSGS_AUTH_VERIFIED | LWSGS_AUTH_ADMIN;
|
||||
}
|
||||
|
||||
if (!lwsgs_lookup_user(vhd, username, &u)) {
|
||||
if ((u.verified & 0xff) == LWSGS_VERIFIED_ACCEPTED)
|
||||
n |= LWSGS_AUTH_LOGGED_IN | LWSGS_AUTH_VERIFIED;
|
||||
|
||||
if (u.last_forgot_validated > (time_t)lws_now_secs() - 300)
|
||||
n |= LWSGS_AUTH_FORGOT_FLOW;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
lwsgs_check_credentials(struct per_vhost_data__gs *vhd,
|
||||
const char *username, const char *password)
|
||||
{
|
||||
struct lws_genhash_ctx hash_ctx;
|
||||
lwsgw_hash_bin hash_bin;
|
||||
struct lwsgs_user u;
|
||||
lwsgw_hash hash;
|
||||
|
||||
if (lwsgs_lookup_user(vhd, username, &u))
|
||||
return -1;
|
||||
|
||||
lwsl_info("user %s found, salt '%s'\n", username, u.pwsalt.id);
|
||||
|
||||
/* sha256sum of password + salt */
|
||||
|
||||
if (lws_genhash_init(&hash_ctx, LWS_GENHASH_TYPE_SHA256) ||
|
||||
lws_genhash_update(&hash_ctx, password, strlen(password)) ||
|
||||
lws_genhash_update(&hash_ctx, "-", 1) ||
|
||||
lws_genhash_update(&hash_ctx, vhd->confounder, strlen(vhd->confounder)) ||
|
||||
lws_genhash_update(&hash_ctx, "-", 1) ||
|
||||
lws_genhash_update(&hash_ctx, u.pwsalt.id, strlen(u.pwsalt.id)) ||
|
||||
lws_genhash_destroy(&hash_ctx, hash_bin.bin)) {
|
||||
lws_genhash_destroy(&hash_ctx, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sha256_to_lwsgw_hash(&hash_bin.bin[0], &hash);
|
||||
|
||||
return !!strcmp(hash.id, u.pwhash.id);
|
||||
}
|
||||
|
||||
/* sets u->pwsalt and u->pwhash */
|
||||
|
||||
int
|
||||
lwsgs_hash_password(struct per_vhost_data__gs *vhd,
|
||||
const char *password, struct lwsgs_user *u)
|
||||
{
|
||||
unsigned char sid_rand[32];
|
||||
struct lws_genhash_ctx hash_ctx;
|
||||
lwsgw_hash_bin hash_bin;
|
||||
|
||||
/* create a random salt as big as the hash */
|
||||
|
||||
if (lws_get_random(vhd->context, sid_rand,
|
||||
sizeof(sid_rand)) !=
|
||||
sizeof(sid_rand)) {
|
||||
lwsl_err("Problem getting random for salt\n");
|
||||
return 1;
|
||||
}
|
||||
sha256_to_lwsgw_hash(sid_rand, &u->pwsalt);
|
||||
/*
|
||||
if (lws_get_random(vhd->context, sid_rand,
|
||||
sizeof(sid_rand)) !=
|
||||
sizeof(sid_rand)) {
|
||||
lwsl_err("Problem getting random for token\n");
|
||||
return 1;
|
||||
}
|
||||
sha256_to_lwsgw_hash(sid_rand, &hash);
|
||||
*/
|
||||
/* sha256sum of password + salt */
|
||||
|
||||
if (lws_genhash_init(&hash_ctx, LWS_GENHASH_TYPE_SHA256) ||
|
||||
lws_genhash_update(&hash_ctx, password, strlen(password)) ||
|
||||
lws_genhash_update(&hash_ctx, "-", 1) ||
|
||||
lws_genhash_update(&hash_ctx, vhd->confounder, strlen(vhd->confounder)) ||
|
||||
lws_genhash_update(&hash_ctx, "-", 1) ||
|
||||
lws_genhash_update(&hash_ctx, u->pwsalt.id, strlen(u->pwsalt.id)) ||
|
||||
lws_genhash_destroy(&hash_ctx, hash_bin.bin)) {
|
||||
lws_genhash_destroy(&hash_ctx, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sha256_to_lwsgw_hash(&hash_bin.bin[0], &u->pwhash);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
<script src="/lws-common.js"></script>
|
||||
<script src="lwsgt.js"></script>
|
||||
<style>
|
||||
.body { font-size: 12 }
|
||||
.gstitle { font-size: 24; text-align:center }
|
||||
.group1 { vertical-align:middle;text-align:center;background:#f0f0e0;
|
||||
padding:12px; -webkit-border-radius:10px;
|
||||
-moz-border-radius:10px;border-radius:10px; }
|
||||
.group2 { vertical-align:middle; font-size: 18;text-align:center;
|
||||
margin:auto; align:center;
|
||||
background-color: rgba(255, 255, 255, 0.8); padding:12px;
|
||||
display:inline-block; -webkit-border-radius:10px;
|
||||
-moz-border-radius:10px; border-radius:10px; }
|
||||
|
||||
.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>
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<tr><td class="gstitle">
|
||||
LWS Generic Table demo
|
||||
</td></tr>
|
||||
<tr><td class="group2">
|
||||
This is a demo of lws generic table, using a protocol plugin
|
||||
"protocol-lws-table-dirlisting". It shows a directory listing,
|
||||
but unlike an oldstyle directory listing done on the
|
||||
server side with a script, this is static html that connects
|
||||
back to the server with a websocket, and gets live JSON from
|
||||
that.
|
||||
<p>
|
||||
Actually the static html is extremely simple, since it uses
|
||||
lwsgt, LWS Generic Table, JS include on the client-side that
|
||||
handles all the table generation from a template sent in JSON
|
||||
over the ws link. It means there is no custom JS required
|
||||
clientside either. It's just CSS, this text and a call to
|
||||
initialize lwsgt with the appropriate ws protocol.
|
||||
</td></tr>
|
||||
<tr><td><div id="lwsgt1" class="group1"></div></td></tr>
|
||||
<tr><td class="group2">
|
||||
There's no problem having multiple independent instances per
|
||||
page...
|
||||
</td></tr>
|
||||
<tr><td><div id="lwsgt2" class="group1"></div></td></tr>
|
||||
</table>
|
||||
<div id="debug"></div>
|
||||
|
||||
<script nonce="lwscaro">
|
||||
var v1 = new lwsgt_initial("Dir listing demo",
|
||||
"protocol-lws-table-dirlisting",
|
||||
"lwsgt1", "lwsgt_dir_click", "v1");
|
||||
var v2 = new lwsgt_initial("Dir listing 2",
|
||||
"protocol-lws-table-dirlisting",
|
||||
"lwsgt2", "lwsgt_dir_click", "v2");
|
||||
|
||||
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>
|
||||
</body>
|
||||
</html>
|
|
@ -1,139 +0,0 @@
|
|||
function lwsgt_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);
|
||||
}
|
||||
|
||||
return pcol + u;
|
||||
}
|
||||
|
||||
function lwsgt_app_hdr(j, bc, ws)
|
||||
{
|
||||
var s = "", n, m = 0;
|
||||
|
||||
ws.bcq = 0;
|
||||
|
||||
for (n = 0; n < j.cols.length; n++)
|
||||
if (!j.cols[n].hide)
|
||||
m++;
|
||||
|
||||
s = "<tr><td colspan=\"" + m + "\" class=\"lwsgt_title\">" +
|
||||
ws.lwsgt_title + "</td></tr>";
|
||||
|
||||
if (!!bc) {
|
||||
s += "<tr><td colspan=\"" + m + "\" class=\"lwsgt_breadcrumbs\">";
|
||||
for (n = 0; n < bc.length; n++) {
|
||||
s += " / ";
|
||||
if (!bc[n].url && bc[n].url !== "")
|
||||
s += " " + lws_san(bc[n].name) + " ";
|
||||
else {
|
||||
s += "<a href=# id=\"bc_"+ ws.divname + ws.bcq + "\" h=\"" +
|
||||
ws.lwsgt_cb + "\" p=\""+ws.lwsgt_parent+"\" aa=\"="+
|
||||
lws_san(encodeURI(bc[n].url))+"\" m=\"-1\" n=\"-1\">" +
|
||||
lws_san(bc[n].name) + "</a> ";
|
||||
ws.bcq++;
|
||||
}
|
||||
}
|
||||
s += "</td></tr>";
|
||||
}
|
||||
s += "<tr>";
|
||||
for (n = 0; n < j.cols.length; n++)
|
||||
if (!j.cols[n].hide)
|
||||
s = s + "<td class=\"lwsgt_hdr\">" + lws_san(j.cols[n].name) +
|
||||
"</td>";
|
||||
|
||||
s += "</tr>";
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
function lwsgt_click_callthru()
|
||||
{
|
||||
window[this.getAttribute("h")](this.getAttribute("p"), this.getAttribute("aa"), this.getAttribute("m"), this.getAttribute("n"));
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
function lwsgt_initial(title, pcol, divname, cb, gname)
|
||||
{
|
||||
this.divname = divname;
|
||||
|
||||
lws_gray_out(true,{"zindex":"499"});
|
||||
|
||||
this.lwsgt_ws = new WebSocket(lwsgt_get_appropriate_ws_url(), pcol);
|
||||
this.lwsgt_ws.divname = divname;
|
||||
this.lwsgt_ws.lwsgt_cb = cb;
|
||||
this.lwsgt_ws.lwsgt_parent = gname;
|
||||
this.lwsgt_ws.lwsgt_title = title;
|
||||
try {
|
||||
this.lwsgt_ws.onopen = function() {
|
||||
lws_gray_out(false);
|
||||
// document.getElementById("debug").textContent =
|
||||
// "ws opened " + lwsgt_get_appropriate_ws_url();
|
||||
};
|
||||
this.lwsgt_ws.onmessage = function got_packet(msg) {
|
||||
var s, m, n, j = JSON.parse(msg.data);
|
||||
document.getElementById("debug").textContent = msg.data;
|
||||
if (j.cols) {
|
||||
this.hdr = j;
|
||||
}
|
||||
if (j.breadcrumbs)
|
||||
this.breadcrumbs = j.breadcrumbs;
|
||||
|
||||
if (j.data) {
|
||||
var q = 0;
|
||||
s = "<table class=\"lwsgt_table\">" +
|
||||
lwsgt_app_hdr(this.hdr, this.breadcrumbs, this);
|
||||
for (m = 0; m < j.data.length; m++) {
|
||||
s = s + "<tr class=\"lwsgt_tr\">";
|
||||
for (n = 0; n < this.hdr.cols.length; n++) {
|
||||
if (!this.hdr.cols[n].hide) {
|
||||
if (!this.hdr.cols[n].align)
|
||||
s = s + "<td class=\"lwsgt_td\">";
|
||||
else
|
||||
s = s + "<td class=\"lwsgt_td\" style=\"text-align: right\">";
|
||||
|
||||
if (this.hdr.cols[n].href &&
|
||||
!!j.data[m][this.hdr.cols[n].href]) {
|
||||
s = s + "<a href=# id=\""+ this.divname + q + "\" h=\"" + this.lwsgt_cb + "\" p=\""+this.lwsgt_parent+"\" aa=\""+
|
||||
lws_san(encodeURI(j.data[m][this.hdr.cols[n].href]))+"\" m=\""+m+"\" n=\""+n+"\">" +
|
||||
lws_san(j.data[m][this.hdr.cols[n].name]) +
|
||||
"</a>";
|
||||
q++;
|
||||
}
|
||||
else
|
||||
s = s + lws_san(j.data[m][this.hdr.cols[n].name]);
|
||||
|
||||
s = s + "</td>";
|
||||
}
|
||||
}
|
||||
|
||||
s = s + "</tr>";
|
||||
}
|
||||
s = s + "</table>";
|
||||
document.getElementById(this.divname).innerHTML = s;
|
||||
for (n = 0; n < q; n++)
|
||||
document.getElementById(this.divname + n).onclick =
|
||||
lwsgt_click_callthru;
|
||||
|
||||
for (n = 0; n < this.bcq; n++)
|
||||
document.getElementById("bc_" + this.divname + n).onclick =
|
||||
lwsgt_click_callthru;
|
||||
|
||||
}
|
||||
};
|
||||
this.lwsgt_ws.onclose = function(){
|
||||
lws_gray_out(true,{"zindex":"499"});
|
||||
};
|
||||
} catch(exception) {
|
||||
alert("<p>Error" + exception);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,397 +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.
|
||||
*/
|
||||
|
||||
#define LWS_DLL
|
||||
#define LWS_INTERNAL
|
||||
#include <libwebsockets.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <uv.h>
|
||||
|
||||
struct fobj {
|
||||
struct fobj *next;
|
||||
const char *name, *uri, *icon, *date;
|
||||
time_t m;
|
||||
unsigned long size;
|
||||
};
|
||||
|
||||
struct per_session_data__tbl_dir {
|
||||
struct fobj base;
|
||||
char strings[64 * 1024];
|
||||
char reldir[256];
|
||||
char *p;
|
||||
const char *dir;
|
||||
|
||||
#if UV_VERSION_MAJOR > 0
|
||||
uv_fs_event_t *event_req;
|
||||
#endif
|
||||
struct lws *wsi;
|
||||
};
|
||||
|
||||
#if UV_VERSION_MAJOR > 0
|
||||
static void
|
||||
mon_cb(uv_fs_event_t *handle, const char *filename, int events, int status)
|
||||
{
|
||||
struct per_session_data__tbl_dir *pss = handle->data;
|
||||
|
||||
//lwsl_notice("%s\n", __func__);
|
||||
|
||||
if (pss && pss->wsi)
|
||||
lws_callback_on_writable(pss->wsi);
|
||||
}
|
||||
|
||||
static void lws_uv_close_cb(uv_handle_t *handle)
|
||||
{
|
||||
free(handle);
|
||||
}
|
||||
|
||||
static void
|
||||
lws_protocol_dir_kill_monitor(struct per_session_data__tbl_dir *pss)
|
||||
{
|
||||
if (!pss->event_req)
|
||||
return;
|
||||
pss->wsi = NULL;
|
||||
pss->event_req->data = NULL;
|
||||
uv_fs_event_stop(pss->event_req);
|
||||
uv_close((uv_handle_t *)pss->event_req, lws_uv_close_cb);
|
||||
pss->event_req = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
scan_dir(struct lws *wsi, struct per_session_data__tbl_dir *pss)
|
||||
{
|
||||
/* uuh travis... */
|
||||
#if UV_VERSION_MAJOR > 0
|
||||
uv_loop_t *loop = lws_uv_getloop(lws_get_context(wsi), 0);
|
||||
char *end = &(pss->strings[sizeof(pss->strings) - 1]);
|
||||
struct fobj *prev = &pss->base;
|
||||
char path[512], da[200];
|
||||
const char *icon;
|
||||
uv_dirent_t dent;
|
||||
struct fobj *f;
|
||||
struct stat st;
|
||||
struct tm *tm;
|
||||
int ret = 0, n;
|
||||
uv_fs_t req;
|
||||
|
||||
lws_protocol_dir_kill_monitor(pss);
|
||||
|
||||
lws_snprintf(path, sizeof(path) - 1, "%s/%s", pss->dir, pss->reldir);
|
||||
//lwsl_notice("path = %s\n", path);
|
||||
|
||||
pss->event_req = malloc(sizeof(*pss->event_req));
|
||||
if (!pss->event_req)
|
||||
return 2;
|
||||
|
||||
pss->wsi = wsi;
|
||||
pss->event_req->data = pss;
|
||||
|
||||
uv_fs_event_init(lws_uv_getloop(lws_get_context(wsi), 0),
|
||||
pss->event_req);
|
||||
// The recursive flag watches subdirectories too.
|
||||
n = uv_fs_event_start(pss->event_req, mon_cb, path, UV_FS_EVENT_RECURSIVE);
|
||||
//lwsl_notice("monitoring %s (%d)\n", path, n);
|
||||
|
||||
if (!uv_fs_scandir(loop, &req, path, 0, NULL)) {
|
||||
lwsl_err("Scandir on %s failed\n", path);
|
||||
return 2;
|
||||
}
|
||||
|
||||
pss->p = pss->strings;
|
||||
|
||||
while (uv_fs_scandir_next(&req, &dent) != UV_EOF) {
|
||||
lws_snprintf(path, sizeof(path) - 1, "%s/%s/%s", pss->dir, pss->reldir, dent.name);
|
||||
|
||||
if (stat(path, &st)) {
|
||||
lwsl_info("unable to stat %s\n", path);
|
||||
continue;
|
||||
}
|
||||
f = malloc(sizeof(*f));
|
||||
f->next = NULL;
|
||||
f->name = pss->p;
|
||||
n = lws_snprintf(pss->p, end - pss->p, "%s", dent.name);
|
||||
pss->p += n + 1;
|
||||
f->uri = NULL;
|
||||
if ((S_IFMT & st.st_mode) == S_IFDIR) {
|
||||
n = lws_snprintf(pss->p, end - pss->p, "=%s/%s", pss->reldir, dent.name);
|
||||
f->uri = pss->p;
|
||||
}
|
||||
if (lws_get_mimetype(dent.name, NULL)) {
|
||||
n = lws_snprintf(pss->p, end - pss->p, "./serve/%s/%s", pss->reldir, dent.name);
|
||||
f->uri = pss->p;
|
||||
}
|
||||
if (f->uri)
|
||||
pss->p += n + 1;
|
||||
|
||||
if (end - pss->p < 100) {
|
||||
free(f);
|
||||
break;
|
||||
}
|
||||
|
||||
icon = " ";
|
||||
if ((S_IFMT & st.st_mode) == S_IFDIR)
|
||||
icon = "📂";
|
||||
|
||||
f->icon = pss->p;
|
||||
n = lws_snprintf(pss->p, end - pss->p, "%s", icon);
|
||||
pss->p += n + 1;
|
||||
|
||||
f->date = pss->p;
|
||||
tm = gmtime(&st.st_mtime);
|
||||
strftime(da, sizeof(da), "%Y-%b-%d %H:%M:%S %z", tm);
|
||||
n = lws_snprintf(pss->p, end - pss->p, "%s", da);
|
||||
pss->p += n + 1;
|
||||
|
||||
f->size = st.st_size;
|
||||
f->m = st.st_mtime;
|
||||
prev->next = f;
|
||||
prev = f;
|
||||
}
|
||||
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
free_scan_dir(struct per_session_data__tbl_dir *pss)
|
||||
{
|
||||
struct fobj *f = pss->base.next, *f1;
|
||||
|
||||
while (f) {
|
||||
f1 = f->next;
|
||||
free(f);
|
||||
f = f1;
|
||||
}
|
||||
|
||||
pss->base.next = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
callback_lws_table_dirlisting(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
struct per_session_data__tbl_dir *pss = (struct per_session_data__tbl_dir *)user;
|
||||
char j[LWS_PRE + 16384], *p = j + LWS_PRE, *start = p, *q, *q1, *w,
|
||||
*end = j + sizeof(j) - LWS_PRE, e[384], s[384], s1[384];
|
||||
const struct lws_protocol_vhost_options *pmo;
|
||||
struct fobj *f;
|
||||
int n, first = 1;
|
||||
|
||||
switch (reason) {
|
||||
case LWS_CALLBACK_PROTOCOL_INIT: /* per vhost */
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED:
|
||||
lwsl_debug("LWS_CALLBACK_ESTABLISHED\n");
|
||||
/*
|
||||
* send client the lwsgt table layout
|
||||
*/
|
||||
start = "{\"cols\":["
|
||||
" {\"name\": \"Date\"},"
|
||||
" {\"name\": \"Size\", \"align\": \"right\"},"
|
||||
" {\"name\": \"Icon\"},"
|
||||
" {\"name\": \"Name\", \"href\": \"uri\"},"
|
||||
" {\"name\": \"uri\", \"hide\": \"1\" }"
|
||||
" ]"
|
||||
"}";
|
||||
if (lws_write(wsi, (unsigned char *)start, strlen(start),
|
||||
LWS_WRITE_TEXT) < 0)
|
||||
return -1;
|
||||
|
||||
/* send a view update next */
|
||||
lws_callback_on_writable(wsi);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RECEIVE:
|
||||
if (len > sizeof(pss->reldir) - 1)
|
||||
len = sizeof(pss->reldir) - 1;
|
||||
if (!strstr(in, "..") && !strchr(in, '~'))
|
||||
lws_strncpy(pss->reldir, in, len + 1);
|
||||
else
|
||||
len = 0;
|
||||
pss->reldir[len] = '\0';
|
||||
if (pss->reldir[0] == '/' && !pss->reldir[1])
|
||||
pss->reldir[0] = '\0';
|
||||
lwsl_info("%s\n", pss->reldir);
|
||||
lws_callback_on_writable(wsi);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||
|
||||
if (scan_dir(wsi, pss))
|
||||
return 1;
|
||||
|
||||
p += lws_snprintf(p, end - p, "{\"breadcrumbs\":[");
|
||||
q = pss->reldir;
|
||||
|
||||
if (!q[0])
|
||||
p += lws_snprintf(p, end - p, "{\"name\":\"top\"}");
|
||||
|
||||
while (*q) {
|
||||
|
||||
q1 = strchr(q, '/');
|
||||
if (!q1) {
|
||||
if (first)
|
||||
strcpy(s, "top1");
|
||||
else
|
||||
strcpy(s, q);
|
||||
s1[0] = '\0';
|
||||
q += strlen(q);
|
||||
} else {
|
||||
n = lws_ptr_diff(q1, q);
|
||||
if (n > (int)sizeof(s) - 1)
|
||||
n = sizeof(s) - 1;
|
||||
if (first) {
|
||||
strcpy(s1, "/");
|
||||
strcpy(s, "top");
|
||||
} else {
|
||||
lws_strncpy(s, q, n + 1);
|
||||
|
||||
n = lws_ptr_diff(q1, pss->reldir);
|
||||
if (n > (int)sizeof(s1) - 1)
|
||||
n = sizeof(s1) - 1;
|
||||
lws_strncpy(s1, pss->reldir, n + 1);
|
||||
}
|
||||
q = q1 + 1;
|
||||
}
|
||||
if (!first)
|
||||
p += lws_snprintf(p, end - p, ",");
|
||||
else
|
||||
first = 0;
|
||||
|
||||
p += lws_snprintf(p, end - p, "{\"name\":\"%s\"",
|
||||
lws_json_purify(e, s, sizeof(e), NULL));
|
||||
if (*q) {
|
||||
w = s1;
|
||||
while (w[0] == '/' && w[1] == '/')
|
||||
w++;
|
||||
p += lws_snprintf(p, end - p, ",\"url\":\"%s\"",
|
||||
lws_json_purify(e, w, sizeof(e), NULL));
|
||||
}
|
||||
p += lws_snprintf(p, end - p, "}");
|
||||
if (!q1)
|
||||
break;
|
||||
}
|
||||
|
||||
p += lws_snprintf(p, end - p, "],\"data\":[");
|
||||
|
||||
f = pss->base.next;
|
||||
while (f) {
|
||||
/* format in JSON */
|
||||
p += lws_snprintf(p, end - p, "{\"Icon\":\"%s\",",
|
||||
lws_json_purify(e, f->icon, sizeof(e), NULL));
|
||||
p += lws_snprintf(p, end - p, " \"Date\":\"%s\",",
|
||||
lws_json_purify(e, f->date, sizeof(e), NULL));
|
||||
p += lws_snprintf(p, end - p, " \"Size\":\"%ld\",",
|
||||
f->size);
|
||||
if (f->uri)
|
||||
p += lws_snprintf(p, end - p, " \"uri\":\"%s\",",
|
||||
lws_json_purify(e, f->uri, sizeof(e), NULL));
|
||||
p += lws_snprintf(p, end - p, " \"Name\":\"%s\"}",
|
||||
lws_json_purify(e, f->name, sizeof(e), NULL));
|
||||
|
||||
f = f->next;
|
||||
|
||||
if (f)
|
||||
p += lws_snprintf(p, end - p, ",");
|
||||
}
|
||||
|
||||
p += lws_snprintf(p, end - p, "]}");
|
||||
|
||||
free_scan_dir(pss);
|
||||
|
||||
if (lws_write(wsi, (unsigned char *)start, p - start,
|
||||
LWS_WRITE_TEXT) < 0)
|
||||
return -1;
|
||||
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_HTTP_PMO:
|
||||
/* find the per-mount options we're interested in */
|
||||
lwsl_debug("LWS_CALLBACK_HTTP_PMO\n");
|
||||
pmo = (struct lws_protocol_vhost_options *)in;
|
||||
while (pmo) {
|
||||
if (!strcmp(pmo->name, "dir")) /* path to list files */
|
||||
pss->dir = pmo->value;
|
||||
pmo = pmo->next;
|
||||
}
|
||||
if (!pss->dir[0]) {
|
||||
lwsl_err("dirlisting: \"dir\" pmo missing\n");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_HTTP_DROP_PROTOCOL:
|
||||
//lwsl_notice("LWS_CALLBACK_HTTP_DROP_PROTOCOL\n");
|
||||
#if UV_VERSION_MAJOR > 0
|
||||
lws_protocol_dir_kill_monitor(pss);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static const struct lws_protocols protocols[] = {
|
||||
{
|
||||
"protocol-lws-table-dirlisting",
|
||||
callback_lws_table_dirlisting,
|
||||
sizeof(struct per_session_data__tbl_dir),
|
||||
0,
|
||||
},
|
||||
};
|
||||
|
||||
LWS_VISIBLE int
|
||||
init_protocol_lws_table_dirlisting(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_table_dirlisting(struct lws_context *context)
|
||||
{
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue