Initial release

This commit is contained in:
Joaquim Homrighausen
2022-10-21 11:01:16 +02:00
parent bf37802802
commit bf85b9f127
24 changed files with 1341 additions and 1 deletions
+96 -1
View File
@@ -1,2 +1,97 @@
[![Software License](https://img.shields.io/badge/license-GPLv2-blue?style=flat-square)](LICENSE)
[![made-with-javascript](https://img.shields.io/badge/Made%20with-JavaScript-1f425f.svg)](https://en.wikipedia.org/wiki/JavaScript)
# POMjs
POMjs is a random password generator in HTML and pure Javascript
**POMjs** is a random password generator in HTML and pure Javascript. It can be customized by modifying the sources. There's really nothing magic going on here, but it works and is somewhat responsive. The goal was to make something small, useful, and resonably free from dependencies.
## Parts
**POMjs** uses a "minified" version of [normalize.css](https://necolas.github.io/normalize.css) to reset the DOM to reasonable settings :blush:
**POMjs** includes no external resources and contains no tracking code or cookie management.
## Installation
Download the distribution or clone the repo. Files and folders should be placed in your web root, or another folder accessible to your web server.
There may be references to "Öppet Moln" ("Open Cloud"), which is a Swedish site run by the author of **POMjs**, [oppetmoln.se](https://oppetmoln.se), to promote open source solutions for general use. You can, of course, delete such references.
I'd appreciate a mention on whatever website you use this one, and a link to the original repo.
## Usage
From a visitor perspective, simply enable the desired string sequences, and possibly adjust the password length. Click on the `Enter` button.
The generated password is displayed at the bottom of the box, along with a strength indicator.
The slider can also be used to change the number of characters in the generated password, as can the input field to the right of the slider.
The HTML should have proper `tabindex` attributes for easier keyboard navigation.
To copy the generated password to the clipboard, click on the password.
## Customization
The original Javascript source is in `password-om.js`. The `index.html` file includes `password-om.min.js`. So I suggest you make your customizations in the "unminified" .js file and then create a new `password-om.min.js` file. If you do not have access to a "minification tool", you can simply copy an "unminified" version of `password-om.js` to `password-om.min.js`, it's really not that big of a difference.
Most parameters/settings can be changed in the `.js` file.
### Variables (in .js file)
| Name | Default | Comment |
| ------------------------- | -------------------- | ------------------------------------------ |
| POM_strUppercase | Auto-generated A-Z | Change if needed, used by default |
| POM_strLowercase | Auto-generated a-z | Change if needed, used by default |
| POM_strDigits | Auto-generated 0-9 | Change if needed, used by default |
| POM_strSpecialOne | -.\_#$@%! | Change if needed, used by default |
| POM_strSpecialTwo | "+(){}[]?&,\*<>\|:;^ | Change if needed, **not** used by default |
| POM_strUppercase_Default | true | Enables POM_strUppercase by default |
| POM_strLowercase_Default | true | Enables POM_strLowercase by default |
| POM_strDigits_Default | true | Enables POM_strDigits by default |
| POM_strSpecialOne_Default | true | Enables POM_strSpecialOne by default |
| POM_strSpecialTwo_Default | **false** | Enables POM_strSpecialTwo by default |
| POM_mkPasswordOnLoad | true | Generate password on first page load |
| POM_minLength | 16 | Minimum (and default) password length |
| POM_maxLength | 256 | Maxmium password length |
| POM_sliderStep | 8 | 1 - .. |
| POM_debug | false | Emit "debug" output with console.log() |
### CSS
Most of the styling is done via CSS. I have tried to make it reasonably responsive, and I have tested with it with various browsers.
Please note that `index.html` makes use of `password-om.min.css` by default.
### Translation
The (very) few strings can be translated. The distribution contains strings in English (default), Swedish, and German. The code attempts to guess the language from the **navigator.language** properties. If they do not exist, or cannot be interpreted, the fallback language used is English.
The "string setup" is done in the `POM_initialSetup()` function.
If you would like to contribute to the translation, please open an issue and post the language and the translated strings, please include how/if you would like to be mentioned in the credits.
## Credits
Thanks to **Peter Hampf** (hello `O/T-Track` :metal:) for the German translation :blush:
The "cloud icon" comes from [Streamline](https://streamlinehq.com)
**POMjs** was written by Joaquim Homrighausen while converting caffeine into code :coffee:
## License
**POMjs** is licensed under the GPLv2 license. See the [`LICENSE`](LICENSE) file for more details.
Copyright 2022 Joaquim Homrighausen.
### External references
These links are not here for any sort of endorsement or marketing, they're purely for informational purposes :sunglasses:
* WebbPlatsen; [webbplatsen.se](https://webbplatsen.se)
* Öppet Moln ("Open Cloud"); [oppetmoln.se](https://oppetmoln.se)
* me; [joho.se](https://joho.se) and [github.com/joho1968](https://github.com/joho1968)
* POMjs repo; [github.com/joho1968/POMjs](https://github.com/joho1968/POMjs)
* normalize.css repo; [github.com/necolas/normalize.css](https://github.com/necolas/normalize.css)
* Streamline, Icons and Illustrations; [streamlinehq.com](https://streamlinehq.com)
+9
View File
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="https://password.oppetmoln.se/favicon/mstile-150x150.png"/>
<TileColor>#2b5797</TileColor>
</tile>
</msapplication>
</browserconfig>
+349
View File
@@ -0,0 +1,349 @@
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in iOS.
*/
html {
line-height: 1.15; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers.
*/
body {
margin: 0;
}
/**
* Render the `main` element consistently in IE.
*/
main {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* Remove the gray background on active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10.
*/
img {
border-style: none;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input { /* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select { /* 1 */
text-transform: none;
}
/**
* Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline;
}
/**
* Remove the default vertical scrollbar in IE 10+.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in Edge, IE 10+, and Firefox.
*/
details {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Misc
========================================================================== */
/**
* Add the correct display in IE 10+.
*/
template {
display: none;
}
/**
* Add the correct display in IE 10.
*/
[hidden] {
display: none;
}
+1
View File
@@ -0,0 +1 @@
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */button,hr,input{overflow:visible}progress,sub,sup{vertical-align:baseline}[type=checkbox],[type=radio],legend{box-sizing:border-box;padding:0}html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}details,main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:ButtonText dotted 1px}fieldset{padding:.35em .75em .625em}legend{color:inherit;display:table;max-width:100%;white-space:normal}textarea{overflow:auto}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}[hidden],template{display:none}
+248
View File
@@ -0,0 +1,248 @@
:root {
--pom-bg-color-normal:#ffffff;
--pom-fg-color-normal:#000000;
--pom-h-color:#404040;
--pom-a-color:#008000;
--pom-a-hover-color:#006000;
--pom-gen-bg:#cccccc;
--pom-gen-border:#bbbbbb;
--pom-gen-shadow:#aaaaaa;
--pom-gen-opacity:1;
--pom-mk-password-field-border:#bbbbbb;
--pom-mk-password-field-focus:green;
--pom-mk-password-field-focus-text:#ffffff;
--pom-mk-password-len-slider:#e3e3e3;
--pom-mk-password-len-slider-opacity:0.7;
--pom-mk-password-len-slider-thumb:#00008B;
--pom-mk-password-btn:#000000;
--pom-mk-password-btn-text:#ffffff;
}
@media screen and (prefers-color-scheme: dark) {
:root {
--pom-bg-color-normal:#000000;
--pom-fg-color-normal:#ffffff;
--pom-h-color:#00e000;
--pom-a-color:#00dddd;
--pom-a-hover-color:#00ffff;
--pom-gen-bg:#383838;
--pom-gen-border:#686868;
--pom-gen-shadow:#cccccc;
--pom-gen-opacity:0.9;
--pom-mk-password-field-border:#eeeeee;
--pom-mk-password-field-focus:#00FF33;
--pom-mk-password-field-focus-text:#000000;
--pom-mk-password-len-slider:#0000ff;
--pom-mk-password-len-slider-opacity:0.9;
--pom-mk-password-len-slider-thumb:#f0f0f0;
--pom-mk-password-btn:#eeeeee;
--pom-mk-password-btn-text:#000000;
}
}
html {
background-color:var(--pom-bg-color-normal);
color:var(--pom-fg-color-normal);
}
body {
padding:0px;
margin:0px;
font-family: "Lucida Sans Typewriter", "Lucida Console", Monaco, "Bitstream Vera Sans Mono", monospace;
}
h1, h2 {
color:var(--pom-h-color);
}
header {
margin-top:30px;
text-align:center;
}
footer {
margin-top:30px;
padding:5px;
text-align:center;
}
a, a:visited {
text-decoration:none;
color:var(--pom-a-color);
}
a:hover {
color:var(--pom-a-hover-color);
text-decoration:underline;
}
#cfg-page-title {
font-size:1.8rem;
}
#cfg-page-slogan {
font-size:1.6rem;
}
#cfg-page-lang {
font-size:0.8rem;
color:#aaaaaa;
}
#gen-hosted-by {
font-size:0.9rem !important;
}
#gen-timestamp {
font-size:0.8rem !important;
color:#eee;
display:none;
}
#generator {
padding:40px;
margin:0 auto !important;
width:50vw;
max-width:450px;
min-width:350px !important;
border-radius:20px;
background-color:var(--pom-gen-bg);
border:2px solid var(--pom-gen-border);
box-shadow:0 0 5px var(--pom-gen-shadow);
opacity:var(--pom-gen-opacity);
}
#mk-password-div {
margin:0 auto !important;
}
#mk-password-field {
width:98% !important;
border:2px solid var(--pom-mk-password-field-border);
border-radius:5px !important;
}
.mk-password-field-focus {
outline:none !important;
border:2px solid var(--pom-mk-password-field-focus) !important;
background-color:var(--pom-mk-password-field-focus) !important;
color:var(--pom-mk-password-field-focus-text) !important;
transition:0.5s;
}
#mk-password-field:hover {
cursor:pointer !important;
}
#mk-password-good {
width:100% !important;
height:48px;
margin-top:10px;
}
#mk-password-len-slider {
-webkit-appearance:none;
outline: none;
width:85%;
max-width:410px !important;
height: 12px;
border-radius: 5px;
opacity:var(--pom-mk-password-len-slider-opacity);
-webkit-transition:.2s;
transition:opacity .2s;
background:var(--pom-mk-password-len-slider);
}
#mk-password-len-slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
cursor:pointer;
width:22px;
height:22px;
border-radius:50%;
background:var(--pom-mk-password-len-slider-thumb);
}
#mk-password-len-slider::-moz-range-thumb {
cursor:pointer;
width:22px;
height:22px;
border-radius:50%;
background:var(--pom-mk-password-len-slider-thumb);
}
#mk-length-field {
font-size:0.9rem !important;
width:32px !important;
border:1px solid #cccccc !important;
border-radius:5px !important;
}
#mk-length-field:hover {
cursor:pointer !important;
}
#mk-length-field:active {
cursor:text !important;
}
#mk-length-field:focus {
cursor:text !important;
}
#mk-password-btn-div {
text-align:right;
margin-bottom:10px;
}
#mk-password-btn {
width:60px;
font-size:1.4rem !important;
line-height:1.4rem !important;
font-weight:bold;
max-height:32px !important;
border:1px solid #cccccc !important;
border-radius:5px !important;
color:var(--pom-mk-password-btn-text);
background-color:var(--pom-mk-password-btn);
}
#mk-password-btn:hover {
cursor:pointer !important;
}
#mk-password-btn:before {
content: "";
display:inline-block;
height:1.6rem;
vertical-align:middle;
}
.selection-row {
font-size:1.1rem !important;
width:100%;
margin-bottom:10px;
display:grid;
grid-template-columns: 310px 40px;
justify-content:space-between;
}
.selection-col {
text-align:right;
justify-self:end;
}
.check-option {
width:28px;
height:20px;
position:relative;
display:inline-block;
margin-left:auto;
padding:0 !important;
}
.check-option input {
width:0;
height:0;
opacity:0;
}
/* Let's be nice to smaller screens */
@media only screen and (max-width: 450px) {
footer {
margin-top:20px;
font-size:0.8rem !important;
}
#gen-hosted-by {
font-size:0.8rem !important;
}
#generator {
padding:20px !important;
margin:0 auto !important;
width:100% !important;
border-radius:0px !important;
box-shadow:none !important;
max-width:320px !important;
min-width:300px !important;
}
.static-col {
font-size:0.9rem !important;
}
#cfg-page-title {
font-size:1.4rem !important;
}
#cfg-page-slogan {
font-size:1.2rem !important;
}
.selection-row {
grid-template-columns: 280px 40px !important;
}
}
/* end of file "password-om.css" */
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 671 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

