Lomiri
PasswordMeter.qml
1 /*
2  * Copyright (C) 2015 Canonical Ltd.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 3.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 import QtQuick 2.4
18 import Lomiri.Components 1.3
19 
20 Item {
21  property string password: ""
22  readonly property int passwordScore: scorePassword(password)
23  property var matching
24 
25  function scorePassword(pass) {
26  var score = 0;
27  if (!pass)
28  return score;
29 
30  // award every unique letter until 5 repetitions
31  var letters = Object();
32  for (var i=0; i<pass.length; i++) {
33  letters[pass[i]] = (letters[pass[i]] || 0) + 1;
34  score += 5.0 / letters[pass[i]];
35  }
36 
37  // bonus points for mixing it up
38  var variations = {
39  digits: /\d/.test(pass),
40  lower: /[a-z]/.test(pass),
41  upper: /[A-Z]/.test(pass),
42  nonWords: /\W/.test(pass),
43  }
44 
45  var variationCount = 0;
46  for (var check in variations) {
47  variationCount += (variations[check] === true) ? 1 : 0;
48  }
49  score += (variationCount - 1) * 10;
50 
51  return parseInt(score);
52  }
53 
54  Rectangle {
55  id: passwordStrengthMeter
56  anchors {
57  left: parent.left
58  right: parent.right
59  }
60  width: parent.width
61  height: units.gu(0.5)
62  color: {
63  if (passwordScore > 80)
64  return okColor;
65  else if (passwordScore > 60)
66  return "#f9c00f";
67  else if (passwordScore >= 30)
68  return errorColor;
69 
70  return errorColor;
71  }
72  visible: password.length > 0
73  }
74 
75  Label {
76  id: passwordStrengthInfo
77  anchors {
78  left: parent.left
79  right: parent.right
80  top: passwordStrengthMeter.bottom
81  topMargin: units.gu(.5)
82  }
83  wrapMode: Text.Wrap
84  text: {
85  if (matching !== undefined) {
86  if (password.length < 8)
87  return i18n.tr("Password too short");
88  else if (matching)
89  return i18n.tr("Passwords match");
90  else if (!matching)
91  return i18n.tr("Passwords do not match");
92  }
93 
94  if (passwordScore > 80)
95  return i18n.tr("Strong password");
96  else if (passwordScore > 60)
97  return i18n.tr("Fair password");
98  else if (passwordScore >= 30)
99  return i18n.tr("Weak password");
100 
101  return i18n.tr("Very weak password");
102  }
103  color: LomiriColors.ash
104  fontSize: "small"
105  font.weight: Font.Light
106  visible: password.length > 0
107  }
108 }