@@ -0,0 +1,205 @@
2+ * Copyright (C) 2015 Canonical, Ltd.
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.
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.
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/>.
18+import Ubuntu.Components 1.2
19+import ".." as LocalComponents
20+import "../../Components" as UnityComponents
23+ * See the main passwd-type page for an explanation of why we don't actually
24+ * directly set the password here.
27+LocalComponents.Page {
29+ objectName: "passwdSetPage"
30+ forwardButtonSourceComponent: forwardButton
32+ title: confirmPhase ? i18n.tr("Confirm password") : i18n.tr("Enter password")
33+ backButtonText: i18n.tr("Cancel")
35+ property alias password: passwordField.text
36+ readonly property int passwordScore: scorePassword(password)
37+ property bool confirmPhase: false
39+ // If we are entering this page, clear any saved password and get focus
40+ onEnabledChanged: if (enabled) password = ""
42+ Component.onCompleted: {
44+ passwordField.forceActiveFocus()
48+ root.password = password
54+ interval: UbuntuAnimation.SnapDuration
58+ passwordField.forceActiveFocus()
62+ function setError(text) {
64+ infoLabel.hasError = true
65+ infoLabel.text = text
69+ function setInfo(text) {
70+ infoLabel.hasError = false
72+ infoLabel.text = text
74+ infoLabel.text = i18n.tr("Enter at least 4 characters")
78+ function scorePassword(pass) {
83+ // award every unique letter until 5 repetitions
84+ var letters = Object();
85+ for (var i=0; i<pass.length; i++) {
86+ letters[pass[i]] = (letters[pass[i]] || 0) + 1;
87+ score += 5.0 / letters[pass[i]];
90+ // bonus points for mixing it up
92+ digits: /\d/.test(pass),
93+ lower: /[a-z]/.test(pass),
94+ upper: /[A-Z]/.test(pass),
95+ nonWords: /\W/.test(pass),
98+ var variationCount = 0;
99+ for (var check in variations) {
100+ variationCount += (variations[check] === true) ? 1 : 0;
102+ score += (variationCount - 1) * 10;
104+ return parseInt(score);
109+ anchors.fill: content
113+ property bool hasError: false
119+ color: hasError ? "#e14141": "#525252"
127+ top: infoLabel.bottom
128+ topMargin: units.gu(1)
130+ echoMode: TextInput.Password
133+ if (password !== root.password) {
134+ setError(i18n.tr("Passwords do not match"))
136+ setInfo(i18n.tr("Passwords match"))
143+ id: passwordStrengthMeter
147+ top: passwordField.bottom
148+ topMargin: units.gu(1)
153+ if (passwordScore > 80)
155+ if (passwordScore > 60)
157+ if (passwordScore >= 30)
162+ visible: password.length > 0
166+ id: passwordStrengthInfo
170+ top: passwordStrengthMeter.bottom
171+ topMargin: units.gu(1)
175+ if (passwordScore > 80)
176+ return i18n.tr("Strong password");
177+ else if (passwordScore > 60)
178+ return i18n.tr("Medium password")
179+ if (passwordScore >= 30)
180+ return i18n.tr("Weak password");
182+ return i18n.tr("Very weak password");
186+ font.weight: Font.Light
187+ visible: password.length > 0
193+ LocalComponents.StackButton {
194+ enabled: confirmPhase ? password === root.password : password.length >= 4 // TODO set more sensible restrictions for the length?
200+ passwdSetPage.confirm()