+9
View File
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="https://password.oppetmoln.se/favicon/mstile-150x150.png"/>
<TileColor>#2b5797</TileColor>
</tile>
</msapplication>
</browserconfig>
Binary file not shown.

After

Width:  |  Height:  |  Size: 671 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

+27
View File
@@ -0,0 +1,27 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="260.000000pt" height="260.000000pt" viewBox="0 0 260.000000 260.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.14, written by Peter Selinger 2001-2017
</metadata>
<g transform="translate(0.000000,260.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M1811 2395 c-77 -17 -180 -64 -209 -96 -50 -52 -6 -149 67 -149 20 0
46 6 57 14 68 48 223 70 328 46 254 -57 410 -318 341 -570 -10 -36 -18 -75
-18 -88 2 -57 67 -99 126 -79 80 27 121 293 72 462 -61 211 -239 389 -450 450
-77 23 -231 27 -314 10z"/>
<path d="M1220 1862 c-262 -31 -500 -207 -595 -440 l-23 -57 -59 -3 c-85 -4
-173 -27 -250 -64 -95 -46 -208 -159 -257 -255 l-36 -73 0 -194 c0 -192 1
-197 27 -253 15 -32 33 -64 40 -71 7 -7 13 -16 13 -20 0 -11 71 -84 121 -124
53 -44 150 -90 229 -109 78 -18 1564 -20 1660 -1 202 39 376 195 446 402 29
84 26 272 -5 360 -75 213 -244 355 -468 393 l-75 13 -23 55 c-72 177 -239 336
-420 399 -60 22 -72 25 -134 36 -38 7 -151 11 -191 6z m249 -211 c171 -59 294
-191 351 -375 27 -85 44 -97 152 -101 127 -6 219 -46 295 -128 133 -144 145
-359 29 -512 -57 -75 -104 -109 -193 -141 l-68 -24 -771 0 -770 0 -68 25
c-195 71 -299 256 -261 465 11 60 57 143 110 195 85 86 165 117 310 121 50 1
98 2 108 3 32 2 63 45 85 117 43 141 144 260 280 328 116 58 286 70 411 27z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

