Lors d’un de mes précédents billets, j’avais expliqué brièvement comment réaliser une application pour l’environnement GNOME avec Glade et l’API java-gnome. Pour cela, nous avions réalisé une application très simple avec un bouton et un label. Aujourd’hui nous allons construire une application complète et vraiment “utile”. Pour ne pas trop compliquer ce billet, j’ai décidé donc que nous allions faire un générateur de mot de passe dont l’algorithme n’est pas très complexe. Voyons ceci dès maintenant.
1 - Utilisation de java-gnome
Je ne vais pas redétailler cette partie, si certain l’on raté, l’explication est dans ce billet.
2 - Le projet
J’utilise Eclipse pour mes projets en Java depuis mes débuts. Je vous propose donc de l’utiliser aussi. Voici l’arborescence du projet après fin du code.
Vu que je ne vais pas détailler chaque partie de mon code je vous propose le téléchargement du projet directement grâce au fichier PasswordGenerator.tar.bz2.
3 - Algorithme du générateur de mot de passe
L’algorithme que l’on va utiliser pour générer le mot de passe n’est pas très complexe à comprendre. Le but est de sélectionner un caractère aléatoirement dans une liste et de l’ajouter à la chaîne de caractères composant le mot de passe. On veut que le mot de passe soit un minimum modifiable, par conséquent, on va pouvoir via notre interface GTK+ sélectionner les types de caractères que l’on souhaite. On en distingue 4 :
- les majuscules,
- les minusucules,
- les chiffres,
- les caractères spéciaux.
Pour pouvoir réaliser ceci, on ne va donc pas se contenter d’une seule liste réunissant tout l’ensemble mais de 4 listes (en réalité des chaînes de caractères pour ne pas se compliquer la tâche) bien distinctes comportant chacune un type de caractères. Chose important, le nombre aléatoire que l’on va obtenir ne doit pas dépasser la taille de la liste. C’est à dire que si la liste comporte 26 caractères, il ne faut pas tomber sur un nombre supérieur à 26. Pour cela, on va réaliser notre propre méthode de génération de nombre aléatoire en utilisant ce que l’API nous offre déjà. Ce n’est pas très complexe, je vous laisse regarder le contenu du package nommé random.
Maintenant, voici l’en-tête de notre méthode de génération du mot de passe.
public static String randomPassword(int length, boolean[] use)
Le premier argument, length, qui est un entier, correspond à la taille du mot de passe donc au nombre de caractères qu’il contiendra. Le deuxième argument est un tableau de booléens. Plus précisément, un tableau de 4 booléens qui va nous permettre de savoir quoi mettre dans le mot de passe. Le premier booléen correspond aux chiffres, le deuxième aux majuscules, le troisième aux minuscules et le dernier aux caractères spéciaux.
StringBuilder password = new StringBuilder();
String lowerChar = "azertyuiopqsdfghjklmwxcvbn";
String upperChar = "AZERTYUIOPQSDFGHJKLMWXCVBN";
String digits = "0123456789";
String specialChar = "&~#{([-|_\\^@)]=}$%*!:/;.?,<> ";
Voici les suites de caractères à utiliser ainsi que la déclaration de la chaîne password qui va contenir le mot de passe. On utilise un StringBuilder et non un String basique car il va y avoir plusieurs opérations d’ajout d’un seul caractère c’est donc beaucoup plus propre de le faire ainsi que par des concaténation de chaînes.
for (int i = 0; i < length; i++) {
int rnd = -1;
int charSet = Random.nextInt(4);
if (!use[charSet]) {
i--;
continue;
}
...
}
Voici la boucle qui va générer le mot de passe. On initialise une variable qui s’incrémentera jusqu’à obtenir la valeur de la taille du mot de passe voulue. L’entier nommé rnd correspond à la valeur du nombre aléatoire utilisé pour choisir le caractère et l’entier nommé charSet va servir à sélectionner le type de caractères à utiliser. Ici un nombre entier compris entre 0 et 3 (inclus, le 4 est exclu). Le test avec la condition (!use[charSet]) permet de ne pas utiliser un type de caractères dans le cas ou on n’en voudrait pas. En gros, si la variable charSet prend une valeur qui permettra de sélectionner les chiffres mais que l’on ne veut pas de chiffres, le on rentrera dans le if qui va décrémenter i (pour annuler “l’effet” de l’itération) et lancer une nouvelle itération avec le mot-clé continue.
switch (charSet) {
case 0:
rnd = Random.nextInt(digits.length());
password.append(digits.charAt(rnd));
break;
Ici, selon le type de caractères, on va sélectionner le caractère qui va bien et l’ajouter dans le mot de passe. Pour cela, on choisit un nombre compris entre 0 et la taille de la chaîne contenant le caractère puis on l’ajoute. Le case 0 correspond au cas des chiffres, on retrouve d’autres case pour les majuscules, minuscules et caractères spéciaux.
Enfin, après avoir itérer autant qu’il a fallut, on retourne le mot de passe sous forme de String. Rappelez-vous dans notre en-tête de méthode, on a bien spécifier que notre méthode retournait une variable de type String.
return password.toString();
Vous pouvez retrouver tout ce code (en entier c’est mieux) dans le fichier Password.java.
4 - Réalisation de l’interface GTK+
Pour ce qui est du design même de l’interface, on ne va pas s’embêter et on va utiliser Glade, un outil dans j’ai parlé plusieurs fois et qui permet de réaliser très simplement son interface. Pour ce qui est de la fenêtre que l’on va faire on va gagner du temps et utiliser directement une boîte de dialogue qui comporte déjà 2 parties utiles. A savoir, une partie vide ainsi que une spécialement faite pour y mettre des boutons. Réalisons donc une interface ressemblant à ceci, avec une arborescence identique à celle proposée sur l’image ci-dessous. Le fichier Glade est disponible dans l’archive et se nomme PasswordGenerator.glade.

Une fois l’interface réalisé, il faut maintenant l’exploiter avec le code Java et lui faire réaliser les actions que l’on souhaite. Tout d’abord, qu’est-ce que l’on voit sur cette interface GTK+ ? On remarque qu’il y a 4 checkboxs correspondant à l’utilisation (case cochée, par défaut) ou non (case décochée) des types de caractères. On voit aussi une barre pour choisir la taille du mot de passe (valeur par défaut 8). On sait tous qu’un vrai mot de passe se compose d’au moins 8 caractères avec alternance majuscules, minuscules, chiffres et caractères spéciaux. Enfin, il y a 3 boutons, un bouton Quitter (qui veut tout dire), un Actualiser qui va permettre de générer le mot de passe (qui se situera dans la champ de texte) et un bouton Copier pour copier le mot de passe dans le presse-papier. Tous ces boutons sont des boutons “basiques” dont l’icône, le label et le mnemonic sont déjà définis. Nous allons donc voir seulement les actions associées à ses boutons pour le reste il vous suffira de voir le code ce n’est pas très complexe et il y a des commentaires.
Commençons par le bouton Quitter. Ce dernier a pour effet de terminer le programme. Voilà comment on code ceci.
// Exit button
Button exitButton = (Button) _glade.getWidget("exit_button");
exitButton.connect(new Button.Clicked() {
@Override
public void onClicked(Button source) {
Gtk.mainQuit();
}
});
On récupère l’élément bouton et au clic sur ce bouton on applique l’action Gtk.mainQuit() qui termine la boucle lancée par Gtk.main().
Après ceci, occupons-nous du bouton Actualiser qui lancera la génération du mot de passe. Idem on récupère le bouton mais au clic on lui applique une autre méthode que l’on a créé auparavant.
// Refresh button
Button applyButton = (Button) _glade.getWidget("apply_button");
applyButton.connect(new Button.Clicked() {
@Override
public void onClicked(Button source) {
GtkInterface.this.generatePassword();
}
});
La méthode generatePassword() va elle vraiment se charger de récupérer un mot de passe et d’actualiser le champ de texte de l’interface.
private void generatePassword() {
boolean[] checks = { _digitCheck.getActive(), _upperCheck.getActive(),
_lowerCheck.getActive(), _specialCheck.getActive() };
int length = (int) _lengthScale.getValue();
if (!checks[0] && !checks[1] && !checks[2] && !checks[3])
this.errorDialog(Languages.ERROR, Languages.CHECKBOX_ERROR);
else {
String password = Password.randomPassword(length, checks);
_passwordEntry.setText(password);
}
}
On récupère la longueur du mot de passe. Et là un test, si on a décoché toutes les cases, on signale une erreur à l’utilisateur via une fenêtre spéciale appelée par la méthode errorDialog(String title, String text).
Pour finir, on définit l’action du bouton Copier. On va bien entendu copier le mot de passe dans le presse-papier dans le but de le coller plus tard bien entendu.
// Copy button
Button copyButton = (Button) _glade.getWidget("copy_button");
copyButton.connect(new Button.Clicked() {
@Override
public void onClicked(Button source) {
GtkInterface.this.copyToClipboard(_passwordEntry.getText());
}
});
C’est la méthode copyToClipboard(String text) qui va copier le contenu du champ texte dans le presse-papier si bien entendu l’environnement le supporte mais ça ne devrait pas poser de problème. Voici le contenu de cette méthode.
private void copyToClipboard(String password) {
try {
StringSelection selection = new StringSelection(
password == null ? "" : password);
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(
selection, null);
} catch (IllegalStateException e) {
this.errorDialog(Languages.ERROR, Languages.COPY_ERROR);
}
}
N’oubliez pas surtout de regarder tous les autres fichiers pour comprendre le code et tous les appels de méthodes. Et normalement, après compilation (via le script Ant), Il ne reste qu’à dézipper le fichier .zip généré, donner les droits d’exécution au script shell et le lancer (on peut aussi utiliser le Run de Eclipse). Après tout ceci, on obtient notre joli générateur de mot de passe sans aucun problème.
Si vous avez des questions, besoin de plus d’explication, n’hésitez pas à demander.