Skip to content

Commit

Permalink
Add size to OTPAuth select-option fetcher for UX/UI simplicity and ef…
Browse files Browse the repository at this point in the history
…iciency. Minor Fixes
  • Loading branch information
A99US committed Nov 12, 2023
1 parent 405a6bb commit 6b9f334
Show file tree
Hide file tree
Showing 4 changed files with 12 additions and 2 deletions.
5 changes: 5 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,10 @@ <h3>Custom OTPAuth Source</h3>
)
arrayID += 1
}
// Max size of OTPAuth select-option fetcher
let optMax = 6
// Set the size of OTPAuth select-option fetcher
secretopt.size = selectArray.length<=optMax ? selectArray.length : optMax
// Select option already built, Get the token
checkArray()
};
Expand Down Expand Up @@ -802,6 +806,7 @@ <h3>Custom OTPAuth Source</h3>
let option = document.createElement("option")
option.value = value
option.text = text
if(value==0) option.selected = true
// let select = document.getElementById("selectid")
select.appendChild(option)
/*
Expand Down
5 changes: 5 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,10 @@ window.addEventListener("load", function () {
)
arrayID += 1
}
// Max size of OTPAuth select-option fetcher
let optMax = 6
// Set the size of OTPAuth select-option fetcher
secretopt.size = selectArray.length<=optMax ? selectArray.length : optMax
// Select option already built, Get the token
checkArray()
};
Expand Down Expand Up @@ -308,6 +312,7 @@ window.addEventListener("load", function () {
let option = document.createElement("option")
option.value = value
option.text = text
if(value==0) option.selected = true
// let select = document.getElementById("selectid")
select.appendChild(option)
/*
Expand Down
2 changes: 1 addition & 1 deletion index.min.html
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ <h3>Custom OTPAuth Source</h3>
This is a modified version by A99US (https://github.com/A99US/totp-js)
*/
"use strict";var Convert=Convert||{};Convert.base32toHex=function(t){if("string"!=typeof t)throw new Error("Argument to base32toHex() is not a string");if(0===t.length)throw new Error("Argument to base32toHex() is empty");if(!t.match(/^[A-Z2-7]+=*$/i))throw new Error("Argument to base32toHex() contains invalid characters");var r="",e="ABCDEFGHIJKLMNOPQRSTUVWXYZ234567".split(""),n=(t.toUpperCase()+"========").match(/.{1,8}/g);n.pop();var o=n[n.length-1].match(/=*$/)[0].length;if(o>6)throw new Error("Invalid base32 data (too much padding)");for(var a=0;a<n.length;a++){for(var u=0,i=n[a].split(""),s=0;s<i.length;s++){u*=e.length;var f=e.indexOf(i[s]);"="===i[s]&&(f=0),u+=f}r+=("0000000000"+u.toString(16)).substr(-10)}switch(o){case 6:return r.substr(0,r.length-8);case 4:return r.substr(0,r.length-6);case 3:return r.substr(0,r.length-4);case 1:return r.substr(0,r.length-2);default:return r}},Convert.hexToArray=function(t){return t.match(/[\dA-Fa-f]{2}/g).map((function(t){return parseInt(t,16)}))},Convert.arrayToHex=function(t){var r="";if(t instanceof ArrayBuffer)return Convert.arrayToHex(new Uint8Array(t));for(var e=0;e<t.length;e++)r+=("0"+t[e].toString(16)).substr(-2);return r},Convert.int32toHex=function(t){return("00000000"+Math.floor(Math.abs(t)).toString(16)).substr(-8)};var TOTP={getOtpCounter:function(t,r){return t/r|0},getCurrentCounter:function(t=30){return TOTP.getOtpCounter(Date.now()/1e3|0,t)},getCountdown:function(t=30){return t-(Date.now()/1e3|0)%t},otp:async function(t,r=6,e=!1,n=!1,o=!1){var a=function(t){return t==t|0};if("string"!=typeof t)throw new Error("Invalid hex key");if(!1===e)e=TOTP.getCurrentCounter();else if("number"!=typeof e||!a(e))throw new Error("Invalid counter value");if("number"!=typeof r||r<6||r>10||!a(r))throw new Error("Invalid size value (default is 6)");if(!1!==n){if("number"!=typeof n||!a(n))throw new Error("Invalid interval value");e+=TOTP.getCurrentCounter(n)}let u=await TOTP.hmac(t,"00000000"+Convert.int32toHex(e),o),i=parseInt(u.substr(-1),16),s=2147483647&parseInt(u.substr(2*i,8),16);return s=("0000000000"+s%Math.pow(10,r)).substr(-r),o&&console.debug("Token",s),s},hmac:async function(t,r,e){var n={name:"HMAC",hash:"SHA-1"},o=Uint8Array.from(Convert.hexToArray(t)),a=Uint8Array.from(Convert.hexToArray(r));let u=await crypto.subtle.importKey("raw",o,n,!1,["sign","verify"]);return e&&console.debug("Key imported",t),u=await crypto.subtle.sign(n,u,a),u=Convert.arrayToHex(u),e&&console.debug("HMAC calculated",a,u),u},isCompatible:function(){var t=function(r){return typeof r==typeof t};return typeof crypto==typeof TOTP&&typeof Uint8Array==typeof t&&!!(crypto.subtle&&t(crypto.subtle.importKey)&&t(crypto.subtle.sign)&&t(crypto.subtle.digest))}};if(typeof Convert!=typeof TOTP)throw TOTP=null,alert("Data conversion module not loaded"),new Error("Data conversion module not loaded");
"use strict";window.addEventListener("load",(function(){var e=document.querySelector.bind(document),t=document.querySelectorAll.bind(document),n=e("#getTokenSingle"),r=e("#getTokenArray"),o=e("#token"),a=e("#digits"),i=e("#enctype"),s=e("#interval"),l=e("#otpauthSource"),c=e("#secretopt");l.innerHTML="undefined"!=typeof otpauthsource?otpauthsource:"otpauth://totp?secret=CCDDBBAA333666\notpauth://totp/Example.Com:XMPLUser?secret=ABBCCDD2345&issuer=Example.Com\notpauth://totp/GitServer:Dev123?secret=CCBBDDAA5432&issuer=GitServer&digit=7&period=5";var d={1:{regex:"[A-Za-z2-7]+=*",title:"Secret should be Base32 encoded (using only a-z and 2-7)"},2:{regex:"([A-Fa-f0-9]{2})*",title:"Hexadecimal only (0-9 and a-f, even number of characters)"}},u=function(e,t,n){return 0|Math.max(Math.min(0|t,n),e)},p=function(e){return!e.reportValidity||e.reportValidity()},y=function(){if(p(o)&&p(a)&&p(i)){clearTimeout(g.single);var t=u(6,+a.value,8);let r=s.value;var n=o.value;if("1"===i.value){try{n=Convert.base32toHex(n)}catch(e){return void alert("Invalid Base32 characters")}!function(e,t,n,r){location.hash="#"+JSON.stringify({c:e,m:t,d:n,p:r})}(o.value,+i.value,t,r),e("#codes").style.display="block",v({secret:n,digits:t,period:parseInt(r),type:"single",init:!0,target:{time:".time",token:[["#totpPP",-2],["#totpP",-1],["#totpC",0],["#totpN",1]],countdown:[".counter","s"]}})}}},g={single:null,array:null},v=async function(t){try{if(t.debug&&console.debug("Getting TOTP for",t.secret),t.init||t.countdown==t.period){let n=TOTP.getCurrentCounter(t.period);t.countdown=TOTP.getCountdown(t.period);let r=0;for(e(t.target.time).textContent=(new Date).toLocaleTimeString();t.target.token[r];)e(t.target.token[r][0]).textContent=await TOTP.otp(t.secret,t.digits,n+t.target.token[r][1]),r+=1;t.init=!1}e(t.target.countdown[0]).textContent=t.countdown+(t.target.countdown[1]||""),t.countdown=1==t.countdown?t.period:t.countdown-1,g[t.type]=setTimeout((async()=>{await v(t)}),1e3)}catch(t){e("#codes").style.display="none",console.error(t),alert("Problem decoding Secret.\nVerify your secret and type are correct.\nMessage from decoder: "+t.message)}},m=[],h=async function(){if(c.options.length<1)return;clearTimeout(g.array);let t=m[c.value];t.init=!0;let n=(e,t="")=>"<label class='listLabel2'>"+e+"</label>"+t,r=(e,t)=>"<tr><td>"+e+"&nbsp;</td><td>&nbsp;"+t+"</td></tr>",o=e=>"<div class='form'>"+e+"</div>";e("#arrayResult").innerHTML=o(n("Issuer"," : ")+(t.issuer&&""!=t.issuer?t.issuer:"<i>No Issuer</i>"))+o(n("Username"," : ")+(t.username&&""!=t.username?t.username:"<i>No Username</i>"))+o(n("Setting"," : ")+t.digits+" digits, "+t.period+"s period, "+t.algo+" algorithm")+o(n("Generated at"," : ")+"<span class='timeArray'></span>, refresh in <span class='counterArray'></span>")+"<BR><table class='table'>"+r("<code class='tokenArrayN totp'></code>","Next Token")+r("<code class='tokenArrayC totp'></code>","<b>Current Token</b>")+r("<code class='tokenArrayP totp'></code>","Previous Token")+r("<code class='tokenArrayPP totp'></code>","2nd Previous Token")+"</table>",await v(t)},f=function(e,t,n=""){let r=document.createElement("option");r.value=t,r.text=n,e.appendChild(r)};TOTP.isCompatible()?(n.addEventListener("click",y),r.addEventListener("click",(async function(){clearTimeout(g.array),m=[],c.innerHTML="",e("#arrayResult").innerHTML="";let t,n,r,o,a,i,s,d,p,y,v,w,b=l.value.split("\n"),k=0;for(;b[k];){if(t=b[k],n=new URL(t),r=e=>n.searchParams.get(e),o=n.pathname.split("/"),a=o[2]||null,i=o[3]?decodeURIComponent(o[3]):null,"otpauth:"==n.protocol&&"totp"==a&&r("secret")){s=i&&i.split(":").length>1?i.split(":").slice(-1)[0]:null,d=r("issuer")?decodeURIComponent(r("issuer")):i&&s?i.substr(0,i.length-(s.length+1)):i||null,p=r("algo")||r("algorithm")||"SHA1",y=u(6,+parseInt(r("digits")||r("digit")),8)||6,v=parseInt(r("period"))||parseInt(r("interval"))||30;try{w=Convert.base32toHex(r("secret"))}catch(e){return void alert("Invalid Base32 characters\ncode : "+r("secret")+"\nLine : "+(k+1))}m.push({issuer:d,username:s,secret:w,secretori:r("secret"),digits:y,period:parseInt(v),algo:p,type:"array",init:!0,target:{time:".timeArray",token:[[".tokenArrayC",0],[".tokenArrayP",-1],[".tokenArrayPP",-2],[".tokenArrayN",1]],countdown:[".counterArray","s"]}})}k+=1}for(k=0;m[k];)t=m[k],f(c,k,t.issuer&&""!=t.issuer||t.username&&""!=t.username?(t.issuer&&""!=t.issuer?t.issuer:"No Issuer")+" - "+(t.username&&""!=t.username?t.username:"No Username"):"Secret Code : "+t.secretori),k+=1;h()})),c.addEventListener("change",h)):(alert("Your browser is outdated and lacks missing components for this implementation. Please update your browser"),e(".container").innerHTML='<h1 class="alert alert-danger">Outdated browser, try to live in the year'+(new Date).getFullYear()+"</h1>");var w=function(){d[i.value]?(o.setAttribute("pattern",d[i.value].regex),o.setAttribute("title",d[i.value].title)):(alert("attempted to select invalid Pattern. The website will reset now"),location.reload(!0))};i.addEventListener("change",w);for(var b=0!==location.protocol.indexOf("file:"),k=t(".online-only"),C=t(".offline-only"),L=0;L<C.length;L++)C[L].style.display=b?"none":"block";for(L=0;L<k.length;L++)k[L].style.display=b?"block":"none";function T(e,t="download.txt"){"string"==typeof e&&(e=new Blob([e],{type:"text/plain"})),e=window.URL.createObjectURL(e);let n=document.createElement("a");n.href=e,n.download=t,n.style.display="none",document.body.appendChild(n),n.click(),document.body.removeChild(n),window.URL.revokeObjectURL(e),window.URL.revokeObjectURL(n.href)}(function(){if(location.hash.length>1){try{var e=JSON.parse(decodeURIComponent(location.hash.substr(1)));o.value=e.c,s.value=e.p,d[e.m]&&(i.value=e.m),a.value=u(6,0|e.d,8)}catch(e){return console.warn(e,"Invalid JSON in URL:",location.hash.substr(1)),!1}return w(),!0}return w(),!1})()&&y(),Array.prototype.slice.call(t("#token,#digits,#enctype,#interval"),0).forEach((function(e){e.addEventListener("keydown",(function(e){13!==e.keyCode&&13!==e.which||(e.preventDefault(),e.stopPropagation(),y())}))})),e("#singleHelpButton").addEventListener("click",(function(t){"block"==e("#singleHelpDiv").style.display?(e("#singleHelpDiv").style.display="none",e("#singleHelpButton").text="Show Help"):(e("#singleHelpDiv").style.display="block",e("#singleHelpButton").text="Hide Help")})),e("#arrayHelpButton").addEventListener("click",(function(t){"block"==e("#arrayHelpDiv").style.display?(e("#arrayHelpDiv").style.display="none",e("#arrayHelpButton").text="Show Help"):(e("#arrayHelpDiv").style.display="block",e("#arrayHelpButton").text="Hide Help")})),e("#hideWarningButton").addEventListener("click",(function(t){e("#warningDiv").style.display="none"})),e("#txtload").addEventListener("click",(function(t){e("#file").click()})),e("#file").addEventListener("change",(async function(t){l.value=(await async function(e){const t=e=>new Promise(((t,n)=>{const r=new FileReader;r.onload=e=>t(e.target.result),r.onerror=n,r.readAsText(e)}));let n,r,o=e.files,a=[];r=Object.keys(o).length;for(let e=0;e<r;e++)n=o[e],a.push(await t(n));return a}(this)).join("\n\n"),e("#file").value=""})),e("#txtsave").addEventListener("click",(function(e){T(l.value,"OTPAuth.txt")}))}));
"use strict";window.addEventListener("load",(function(){var e=document.querySelector.bind(document),t=document.querySelectorAll.bind(document),n=e("#getTokenSingle"),r=e("#getTokenArray"),o=e("#token"),a=e("#digits"),i=e("#enctype"),s=e("#interval"),l=e("#otpauthSource"),c=e("#secretopt");l.innerHTML="undefined"!=typeof otpauthsource?otpauthsource:"otpauth://totp?secret=CCDDBBAA333666\notpauth://totp/Example.Com:XMPLUser?secret=ABBCCDD2345&issuer=Example.Com\notpauth://totp/GitServer:Dev123?secret=CCBBDDAA5432&issuer=GitServer&digit=7&period=5";var d={1:{regex:"[A-Za-z2-7]+=*",title:"Secret should be Base32 encoded (using only a-z and 2-7)"},2:{regex:"([A-Fa-f0-9]{2})*",title:"Hexadecimal only (0-9 and a-f, even number of characters)"}},u=function(e,t,n){return 0|Math.max(Math.min(0|t,n),e)},p=function(e){return!e.reportValidity||e.reportValidity()},y=function(){if(p(o)&&p(a)&&p(i)){clearTimeout(g.single);var t=u(6,+a.value,8);let r=s.value;var n=o.value;if("1"===i.value){try{n=Convert.base32toHex(n)}catch(e){return void alert("Invalid Base32 characters")}!function(e,t,n,r){location.hash="#"+JSON.stringify({c:e,m:t,d:n,p:r})}(o.value,+i.value,t,r),e("#codes").style.display="block",v({secret:n,digits:t,period:parseInt(r),type:"single",init:!0,target:{time:".time",token:[["#totpPP",-2],["#totpP",-1],["#totpC",0],["#totpN",1]],countdown:[".counter","s"]}})}}},g={single:null,array:null},v=async function(t){try{if(t.debug&&console.debug("Getting TOTP for",t.secret),t.init||t.countdown==t.period){let n=TOTP.getCurrentCounter(t.period);t.countdown=TOTP.getCountdown(t.period);let r=0;for(e(t.target.time).textContent=(new Date).toLocaleTimeString();t.target.token[r];)e(t.target.token[r][0]).textContent=await TOTP.otp(t.secret,t.digits,n+t.target.token[r][1]),r+=1;t.init=!1}e(t.target.countdown[0]).textContent=t.countdown+(t.target.countdown[1]||""),t.countdown=1==t.countdown?t.period:t.countdown-1,g[t.type]=setTimeout((async()=>{await v(t)}),1e3)}catch(t){e("#codes").style.display="none",console.error(t),alert("Problem decoding Secret.\nVerify your secret and type are correct.\nMessage from decoder: "+t.message)}},h=[],m=async function(){if(c.options.length<1)return;clearTimeout(g.array);let t=h[c.value];t.init=!0;let n=(e,t="")=>"<label class='listLabel2'>"+e+"</label>"+t,r=(e,t)=>"<tr><td>"+e+"&nbsp;</td><td>&nbsp;"+t+"</td></tr>",o=e=>"<div class='form'>"+e+"</div>";e("#arrayResult").innerHTML=o(n("Issuer"," : ")+(t.issuer&&""!=t.issuer?t.issuer:"<i>No Issuer</i>"))+o(n("Username"," : ")+(t.username&&""!=t.username?t.username:"<i>No Username</i>"))+o(n("Setting"," : ")+t.digits+" digits, "+t.period+"s period, "+t.algo+" algorithm")+o(n("Generated at"," : ")+"<span class='timeArray'></span>, refresh in <span class='counterArray'></span>")+"<BR><table class='table'>"+r("<code class='tokenArrayN totp'></code>","Next Token")+r("<code class='tokenArrayC totp'></code>","<b>Current Token</b>")+r("<code class='tokenArrayP totp'></code>","Previous Token")+r("<code class='tokenArrayPP totp'></code>","2nd Previous Token")+"</table>",await v(t)},f=function(e,t,n=""){let r=document.createElement("option");r.value=t,r.text=n,0==t&&(r.selected=!0),e.appendChild(r)};TOTP.isCompatible()?(n.addEventListener("click",y),r.addEventListener("click",(async function(){clearTimeout(g.array),h=[],c.innerHTML="",e("#arrayResult").innerHTML="";let t,n,r,o,a,i,s,d,p,y,v,w,b=l.value.split("\n"),k=0;for(;b[k];){if(t=b[k],n=new URL(t),r=e=>n.searchParams.get(e),o=n.pathname.split("/"),a=o[2]||null,i=o[3]?decodeURIComponent(o[3]):null,"otpauth:"==n.protocol&&"totp"==a&&r("secret")){s=i&&i.split(":").length>1?i.split(":").slice(-1)[0]:null,d=r("issuer")?decodeURIComponent(r("issuer")):i&&s?i.substr(0,i.length-(s.length+1)):i||null,p=r("algo")||r("algorithm")||"SHA1",y=u(6,+parseInt(r("digits")||r("digit")),8)||6,v=parseInt(r("period"))||parseInt(r("interval"))||30;try{w=Convert.base32toHex(r("secret"))}catch(e){return void alert("Invalid Base32 characters\ncode : "+r("secret")+"\nLine : "+(k+1))}h.push({issuer:d,username:s,secret:w,secretori:r("secret"),digits:y,period:parseInt(v),algo:p,type:"array",init:!0,target:{time:".timeArray",token:[[".tokenArrayC",0],[".tokenArrayP",-1],[".tokenArrayPP",-2],[".tokenArrayN",1]],countdown:[".counterArray","s"]}})}k+=1}for(k=0;h[k];)t=h[k],f(c,k,t.issuer&&""!=t.issuer||t.username&&""!=t.username?(t.issuer&&""!=t.issuer?t.issuer:"No Issuer")+" - "+(t.username&&""!=t.username?t.username:"No Username"):"Secret Code : "+t.secretori),k+=1;c.size=h.length<=6?h.length:6,m()})),c.addEventListener("change",m)):(alert("Your browser is outdated and lacks missing components for this implementation. Please update your browser"),e(".container").innerHTML='<h1 class="alert alert-danger">Outdated browser, try to live in the year'+(new Date).getFullYear()+"</h1>");var w=function(){d[i.value]?(o.setAttribute("pattern",d[i.value].regex),o.setAttribute("title",d[i.value].title)):(alert("attempted to select invalid Pattern. The website will reset now"),location.reload(!0))};i.addEventListener("change",w);for(var b=0!==location.protocol.indexOf("file:"),k=t(".online-only"),C=t(".offline-only"),L=0;L<C.length;L++)C[L].style.display=b?"none":"block";for(L=0;L<k.length;L++)k[L].style.display=b?"block":"none";function T(e,t="download.txt"){"string"==typeof e&&(e=new Blob([e],{type:"text/plain"})),e=window.URL.createObjectURL(e);let n=document.createElement("a");n.href=e,n.download=t,n.style.display="none",document.body.appendChild(n),n.click(),document.body.removeChild(n),window.URL.revokeObjectURL(e),window.URL.revokeObjectURL(n.href)}(function(){if(location.hash.length>1){try{var e=JSON.parse(decodeURIComponent(location.hash.substr(1)));o.value=e.c,s.value=e.p,d[e.m]&&(i.value=e.m),a.value=u(6,0|e.d,8)}catch(e){return console.warn(e,"Invalid JSON in URL:",location.hash.substr(1)),!1}return w(),!0}return w(),!1})()&&y(),Array.prototype.slice.call(t("#token,#digits,#enctype,#interval"),0).forEach((function(e){e.addEventListener("keydown",(function(e){13!==e.keyCode&&13!==e.which||(e.preventDefault(),e.stopPropagation(),y())}))})),e("#singleHelpButton").addEventListener("click",(function(t){"block"==e("#singleHelpDiv").style.display?(e("#singleHelpDiv").style.display="none",e("#singleHelpButton").text="Show Help"):(e("#singleHelpDiv").style.display="block",e("#singleHelpButton").text="Hide Help")})),e("#arrayHelpButton").addEventListener("click",(function(t){"block"==e("#arrayHelpDiv").style.display?(e("#arrayHelpDiv").style.display="none",e("#arrayHelpButton").text="Show Help"):(e("#arrayHelpDiv").style.display="block",e("#arrayHelpButton").text="Hide Help")})),e("#hideWarningButton").addEventListener("click",(function(t){e("#warningDiv").style.display="none"})),e("#txtload").addEventListener("click",(function(t){e("#file").click()})),e("#file").addEventListener("change",(async function(t){l.value=(await async function(e){const t=e=>new Promise(((t,n)=>{const r=new FileReader;r.onload=e=>t(e.target.result),r.onerror=n,r.readAsText(e)}));let n,r,o=e.files,a=[];r=Object.keys(o).length;for(let e=0;e<r;e++)n=o[e],a.push(await t(n));return a}(this)).join("\n\n"),e("#file").value=""})),e("#txtsave").addEventListener("click",(function(e){T(l.value,"OTPAuth.txt")}))}));
</script>
</body>
</html>
Loading

0 comments on commit 6b9f334

Please sign in to comment.