diff --git a/data/s/a.svg b/data/s/a.svg
index 0260f1c..d0335f6 100644
--- a/data/s/a.svg
+++ b/data/s/a.svg
@@ -2,9 +2,11 @@
diff --git a/data/s/b.svg b/data/s/b.svg
index d0335f6..0260f1c 100644
--- a/data/s/b.svg
+++ b/data/s/b.svg
@@ -2,11 +2,9 @@
diff --git a/data/s/bundle.1727d.js b/data/s/bundle.357e7.js
similarity index 66%
rename from data/s/bundle.1727d.js
rename to data/s/bundle.357e7.js
index 012e897..5e6bf43 100644
--- a/data/s/bundle.1727d.js
+++ b/data/s/bundle.357e7.js
@@ -1,2 +1,2 @@
-!function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var o in e)t.d(r,o,function(t){return e[t]}.bind(null,o));return r},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="/",t(t.s="/ODT")}({"/ODT":function(e,t,n){"use strict";function r(e,t){for(var n in t)e[n]=t[n];return e}function o(e){var t=e.parentNode;t&&t.removeChild(e)}function i(e,t,n){var r,o,i,l={};for(i in t)"key"==i?r=t[i]:"ref"==i?o=t[i]:l[i]=t[i];if(arguments.length>2&&(l.children=arguments.length>3?P.call(arguments,2):n),"function"==typeof e&&null!=e.defaultProps)for(i in e.defaultProps)void 0===l[i]&&(l[i]=e.defaultProps[i]);return u(e,l,r,o,null)}function u(e,t,n,r,o){var i={type:e,props:t,key:n,ref:r,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==o?++C:o};return null==o&&null!=x.vnode&&x.vnode(i),i}function l(e){return e.children}function c(e,t){this.props=e,this.context=t}function a(e,t){if(null==t)return e.__?a(e.__,e.__.__k.indexOf(e)+1):null;for(var n;t0?u(v.type,v.props,v.key,null,v.__v):v)){if(v.__=n,v.__b=n.__b+1,null===(y=S[p])||y&&v.key==y.key&&v.type===y.type)S[p]=void 0;else for(b=0;b=n.__.length&&n.__.push({}),n.__[e]}function o(e){return y=1,i(f,e)}function i(e,t,n){var o=r(p++,2);return o.t=e,o.__c||(o.__=[n?n(t):f(void 0,t),function(e){var t=o.t(o.__[0],e);o.__[0]!==t&&(o.__=[t,o.__[1]],o.__c.setState({}))}],o.__c=h),o.__}function u(e,t){var n=r(p++,3);!b.options.__s&&_(n.__H,t)&&(n.__=e,n.__H=t,h.__H.__h.push(n))}function l(e){var t=h.context[e.__c],n=r(p++,9);return n.c=e,t?(null==n.__&&(n.__=!0,t.sub(h)),t.props.value):e.__}function c(){for(var e;e=v.shift();)if(e.__P)try{e.__H.__h.forEach(a),e.__H.__h.forEach(s),e.__H.__h=[]}catch(t){e.__H.__h=[],b.options.__e(t,e.__v)}}function a(e){var t=h,n=e.__c;"function"==typeof n&&(e.__c=void 0,n()),h=t}function s(e){var t=h;e.__c=e.__(),h=t}function _(e,t){return!e||e.length!==t.length||t.some((function(t,n){return t!==e[n]}))}function f(e,t){return"function"==typeof t?t(e):t}n.d(t,"d",(function(){return o})),n.d(t,"c",(function(){return i})),n.d(t,"b",(function(){return u})),n.d(t,"a",(function(){return l}));var p,h,d,b=n("hosL"),y=0,v=[],m=b.options.__b,g=b.options.__r,O=b.options.diffed,j=b.options.__c,k=b.options.unmount;b.options.__b=function(e){h=null,m&&m(e)},b.options.__r=function(e){g&&g(e),p=0;var t=(h=e.__c).__H;t&&(t.__h.forEach(a),t.__h.forEach(s),t.__h=[])},b.options.diffed=function(e){O&&O(e);var t=e.__c;t&&t.__H&&t.__H.__h.length&&(1!==v.push(t)&&d===b.options.requestAnimationFrame||((d=b.options.requestAnimationFrame)||function(e){var t,n=function(){clearTimeout(r),w&&cancelAnimationFrame(t),setTimeout(e)},r=setTimeout(n,100);w&&(t=requestAnimationFrame(n))})(c)),h=null},b.options.__c=function(e,t){t.some((function(e){try{e.__h.forEach(a),e.__h=e.__h.filter((function(e){return!e.__||s(e)}))}catch(n){t.some((function(e){e.__h&&(e.__h=[])})),t=[],b.options.__e(n,e.__v)}})),j&&j(e,t)},b.options.unmount=function(e){k&&k(e);var t,n=e.__c;n&&n.__H&&(n.__H.__.forEach((function(e){try{a(e)}catch(e){t=e}})),t&&b.options.__e(t,n.__v))};var w="function"==typeof requestAnimationFrame},QfWi:function(e,t,n){"use strict";function r(e,t){for(var n in t)e[n]=t[n];return e}function o(e,t,n){var r,o=/(?:\?([^#]*))?(#.*)?$/,i=e.match(o),u={};if(i&&i[1])for(var c=i[1].split("&"),a=0;at.rank?-1:e.index-t.index}function u(e,t){return e.index=t,e.rank=function(e){return e.props.default?0:(t=e.props.path,l(t).map(c).join(""));var t}(e),e.props}function l(e){return e.replace(/(^\/+|\/+$)/g,"").split("/")}function c(e){return":"==e.charAt(0)?1+"*+?".indexOf(e.charAt(e.length-1))||4:5}function a(){var e;return""+((e=ne&&ne.location?ne.location:ne&&ne.getCurrentLocation?ne.getCurrentLocation():"undefined"!=typeof location?location:ie).pathname||"")+(e.search||"")}function s(e,t){return void 0===t&&(t=!1),"string"!=typeof e&&e.url&&(t=e.replace,e=e.url),function(e){for(var t=re.length;t--;)if(re[t].canRoute(e))return!0;return!1}(e)&&function(e,t){void 0===t&&(t="push"),ne&&ne[t]?ne[t](e):"undefined"!=typeof history&&history[t+"State"]&&history[t+"State"](null,null,e)}(e,t?"replace":"push"),_(e)}function _(e){for(var t=!1,n=0;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n0&&void 0!==arguments[0]?arguments[0]:"azif7eqCl5",t=yield fetch("".concat(_e,"/api/userdb"),{method:"GET",mode:"cors",headers:{Authentification:e}}).then((function(e){return e.text()})).then((function(e){return w(e)}));return t})),k.apply(this,arguments)}function w(e){var t=e.split("\n"),n=[];return t.map((function(e,t){var r=v(e.split([";"]),6);n.push({line:t,uid:r[0],first_name:r[1],last_name:r[2],rfid_uid:r[3],user_pin:r[4],enabled:"1"===r[5][0]})})),n}function S(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function A(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n0},t.prototype.routeTo=function(e){this.setState({url:e});var t=this.canRoute(e);return this.updating||this.forceUpdate(),t},t.prototype.componentWillMount=function(){re.push(this),this.updating=!0},t.prototype.componentDidMount=function(){var e=this;ne&&(this.unlisten=ne.listen((function(t){e.routeTo(""+(t.pathname||"")+(t.search||""))}))),this.updating=!1},t.prototype.componentWillUnmount=function(){"function"==typeof this.unlisten&&this.unlisten(),re.splice(re.indexOf(this),1)},t.prototype.componentWillUpdate=function(){this.updating=!0},t.prototype.componentDidUpdate=function(){this.updating=!1},t.prototype.getMatchingChildren=function(e,t,n){return e.filter(u).sort(i).map((function(e){var i=o(t,e.props.path,e.props);if(i){if(!1!==n){var u={url:t,matches:i};return r(u,i),delete u.ref,delete u.key,Object(ee.cloneElement)(e,u)}return e}})).filter(Boolean)},t.prototype.render=function(e,t){var n=e.children,r=e.onChange,o=t.url,i=this.getMatchingChildren(Object(ee.toChildArray)(n),o,!0),u=i[0]||null,l=this.previousUrl;return o!==l&&(this.previousUrl=o,"function"==typeof r&&r({router:this,url:o,previous:l,active:i,current:u})),u},t}(ee.Component),ce=function(e){return Object(ee.createElement)("a",r({onClick:p},e))};le.subscribers=oe,le.getCurrentUrl=a,le.route=s,le.Router=le,le.Route=function(e){return Object(ee.createElement)(e.component,e)},le.Link=ce,le.exec=o;var ae=n("QRet"),se=function(){return Object(ee.h)("div",{class:"container"},Object(ee.h)("h1",null,"Home"),Object(ee.h)("p",null,"This is the Home component."))},_e="http://192.168.4.22",fe={login:function(){return j.apply(this,arguments)},logout:function(){return"DUMMYTOKEN"},checkAuth:function(e){return"DUMMYTOKEN"===e},parsedb:w,fetchdb:function(){return k.apply(this,arguments)}},pe=function(e){for(var t=1;t2&&(l.children=arguments.length>3?U.call(arguments,2):n),"function"==typeof e&&null!=e.defaultProps)for(i in e.defaultProps)void 0===l[i]&&(l[i]=e.defaultProps[i]);return u(e,l,r,o,null)}function u(e,t,n,r,o){var i={type:e,props:t,key:n,ref:r,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==o?++T:o};return null==o&&null!=I.vnode&&I.vnode(i),i}function l(){return{current:null}}function c(e){return e.children}function a(e,t){this.props=e,this.context=t}function s(e,t){if(null==t)return e.__?s(e.__,e.__.__k.indexOf(e)+1):null;for(var n;t0?u(v.type,v.props,v.key,null,v.__v):v)){if(v.__=n,v.__b=n.__b+1,null===(b=k[p])||b&&v.key==b.key&&v.type===b.type)k[p]=void 0;else for(h=0;h2&&(c.children=arguments.length>3?U.call(arguments,2):n),u(e.type,c,o||e.key,i||e.ref,null)}function D(e,t){var n={__c:t="__cC"+H++,__:e,Consumer:function(e,t){return e.children(t)},Provider:function(e){var n,r;return this.getChildContext||(n=[],(r={})[t]=this,this.getChildContext=function(){return r},this.shouldComponentUpdate=function(e){this.props.value!==e.value&&n.some(f)},this.sub=function(e){n.push(e);var t=e.componentWillUnmount;e.componentWillUnmount=function(){n.splice(n.indexOf(e),1),t&&t.call(e)}}),e.children}};return n.Provider.__=n.Consumer.contextType=n}n.r(t),n.d(t,"render",(function(){return x})),n.d(t,"hydrate",(function(){return C})),n.d(t,"createElement",(function(){return i})),n.d(t,"h",(function(){return i})),n.d(t,"Fragment",(function(){return c})),n.d(t,"createRef",(function(){return l})),n.d(t,"isValidElement",(function(){return N})),n.d(t,"Component",(function(){return a})),n.d(t,"cloneElement",(function(){return E})),n.d(t,"createContext",(function(){return D})),n.d(t,"toChildArray",(function(){return b})),n.d(t,"options",(function(){return I}));var U,I,T,N,M,L,R,H,W={},F=[],$=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;U=F.slice,I={__e:function(e,t){for(var n,r,o;t=t.__;)if((n=t.__c)&&!n.__)try{if((r=n.constructor)&&null!=r.getDerivedStateFromError&&(n.setState(r.getDerivedStateFromError(e)),o=n.__d),null!=n.componentDidCatch&&(n.componentDidCatch(e),o=n.__d),o)return n.__E=n}catch(t){e=t}throw e}},T=0,N=function(e){return null!=e&&void 0===e.constructor},a.prototype.setState=function(e,t){var n;n=null!=this.__s&&this.__s!==this.state?this.__s:this.__s=r({},this.state),"function"==typeof e&&(e=e(r({},n),this.props)),e&&r(n,e),null!=e&&this.__v&&(t&&this.__h.push(t),f(this))},a.prototype.forceUpdate=function(e){this.__v&&(this.__e=!0,e&&this.__h.push(e),f(this))},a.prototype.render=c,M=[],L="function"==typeof Promise?Promise.prototype.then.bind(Promise.resolve()):setTimeout,p.__r=0,H=0},z8Av:function(e,t,n){"use strict";(function(e){function r(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null==n)return;var r,o,i=[],u=!0,l=!1;try{for(n=n.call(e);!(u=(r=n.next()).done)&&(i.push(r.value),!t||i.length!==t);u=!0);}catch(e){l=!0,o=e}finally{try{u||null==n.return||n.return()}finally{if(l)throw o}}return i}(e,t)||function(e,t){if(!e)return;if("string"==typeof e)return o(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return o(e,t)}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function o(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n2&&(l.children=arguments.length>3?P.call(arguments,2):n),"function"==typeof e&&null!=e.defaultProps)for(i in e.defaultProps)void 0===l[i]&&(l[i]=e.defaultProps[i]);return u(e,l,r,o,null)}function u(e,t,n,r,o){var i={type:e,props:t,key:n,ref:r,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==o?++C:o};return null==o&&null!=x.vnode&&x.vnode(i),i}function l(e){return e.children}function c(e,t){this.props=e,this.context=t}function a(e,t){if(null==t)return e.__?a(e.__,e.__.__k.indexOf(e)+1):null;for(var n;t0?u(v.type,v.props,v.key,null,v.__v):v)){if(v.__=n,v.__b=n.__b+1,null===(y=S[p])||y&&v.key==y.key&&v.type===y.type)S[p]=void 0;else for(b=0;b=n.__.length&&n.__.push({}),n.__[e]}function o(e){return y=1,i(f,e)}function i(e,t,n){var o=r(p++,2);return o.t=e,o.__c||(o.__=[n?n(t):f(void 0,t),function(e){var t=o.t(o.__[0],e);o.__[0]!==t&&(o.__=[t,o.__[1]],o.__c.setState({}))}],o.__c=h),o.__}function u(e,t){var n=r(p++,3);!b.options.__s&&_(n.__H,t)&&(n.__=e,n.__H=t,h.__H.__h.push(n))}function l(e){var t=h.context[e.__c],n=r(p++,9);return n.c=e,t?(null==n.__&&(n.__=!0,t.sub(h)),t.props.value):e.__}function c(){for(var e;e=v.shift();)if(e.__P)try{e.__H.__h.forEach(a),e.__H.__h.forEach(s),e.__H.__h=[]}catch(t){e.__H.__h=[],b.options.__e(t,e.__v)}}function a(e){var t=h,n=e.__c;"function"==typeof n&&(e.__c=void 0,n()),h=t}function s(e){var t=h;e.__c=e.__(),h=t}function _(e,t){return!e||e.length!==t.length||t.some((function(t,n){return t!==e[n]}))}function f(e,t){return"function"==typeof t?t(e):t}n.d(t,"d",(function(){return o})),n.d(t,"c",(function(){return i})),n.d(t,"b",(function(){return u})),n.d(t,"a",(function(){return l}));var p,h,d,b=n("hosL"),y=0,v=[],m=b.options.__b,g=b.options.__r,O=b.options.diffed,j=b.options.__c,k=b.options.unmount;b.options.__b=function(e){h=null,m&&m(e)},b.options.__r=function(e){g&&g(e),p=0;var t=(h=e.__c).__H;t&&(t.__h.forEach(a),t.__h.forEach(s),t.__h=[])},b.options.diffed=function(e){O&&O(e);var t=e.__c;t&&t.__H&&t.__H.__h.length&&(1!==v.push(t)&&d===b.options.requestAnimationFrame||((d=b.options.requestAnimationFrame)||function(e){var t,n=function(){clearTimeout(r),w&&cancelAnimationFrame(t),setTimeout(e)},r=setTimeout(n,100);w&&(t=requestAnimationFrame(n))})(c)),h=null},b.options.__c=function(e,t){t.some((function(e){try{e.__h.forEach(a),e.__h=e.__h.filter((function(e){return!e.__||s(e)}))}catch(n){t.some((function(e){e.__h&&(e.__h=[])})),t=[],b.options.__e(n,e.__v)}})),j&&j(e,t)},b.options.unmount=function(e){k&&k(e);var t,n=e.__c;n&&n.__H&&(n.__H.__.forEach((function(e){try{a(e)}catch(e){t=e}})),t&&b.options.__e(t,n.__v))};var w="function"==typeof requestAnimationFrame},QfWi:function(e,t,n){"use strict";function r(e,t){for(var n in t)e[n]=t[n];return e}function o(e,t,n){var r,o=/(?:\?([^#]*))?(#.*)?$/,i=e.match(o),u={};if(i&&i[1])for(var c=i[1].split("&"),a=0;at.rank?-1:e.index-t.index}function u(e,t){return e.index=t,e.rank=function(e){return e.props.default?0:(t=e.props.path,l(t).map(c).join(""));var t}(e),e.props}function l(e){return e.replace(/(^\/+|\/+$)/g,"").split("/")}function c(e){return":"==e.charAt(0)?1+"*+?".indexOf(e.charAt(e.length-1))||4:5}function a(){var e;return""+((e=ne&&ne.location?ne.location:ne&&ne.getCurrentLocation?ne.getCurrentLocation():"undefined"!=typeof location?location:ie).pathname||"")+(e.search||"")}function s(e,t){return void 0===t&&(t=!1),"string"!=typeof e&&e.url&&(t=e.replace,e=e.url),function(e){for(var t=re.length;t--;)if(re[t].canRoute(e))return!0;return!1}(e)&&function(e,t){void 0===t&&(t="push"),ne&&ne[t]?ne[t](e):"undefined"!=typeof history&&history[t+"State"]&&history[t+"State"](null,null,e)}(e,t?"replace":"push"),_(e)}function _(e){for(var t=!1,n=0;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n0&&void 0!==arguments[0]?arguments[0]:"azif7eqCl5",t=yield fetch("".concat(_e,"/api/userdb"),{method:"GET",mode:"cors",headers:{Authentification:e}}).then((function(e){return e.text()})).then((function(e){return w(e)}));return t})),k.apply(this,arguments)}function w(e){var t=e.split("\n"),n=[];return t.map((function(e,t){var r=v(e.split([";"]),6);n.push({line:t,uid:r[0],first_name:r[1],last_name:r[2],rfid_uid:r[3],user_pin:r[4],enabled:"1"===r[5][0]})})),n}function S(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function A(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n0},t.prototype.routeTo=function(e){this.setState({url:e});var t=this.canRoute(e);return this.updating||this.forceUpdate(),t},t.prototype.componentWillMount=function(){re.push(this),this.updating=!0},t.prototype.componentDidMount=function(){var e=this;ne&&(this.unlisten=ne.listen((function(t){e.routeTo(""+(t.pathname||"")+(t.search||""))}))),this.updating=!1},t.prototype.componentWillUnmount=function(){"function"==typeof this.unlisten&&this.unlisten(),re.splice(re.indexOf(this),1)},t.prototype.componentWillUpdate=function(){this.updating=!0},t.prototype.componentDidUpdate=function(){this.updating=!1},t.prototype.getMatchingChildren=function(e,t,n){return e.filter(u).sort(i).map((function(e){var i=o(t,e.props.path,e.props);if(i){if(!1!==n){var u={url:t,matches:i};return r(u,i),delete u.ref,delete u.key,Object(ee.cloneElement)(e,u)}return e}})).filter(Boolean)},t.prototype.render=function(e,t){var n=e.children,r=e.onChange,o=t.url,i=this.getMatchingChildren(Object(ee.toChildArray)(n),o,!0),u=i[0]||null,l=this.previousUrl;return o!==l&&(this.previousUrl=o,"function"==typeof r&&r({router:this,url:o,previous:l,active:i,current:u})),u},t}(ee.Component),ce=function(e){return Object(ee.createElement)("a",r({onClick:p},e))};le.subscribers=oe,le.getCurrentUrl=a,le.route=s,le.Router=le,le.Route=function(e){return Object(ee.createElement)(e.component,e)},le.Link=ce,le.exec=o;var ae=n("QRet"),se=function(){return Object(ee.h)("div",{class:"container"},Object(ee.h)("h1",null,"Home"),Object(ee.h)("p",null,"This is the Home component."))},_e="http://192.168.4.22",fe={login:function(){return j.apply(this,arguments)},logout:function(){return"DUMMYTOKEN"},checkAuth:function(e){return"DUMMYTOKEN"===e},parsedb:w,fetchdb:function(){return k.apply(this,arguments)}},pe=function(e){for(var t=1;t2&&(l.children=arguments.length>3?U.call(arguments,2):n),"function"==typeof e&&null!=e.defaultProps)for(i in e.defaultProps)void 0===l[i]&&(l[i]=e.defaultProps[i]);return u(e,l,r,o,null)}function u(e,t,n,r,o){var i={type:e,props:t,key:n,ref:r,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==o?++T:o};return null==o&&null!=I.vnode&&I.vnode(i),i}function l(){return{current:null}}function c(e){return e.children}function a(e,t){this.props=e,this.context=t}function s(e,t){if(null==t)return e.__?s(e.__,e.__.__k.indexOf(e)+1):null;for(var n;t0?u(v.type,v.props,v.key,null,v.__v):v)){if(v.__=n,v.__b=n.__b+1,null===(b=k[p])||b&&v.key==b.key&&v.type===b.type)k[p]=void 0;else for(h=0;h2&&(c.children=arguments.length>3?U.call(arguments,2):n),u(e.type,c,o||e.key,i||e.ref,null)}function D(e,t){var n={__c:t="__cC"+H++,__:e,Consumer:function(e,t){return e.children(t)},Provider:function(e){var n,r;return this.getChildContext||(n=[],(r={})[t]=this,this.getChildContext=function(){return r},this.shouldComponentUpdate=function(e){this.props.value!==e.value&&n.some(f)},this.sub=function(e){n.push(e);var t=e.componentWillUnmount;e.componentWillUnmount=function(){n.splice(n.indexOf(e),1),t&&t.call(e)}}),e.children}};return n.Provider.__=n.Consumer.contextType=n}n.r(t),n.d(t,"render",(function(){return x})),n.d(t,"hydrate",(function(){return C})),n.d(t,"createElement",(function(){return i})),n.d(t,"h",(function(){return i})),n.d(t,"Fragment",(function(){return c})),n.d(t,"createRef",(function(){return l})),n.d(t,"isValidElement",(function(){return N})),n.d(t,"Component",(function(){return a})),n.d(t,"cloneElement",(function(){return E})),n.d(t,"createContext",(function(){return D})),n.d(t,"toChildArray",(function(){return b})),n.d(t,"options",(function(){return I}));var U,I,T,N,M,L,R,H,W={},F=[],$=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;U=F.slice,I={__e:function(e,t){for(var n,r,o;t=t.__;)if((n=t.__c)&&!n.__)try{if((r=n.constructor)&&null!=r.getDerivedStateFromError&&(n.setState(r.getDerivedStateFromError(e)),o=n.__d),null!=n.componentDidCatch&&(n.componentDidCatch(e),o=n.__d),o)return n.__E=n}catch(t){e=t}throw e}},T=0,N=function(e){return null!=e&&void 0===e.constructor},a.prototype.setState=function(e,t){var n;n=null!=this.__s&&this.__s!==this.state?this.__s:this.__s=r({},this.state),"function"==typeof e&&(e=e(r({},n),this.props)),e&&r(n,e),null!=e&&this.__v&&(t&&this.__h.push(t),f(this))},a.prototype.forceUpdate=function(e){this.__v&&(this.__e=!0,e&&this.__h.push(e),f(this))},a.prototype.render=c,M=[],L="function"==typeof Promise?Promise.prototype.then.bind(Promise.resolve()):setTimeout,p.__r=0,H=0},z8Av:function(e,t,n){"use strict";(function(e){function r(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null==n)return;var r,o,i=[],u=!0,l=!1;try{for(n=n.call(e);!(u=(r=n.next()).done)&&(i.push(r.value),!t||i.length!==t);u=!0);}catch(e){l=!0,o=e}finally{try{u||null==n.return||n.return()}finally{if(l)throw o}}return i}(e,t)||function(e,t){if(!e)return;if("string"==typeof e)return o(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return o(e,t)}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function o(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);ndoorlock_pwa
\ No newline at end of file
+doorlock_pwa
\ No newline at end of file
diff --git a/src/AdminAuth.cpp b/src/AdminAuth.cpp
index 64ba351..49ebde6 100644
--- a/src/AdminAuth.cpp
+++ b/src/AdminAuth.cpp
@@ -10,50 +10,77 @@ bool AdminAuth::logout(const char *token)
tokenbuffer->setnull(tid);
return tid != -1;
}
-char *AdminAuth::login(const char *username, const char *password)
+char *AdminAuth::login(const String& username, const String& password)
{
char *res = nullptr;
File adminfile = LittleFS.open("admin", "r");
- bool current_field = false;
- uint16_t current_pos = 0;
- Serial.print('-');
- while (adminfile.available())
- {
- char current = adminfile.read();
- Serial.print(current);
- Serial.print('-');
- if (current == 0x00)
- {
- if (current_field)
- {
- if (password[current_pos] == 0x00)
- res = tokenbuffer->newToken();
- break;
- }
- else
- {
- if (username[current_pos] != 0x00)
- break;
- current_pos = 0;
- current_field = true;
- }
- }
- else if (!current_field)
- {
- Serial.print(String(username[current_pos]));
- if (username[current_pos] == 0x00 || username[current_pos] != current)
- break;
- current_pos++;
- }
- else
- {
- Serial.print(String(password[current_pos]));
- if (password[current_pos] == 0x00 || password[current_pos] != current)
- break;
- current_pos++;
- }
- Serial.print(',');
- }
+ if (username.equals(adminfile.readStringUntil('\0')) && password.equals(adminfile.readStringUntil('\0')))
+ res = tokenbuffer->newToken();
adminfile.close();
return res;
+}
+//char *AdminAuth::login(const char *username, const char *password)
+//{
+// char *res = nullptr;
+// File adminfile = LittleFS.open("admin", "r");
+// bool current_field = false;
+// uint16_t current_pos = 0;
+// Serial.print('-');
+// while (adminfile.available())
+// {
+// char current = adminfile.read();
+// Serial.print(current);
+// Serial.print('-');
+//
+// if (current == 0x00)
+// {
+// if (current_field)
+// {
+// if (password[current_pos] == 0x00)
+// res = tokenbuffer->newToken();
+// break;
+// }
+// else
+// {
+// if (username[current_pos] != 0x00)
+// break;
+// current_pos = 0;
+// current_field = true;
+// }
+// }
+// else if (current_pos >= MAX_USERNAMEPASSWORD_LENGTH)
+// break;
+// else if (!current_field)
+// {
+// Serial.print(String(username[current_pos]));
+// if (username[current_pos] == 0x00 || username[current_pos] != current)
+// break;
+// current_pos++;
+// }
+// else
+// {
+// Serial.print(String(password[current_pos]));
+// if (password[current_pos] == 0x00 || password[current_pos] != current)
+// break;
+// current_pos++;
+// }
+// Serial.print(',');
+// }
+// adminfile.close();
+// return res;
+//}
+bool AdminAuth::setAuth(const String& username, const String& password)
+{
+ if (username.length() == 0 || username.length() > MAX_USERNAMEPASSWORD_LENGTH || password.length()==0 || password.length() > MAX_USERNAMEPASSWORD_LENGTH)
+ return false;
+ File adminfile = LittleFS.open("admin", "w+");
+ adminfile.print(username);
+ adminfile.print('\0');
+ adminfile.print(password);
+ adminfile.print('\0');
+ adminfile.seek(0);
+ adminfile.sendAll(Serial);
+ delay(1);
+ adminfile.close();
+ return true;
}
\ No newline at end of file
diff --git a/src/AdminAuth.h b/src/AdminAuth.h
index e160b5d..8f67722 100644
--- a/src/AdminAuth.h
+++ b/src/AdminAuth.h
@@ -2,6 +2,7 @@
#include "LittleFS.h"
#define TOKENBUFFERCAPACITY 3
#define TOKENLENGHT 10
+#define MAX_USERNAMEPASSWORD_LENGTH 25
namespace webconsole
{
@@ -67,9 +68,11 @@ namespace webconsole
class AdminAuth
{
public:
- char *login(const char *username, const char *password);
+ //char *login(const char *username, const char *password);
+ char *login(const String &username,const String &password);
bool isAuth(const char *token);
bool logout(const char *token);
+ bool setAuth(const String &username, const String &password);
private:
TokenBuffer *tokenbuffer = new TokenBuffer();
diff --git a/src/WebConsole.cpp b/src/WebConsole.cpp
index 0a33f96..dbdbae9 100644
--- a/src/WebConsole.cpp
+++ b/src/WebConsole.cpp
@@ -76,9 +76,7 @@ void WebConsole::_auth()
}
else if (action.equals("login"))
{
- const char *username = _server->arg("username").c_str();
- const char *password = _server->arg("password").c_str();
- char *token = auth.login(username, password);
+ char *token = auth.login(_server->arg("username"), _server->arg("password"));
if (token == nullptr)
_server->send(401, "text/plain", "failed!");
else
@@ -90,6 +88,14 @@ void WebConsole::_auth()
bool res = auth.logout(token);
_server->send(200, "text/plain", res ? "success" : "failed");
}
+ else if (action.equals("update"))
+ {
+ //if (!_isAuth())
+ // return;
+ bool res = auth.setAuth(_server->arg("username"), _server->arg("password"));
+ _server->send(200, "text/plain", res ? "success" : "failed");
+
+ }
else
_server->send(404, "text/plain", "unknown action");
}
diff --git a/src/main.cpp b/src/main.cpp
index 14c3577..e5f0f0e 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -8,6 +8,8 @@
#include "WebConsole.h"
#include "UserDb.h"
#include "Config.h"
+#include
+#include
// File config
Config config;
userdb::UserDb userdatabase("userdb.csv");
@@ -23,22 +25,25 @@ Keyboard keyboard(200);
Interface iface;
// Wifi control
IPAddress local_IP(192, 168, 4, 22);
-IPAddress gateway(192, 168, 4, 9);
+IPAddress gateway(0, 0, 0, 0);
IPAddress subnet(255, 255, 255, 0);
-
-
+IPAddress dns(192, 168, 178, 1);
+DNSServer dnsServer;
void setup()
{
config.loadConfig();
Serial.begin(115200);
Serial.println("Starting System");
Serial.print("\t1. Network config ->");
- Serial.println(WiFi.softAPConfig(local_IP, gateway, subnet) ? "Ready" : "Failed!");
+ WiFi.mode(WIFI_AP);
+ Serial.println(WiFi.softAPConfig(local_IP, local_IP, subnet) ? "Ready" : "Failed!");
Serial.print("\t2 AP setup " + String(config.SSID)+ " -> ");
if (strlen(config.PASS) > 0)
Serial.println(WiFi.softAP(config.SSID, config.PASS) ? "Ready" : "Failed!");
else
Serial.println(WiFi.softAP(config.SSID) ? "Ready" : "Failed!");
+ WiFi.hostname("Doorlock");
+ dnsServer.start(53, "*", local_IP); // DNS spoofing (Only HTTP)
delay(150);
#ifdef DEBUG
userdatabase.print_to_serial();
@@ -52,6 +57,7 @@ void setup()
void loop()
{
+ dnsServer.processNextRequest();
rfid.scan();
web.serve();
keyboard.scanAsync();