+19
View File
@@ -0,0 +1,19 @@
{
"name": "\u00d6ppet Moln",
"short_name": "\u00d6ppet Moln",
"icons": [
{
"src": "https://password.oppetmoln.se/favicon/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "https://password.oppetmoln.se/favicon/android-chrome-256x256.png",
"sizes": "256x256",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

+162
View File
@@ -0,0 +1,162 @@
<!DOCTYPE html>
<html lang="en" prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb#">
<head>
<meta charset="UTF-8">
<meta name="description" content="Random Password Generator" lang="en">
<meta name="description" content="Slumpmässigt Lösenord" lang="sv">
<meta name="description" content="Zufallsgenerator für Passwörter" lang="de">
<meta name="keywords" content="password generator,random password,lösenord,slumpmässigt lösenord,öppet moln,öppen källkod">
<meta name="author" content="Joaquim Homrighausen">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" type="image/png" href="favicon/favicon-32x32.png" />
<title lang="en">POMjs - Random Password Generator</title>
<title lang="sv">POMjs - Slumpmässigt Lösenord</title>
<title lang="de">POMjs - Zufallsgenerator für Passwörter</title>
<link media="all" rel="stylesheet" href="/css/normalize.min.css" />
<link media="all" rel="stylesheet" href="/css/password-om.css" />
<meta name="robots" content="index,nofollow">
<meta name="googlebot" content="index,nofollow,max-snippet:-1,max-image-preview:large,max-video-preview:-1">
<meta name="bingbot" content="index,nofollow,max-snippet:-1,max-image-preview:large,max-video-preview:-1">
<!--
You may, or may not, want to use these. If you put this up on your
own website, please be sure to change the fields accordingly,
thank you.
-->
<!--
<meta property="og:locale" content="en_US" />
<meta property="og:type" content="website" />
<meta property="og:title" content="POMjs - Random Password Generator" />
<meta property="og:description" content="Plain vanilla javascript random password generator" />
<meta property="og:image" content="favicon/pomjs-logo.png" />
<meta property="og:image:width" content="500" />
<meta property="og:image:type" content="image/png" />
<meta property="og:site_name" content="POMjs" />
<meta property="og:url" content="https://password.oppetmoln.se">
<meta name="twitter:card" content="summary_large_image" />
<meta property="twitter:creator" content="@oppetmoln" />
<meta property="twitter:site" content="@oppetmoln" />
<meta property="twitter:domain" content="POMjs" />
<meta property="twitter:url" content="https://password.oppetmoln.se" />
<meta name="twitter:title" content="POMjs - Random Password Generator" />
<meta name="twitter:description" content="Plain vanilla javascript random password generator" />
<meta name="twitter:image" content="favicon/pomjs-logo.png" />
-->
</head>
<!--
POMjs 1.00
Plain vanilla javascript for the "Öppet Moln" ("Open Cloud") random
password generator site (password.oppetmoln.se). For the sake of having
a name, it shall be POMjs. There's really nothing fancy going on here
:-)
Github repo: https://github.com/joho1968/POMjs
Copyright 2022 Joaquim Homrighausen; All rights reserved.
Development sponsored by WebbPlatsen i Sverige AB
https://www.webbplatsen.se
This file is part of POMjs. POMjs is free software.
You may redistribute it and/or modify it under the terms of the
GNU General Public License version 2, as published by the Free Software
Foundation.
POMjs is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with the POMjs package. If not, write to:
The Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor
Boston, MA 02110-1301, USA.
-->
<body>
<header>
<h1 id="cfg-page-title"></h1>
<h2 id="cfg-page-slogan"></h2>
<p id="cfg-page-lang"></p>
<noscript>
<p style="color:red;font-weight:bold;">This site requires Javascript support</p>
</noscript>
</header>
<main>
<div id="generator">
<div class="selection-row">
<div id="gen-uppercase" class="static-col"></div>
<div id="gen-uppercase-select" class="selection-col">
<input class="check-option" type="checkbox" name="mk-uppercase-select" id="mk-uppercase-select" tabindex="1" checked />
</div>
</div>
<div class="selection-row">
<div id="gen-lowercase" class="static-col"></div>
<div id="gen-lowercase-select" class="selection-col">
<input class="check-option" type="checkbox" name="mk-lowercase-select" id="mk-lowercase-select" tabindex="2" checked />
</div>
</div>
<div class="selection-row">
<div id="gen-digits" class="static-col"></div>
<div id="gen-digits-select" class="selection-col">
<input class="check-option" type="checkbox" name="mk-digits-select" id="mk-digits-select" tabindex="3" checked />
</div>
</div>
<div class="selection-row">
<div id="gen-special-one" class="static-col"></div>
<div id="gen-special-one-select" class="selection-col">
<input class="check-option" type="checkbox" name="mk-special-one-select" id="mk-special-one-select" tabindex="4" checked />
</div>
</div>
<div class="selection-row">
<div id="gen-special-two" class="static-col"></div>
<div id="gen-special-two-select" class="selection-col">
<input class="check-option" type="checkbox" name="mk-special-two-select" id="mk-special-two-select" tabindex="5" checked />
</div>
</div>
<div class="selection-row" id="mk-password-len-div">
<div id="gen-length" class="static-col">
<input oninput="document.getElementById('mk-length-field').value=this.value;" type="range" min="1" max="2" value="1" class="slider" step="4" name="mk-password-len-slider" id="mk-password-len-slider" tabindex="6" />
</div>
<div id="gen-length-field" class="selection-col">
<input type="text" inputmode="numeric" pattern="[0-9]{1,3}" size="3" maxlength="3" name="mk-length-field" id="mk-length-field" value="" tabindex="7" />
</div>
</div>
<div class="selection-row" id="mk-password-btn-div">
<div class="static-col"></div>
<div class="selection-col">
<button type="button" name="mk-password-btn" id="mk-password-btn" title="" tabindex="8">
&#8629;&nbsp;
</button>
</div>
</div>
<div id="mk-password-div">
<input type="text" size="40" maxlength="256" name="mk-password-field" id="mk-password-field" tabindex="9" readonly />
</div>
<div id="mk-password-good">
<div id="mk-password-strength">&nbsp;</div>
</div>
</div>
</main>
<footer>
<!--
You may, or may not, want to display this. If you put this up
on your own website, please be sure to change the content
accordingly, thank you.
-->
<!--
<p id="gen-hosted-by">Website hosted by <span style="display:inline-block"><a href="https://www.webbplatsen.se" target="_blank" tabindex="-1">WebbPlatsen i Sverige AB</a></span></p>
-->
<small>POMjs by Joaquim Homrighausen, <span style="display:inline-block">get it at <a href="https://github.com/joho1968/POMjs" target="_blank" tabindex="-1">GitHub</a> (GPLv2)</span></small>
<p id="gen-timestamp"></p>
</footer>
</body>
</html>
<script async src="/js/password-om.min.js" type="text/javascript" id="password-om"></script>
+399
View File
@@ -0,0 +1,399 @@
/**
* POMjs 1.00
*
* password-om.js
*
* Plain vanilla javascript for the "Öppet Moln" ("Open Cloud") random password
* generator site (password.oppetmoln.se). For the sake of having a name, it
* shall be POMjs. There's really nothing fancy going on here :-)
*
* Copyright 2022 Joaquim Homrighausen; All rights reserved.
* Development sponsored by WebbPlatsen i Sverige AB
* https://www.webbplatsen.se
*
* This file is part of POMjs. POMjs is free software.
*
* You may redistribute it and/or modify it under the terms of the
* GNU General Public License version 2, as published by the Free Software
* Foundation.
*
* POMjs is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with the POMjs package. If not, write to:
* The Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301, USA.
*/
/* Some globals, to be filled by script */
var POM_cfgLanguage = 'noLang?';
var POM_cfgTitle = 'noTitle?';
var POM_cfgSlogan = 'noSlogan?';
var POM_cfgGenPasswordHint = 'noHint?';
const POM_strUppercase = POM_genAlphabet(true);
const POM_strLowercase = POM_genAlphabet(false);
const POM_strDigits = POM_genDigits();
const POM_strSpecialOne = '-._#$@%!';
const POM_strSpecialTwo = '"+(){}[]?&,*<>|:;^';
/* Easy customization of defaults, etc */
const POM_strUppercase_Default = true;
const POM_strLowercase_Default = true;
const POM_strDigits_Default = true;
const POM_strSpecialOne_Default = true;
const POM_strSpecialTwo_Default = false;
const POM_mkPasswordOnLoad = true;
const POM_minLength = 16;
const POM_maxLength = 256;
const POM_sliderStep = 8;
const POM_debug = false;
/* Generate some strings */
function POM_genAlphabet(isUpper = false) {
return [...Array(26)].map((_, i) => String.fromCharCode(i + (isUpper ? 65 : 97))).join('');
}
function POM_genDigits() {
return [...Array(10)].map((_, i) => String.fromCharCode(i + 48)).join('');
}
/* Distill string down to unique characters by using a set */
function POM_distillString(s) {
s = s.split('');
s = new Set(s);
s = [...s].join('+');
return(s);
}
/* Escape special regex characters in string, from MDN */
function POM_escapeRegExp(s) {
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
/* Validate "manual input" */
function POM_validateNumInput() {
let mkLengthSlider = document.getElementById('mk-password-len-slider');
if (mkLengthSlider) {
if (this.value === '') {
this.value = POM_minLength;
}
mkLengthSlider.value = this.value;
if (mkLengthSlider.value < POM_minLength) {
mkLengthSlider.value = POM_minLength;
} else if (mkLengthSlider.value > POM_maxLength) {
mkLengthSlider.value = POM_maxLength;
}
this.value = mkLengthSlider.value;
}
}
/* Validate "manual input" */
function POM_generatePassword() {
let strengthP = document.getElementById('mk-password-strength');
strengthP.style.background = 'inherit';
strengthP.style.width = '0';
strengthP.style.transition = 'none';
let passwordField = document.getElementById('mk-password-field');
passwordField.value = '';
passwordField.classList.remove('mk-password-field-focus');
let mkLengthField = document.getElementById('mk-length-field');
if (POM_debug) {
console.clear();
}
if (mkLengthField) {
if (mkLengthField.value >= POM_minLength && mkLengthField.value <= POM_maxLength) {
let passwordSource = '';
if (document.getElementById('mk-uppercase-select').checked) {
passwordSource += POM_strUppercase;
}
if (document.getElementById('mk-special-one-select').checked) {
passwordSource += (POM_strSpecialOne + POM_strSpecialOne);
}
if (document.getElementById('mk-digits-select').checked) {
passwordSource += POM_strDigits;
}
if (document.getElementById('mk-lowercase-select').checked) {
passwordSource += POM_strLowercase;
}
if (document.getElementById('mk-digits-select').checked) {
passwordSource += POM_strDigits;
}
if (document.getElementById('mk-special-two-select').checked) {
passwordSource += (POM_strSpecialTwo + POM_strSpecialTwo);
}
if (passwordSource.length>0) {
let passwordGen = '';
let theChar = '';
for (let i = 0; i < mkLengthField.value; i++) {
const charPos = Math.floor(Math.random() * passwordSource.length);
theChar = passwordSource[charPos];
passwordGen += theChar;
}
passwordField.value = passwordGen;
let scoreP = 0;/* Password strength score, max is 8 */
let searchStr;
let re;
/* See if password contains uppercase characters */
searchStr = '[' + POM_escapeRegExp(POM_strUppercase) + ']';
if (POM_debug) {
console.log('Using ' + searchStr + ' to scan password');
}
re = new RegExp(searchStr);
if (re.test(passwordGen)) {
scoreP++;
if (POM_debug) {
console.log('Password contains UPPERCASE');
}
} else {
if (POM_debug) {
console.log('Password does NOT contain UPPERCASE');
}
}
/* See if password contains lowercase characters */
searchStr = '[' + POM_escapeRegExp(POM_strLowercase) + ']';
if (POM_debug) {
console.log('Using ' + searchStr + ' to scan password');
}
re = new RegExp(searchStr);
if (re.test(passwordGen)) {
scoreP++;
if (POM_debug) {
console.log('Password contains lowercase');
}
} else {
if (POM_debug) {
console.log('Password does NOT contain lowercase');
}
}
/* See if password contains digits characters */
searchStr = '[' + POM_escapeRegExp(POM_strDigits) + ']';
if (POM_debug) {
console.log('Using ' + searchStr + ' to scan password');
}
re = new RegExp(searchStr);
if (re.test(passwordGen)) {
scoreP++;
if (POM_debug) {
console.log('Password contains digits');
}
} else {
if (POM_debug) {
console.log('Password does NOT contain digits');
}
}
/* See if password contains specialOne characters */
searchStr = '[' + POM_escapeRegExp(POM_strSpecialOne) + ']';
if (POM_debug) {
console.log('Using ' + searchStr + ' to scan password');
}
re = new RegExp(searchStr);
if (re.test(passwordGen)) {
scoreP++;
if (POM_debug) {
console.log('Password contains specialOne');
}
} else {
if (POM_debug) {
console.log('Password does NOT contain specialOne');
}
}
/* See if password contains specialtwo characters */
searchStr = '[' + POM_escapeRegExp(POM_strSpecialTwo) + ']';
console.log('Using ' + searchStr + ' to scan password');
re = new RegExp(searchStr);
if (re.test(passwordGen)) {
scoreP++;
if (POM_debug) {
console.log('Password contains specialTwo');
}
} else {
if (POM_debug) {
console.log('Password does NOT contain specialTwo');
}
}
/* Bump score if password is > 7 characters */
if (passwordGen.length > 7) {
scoreP++;
if (POM_debug) {
console.log('Password >7 characters, buping score');
}
}
/* Bump score if password is > 15 characters */
if (passwordGen.length > 15) {
scoreP++;
if (POM_debug) {
console.log('Password >15 characters, buping score');
}
}
/* Bump score if password is > 31 characters */
if (passwordGen.length > 31) {
scoreP += 2;
if (POM_debug) {
console.log('Password >31 characters, buping score');
}
}
/* Bump score if password is > 63 characters */
if (passwordGen.length > 63) {
scoreP += 4;
if (POM_debug) {
console.log('Password >63 characters, buping score');
}
}
/* Let's not overflooooow */
if (scoreP > 8) {
scoreP = 8;
}
if (scoreP > 6) {
strengthP.style.background = '#27ce60';
} else if (scoreP > 5) {
strengthP.style.background = '#27ae60';
} else if (scoreP > 3) {
strengthP.style.background = '#FFC300';
} else {
strengthP.style.background = '#C0392B';
}
strengthP.style.width = (scoreP * 12.5) + '%';
strengthP.style.transition = 'width 0.3s ease-in';
}
}
}
}
/* Copy content of generated password field, if any, to clipboard */
function POM_copyPassword() {
let passwordField = document.getElementById('mk-password-field');
if (passwordField && passwordField.value.length > 0) {
if (navigator && navigator.clipboard && navigator.clipboard.writeText) {
/* Use "modern" method */
navigator.clipboard.writeText(passwordField.value).then(function() {
passwordField.classList.add('mk-password-field-focus');
}, function(e) {
alert("Could not copy text: " + e);
});
} else {
/* Use legacy method */
var theText = document.createElement('textarea');
theText.value = passwordField.value;
theText.setAttribute('readonly', '');
theText.style.position = 'absolute';
theText.style.top = '-6969px';
theText.style.left = '-6969px';
document.body.appendChild(theText);
theText.focus();
theText.select();
try {
var goodCopy = document.execCommand('copy');
if (goodCopy) {
passwordField.classList.add('mk-password-field-focus');
} else {
alert('That did not work');
}
} catch(e) {
alert('Could not copy text: ' + e.message);
}
document.body.removeChild(theText);
}
}
}
/* Initialize */
function POM_initialSetup() {
/* Setup, language strings, etc. Ugly, but it works :-) */
if (navigator.language) {
POM_cfgLanguage = navigator.language;
if (POM_debug) {
console.log("Language: " + POM_cfgLanguage);
}
let dashPos = POM_cfgLanguage.indexOf('-');
if (dashPos && dashPos>0) {
POM_cfgLanguage = POM_cfgLanguage.substring(0, dashPos);
}
POM_cfgLanguage = POM_cfgLanguage.toLowerCase();
} else {
POM_cfgLanguage = '???';
}
/* Add your translation here */
switch(POM_cfgLanguage) {
case 'sv':
case 'se':
POM_cfgTitle = 'Slumpmässigt Lösenord';
POM_cfgSlogan = 'Inga kakor, <span tyle="display:inline-block">ingen spårning.</span><br/>Bara lösenord.';
POM_cfgGenPasswordHint = 'Generera lösenord';
break;
case 'de':
/* Thank you Peter Hampf */
POM_cfgTitle = 'Zufallsgenerator für Passwörter';
POM_cfgSlogan = 'Keine Cookies, <span style="display:inline-block">keine Tracker.</span><br/>Nur Passwörter.';
POM_cfgGenPasswordHint = 'Passwort generieren';
break;
default:
POM_cfgTitle = 'Random Password Generator';
POM_cfgSlogan = 'No cookies, <span style="display:inline-block">no trackers.</span><br/>Just passwords.';
POM_cfgGenPasswordHint = 'Generate password';
break;
}
/* Paint "HTML" with language strings */
document.getElementById('cfg-page-title').innerHTML = POM_cfgTitle;
document.getElementById('cfg-page-slogan').innerHTML = POM_cfgSlogan;
document.getElementById('cfg-page-lang').innerHTML = '[' + POM_cfgLanguage + ']';
document.getElementById('mk-password-btn').title = POM_cfgGenPasswordHint;
/* Set reasonable defaults */
document.getElementById('mk-uppercase-select').checked = POM_strUppercase_Default;
document.getElementById('mk-lowercase-select').checked = POM_strLowercase_Default;
document.getElementById('mk-digits-select').checked = POM_strDigits_Default;
document.getElementById('mk-special-one-select').checked = POM_strSpecialOne_Default;
document.getElementById('mk-special-two-select').checked = POM_strSpecialTwo_Default;
document.getElementById('mk-password-field').value = '';
let mkPasswordSlider = document.getElementById('mk-password-len-slider');
if (mkPasswordSlider) {
mkPasswordSlider.value = POM_minLength;
mkPasswordSlider.setAttribute("min", POM_minLength);
mkPasswordSlider.setAttribute("max", POM_maxLength);
mkPasswordSlider.step = POM_sliderStep;
}
document.getElementById('mk-length-field').value = POM_minLength;
/* Paint "HTML" with password source */
document.getElementById("gen-uppercase").innerText = POM_strUppercase;
document.getElementById("gen-lowercase").innerText = POM_strLowercase;
document.getElementById("gen-digits").innerText = POM_strDigits;
document.getElementById("gen-special-one").innerText = POM_strSpecialOne;
document.getElementById("gen-special-two").innerText = POM_strSpecialTwo;
/* Add timestamp, for no good reason :) */
document.getElementById("gen-timestamp").innerText = Date.now();
/* Add some event handlers */
document.getElementById('mk-password-len-slider').addEventListener("oninput", function() {
let mkLengthField = document.getElementById('mk-length-field');
if (mkLengthField) {
mkLengthField.value = this.value;
if (mkLengthField.value < POM_minLength) {
mkLengthField.value = POM_minLength;
} else if (mkLengthField.value > POM_maxLength) {
mkLengthField.value = POM_maxLength;
}
this.value = mkLengthField.value;
}
});
document.getElementById('mk-length-field').addEventListener("click", function() {
this.select();
});
document.getElementById('mk-length-field').addEventListener("blur", POM_validateNumInput);
document.getElementById('mk-length-field').addEventListener("change", POM_validateNumInput);
document.getElementById('mk-password-btn').addEventListener("click", POM_generatePassword);
document.getElementById('mk-password-field').addEventListener("click", POM_copyPassword);
/* Possibly generate password on load */
if (POM_mkPasswordOnLoad) {
document.getElementById('mk-password-btn').click();
}
}
/* Wait for things to be loaded */
if (document.readyState === "complete" ||
(document.readyState !== "loading" && !document.documentElement.doScroll)) {
POM_initialSetup();
} else {
document.addEventListener("DOMContentLoaded", POM_initialSetup);
}
/* end of file "password-om.js" */
+1
View File
File diff suppressed because one or more lines are too long
+2
View File
@@ -0,0 +1,2 @@
User-agent: *
Disallow: /css
+19
View File
@@ -0,0 +1,19 @@
{
"name": "\u00d6ppet Moln",
"short_name": "\u00d6ppet Moln",
"icons": [
{
"src": "https://password.oppetmoln.se/favicon/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "https://password.oppetmoln.se/favicon/android-chrome-256x256.png",
"sizes": "256x256",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}