PageRenderTime 49ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/LockCrypt.Java/src/com/lime49/lockcrypt/FrmPWGen.java

#
Java | 507 lines | 483 code | 12 blank | 12 comment | 55 complexity | 8fcd24faa8fc972e68a5080f541c6ae2 MD5 | raw file
  1. package com.lime49.lockcrypt;
  2. import com.lime49.lockcrypt.ui.AbstractDialog;
  3. import com.lime49.lockcrypt.ui.GradientJPanel;
  4. import java.util.*;
  5. import javax.swing.*;
  6. import javax.swing.border.*;
  7. import java.awt.*;
  8. import java.awt.event.*;
  9. import java.awt.datatransfer.Clipboard;
  10. import java.awt.datatransfer.StringSelection;
  11. import java.security.NoSuchAlgorithmException;
  12. import java.net.URL;
  13. import java.security.SecureRandom;
  14. import java.text.MessageFormat;
  15. import javax.swing.event.ChangeEvent;
  16. import javax.swing.event.ChangeListener;
  17. import javax.swing.event.ListSelectionEvent;
  18. import javax.swing.event.ListSelectionListener;
  19. public class FrmPWGen extends AbstractDialog {
  20. private JButton btnGen, btnCopy, btnClose;
  21. private JList log;
  22. private DefaultListModel logModel;
  23. private JSpinner spnLength;
  24. private JCheckBox chkUppercase, chkLowercase, chkDigits, chkSpecial, chkBrackets, chkExtended, chkSpecialFormat;
  25. private JTextField txtSpecialFormat;
  26. private ResourceBundle lang;
  27. private Font boldFont;
  28. private String selectedPassword = "";
  29. private GradientJPanel pnlMaxEntropy, pnlSelectedEntropy;
  30. private JLabel lblMaxEntropyPWMeter, lblMaxEntropyBitStrength, lblSelectedEntropyPWMeter, lblSelectedEntropyBitStrength;
  31. private String DIGITS = "0123456789",
  32. LOWERCASE = "abcdefghijklmnopqrstuvwxyz",
  33. UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
  34. SPECIAL = "!\"£$€%^&*-_=+@#~?`/\\",
  35. BRACKETS = "()[]{}<>",
  36. EXTENDED;
  37. /**
  38. * Creates a Password Generator window, using the specified ResourceBundle for language strings
  39. * @param owner The parent dialog on which this dialog should be centered.
  40. * @param lang The ResourceBundle to use for languages
  41. */
  42. public FrmPWGen(JDialog owner, ResourceBundle lang) {
  43. super(owner, lang.getString("PWGEN"), true);
  44. this.init(lang);
  45. }
  46. /**
  47. * Creates a Password Generator window, using the specified ResourceBundle for language strings
  48. * @param owner The parent dialog on which this dialog should be centered.
  49. * @param lang The ResourceBundle to use for languages
  50. */
  51. public FrmPWGen(JFrame owner, ResourceBundle lang) {
  52. super(owner, lang.getString("PWGEN"), true);
  53. this.init(lang);
  54. }
  55. private void init(final ResourceBundle lang) {
  56. //TODO: move buttons to the bottom and add 'enable secure clipboard' checkbox
  57. this.lang = lang;
  58. StringBuffer buff = new StringBuffer(); // populate the extended characters list (mostly unprintable)
  59. for(int i=161;i<256;i++) {
  60. buff.append((char)i);
  61. }
  62. EXTENDED = buff.toString();
  63. KeyStroke escapeKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false);
  64. Action escapeAction = new AbstractAction() {
  65. // close the frame when the user presses escape
  66. public void actionPerformed(ActionEvent e) {
  67. thisDialog.dispose();
  68. }
  69. };
  70. this.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(escapeKeyStroke, "ESCAPE");
  71. this.getRootPane().getActionMap().put("ESCAPE", escapeAction);
  72. this.setLayout(new BorderLayout());
  73. this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
  74. JPanel content = new JPanel();
  75. content.setLayout(new BoxLayout(content, BoxLayout.PAGE_AXIS));
  76. content.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
  77. this.setContentPane(content);
  78. GridBagConstraints c = new GridBagConstraints();
  79. c.insets = Constants.GLOBALINSETS;
  80. c.weighty = 1;
  81. int curY = 0;
  82. JPanel boxLength = new JPanel();
  83. content.add(boxLength);
  84. boxLength.setLayout(new BoxLayout(boxLength, BoxLayout.LINE_AXIS));
  85. JLabel lblLength = new JLabel(lang.getString("LENGTH"));
  86. boldFont = lblLength.getFont().deriveFont(Font.BOLD);
  87. lblLength.setFont(boldFont);
  88. lblLength.setLabelFor(spnLength);
  89. lblLength.setDisplayedMnemonic('e');
  90. boxLength.add(Box.createHorizontalStrut(100));
  91. boxLength.add(lblLength);
  92. boxLength.add(Box.createHorizontalStrut(10));
  93. SpinnerModel spnModel = new SpinnerNumberModel(8,1,511,1);
  94. spnLength = new JSpinner(spnModel);
  95. spnLength.setPreferredSize(new Dimension(50,20));
  96. spnLength.setMaximumSize(new Dimension(80,20));
  97. spnLength.addChangeListener(new ChangeListener() {
  98. public void stateChanged(ChangeEvent e) {
  99. calculateMaxEntropy();
  100. }
  101. });
  102. boxLength.add(spnLength);
  103. boxLength.add(Box.createHorizontalGlue());
  104. JPanel pnlInclude = new JPanel(new GridLayout(0,2,3,3));
  105. pnlInclude.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), lang.getString("PWGEN_POSSIBLECHARS")));
  106. pnlInclude.setFont(boldFont);
  107. content.add(pnlInclude);
  108. EntropyChangeListener entropyChangeListener = new EntropyChangeListener();
  109. MessageFormat fmtUppercase = new MessageFormat(lang.getString("PWGEN_UPPERCASE"));
  110. chkUppercase = new JCheckBox(fmtUppercase.format(new Object [] {"A-Z"}));
  111. chkUppercase.setMnemonic('U');
  112. chkUppercase.setSelected(true);
  113. chkUppercase.addItemListener(entropyChangeListener);
  114. pnlInclude.add(chkUppercase);
  115. MessageFormat fmtDigits = new MessageFormat(lang.getString("PWGEN_DIGITS"));
  116. chkDigits = new JCheckBox(fmtDigits.format(new Object [] {"0-9"}));
  117. chkDigits.setMnemonic('D');
  118. chkDigits.setSelected(true);
  119. chkDigits.addItemListener(entropyChangeListener);
  120. pnlInclude.add(chkDigits);
  121. MessageFormat fmtLowercase = new MessageFormat(lang.getString("PWGEN_LOWERCASE"));
  122. chkLowercase = new JCheckBox(fmtLowercase.format(new Object [] {"a-z"}));
  123. chkLowercase.setMnemonic('L');
  124. chkLowercase.setSelected(true);
  125. chkLowercase.addItemListener(entropyChangeListener);
  126. pnlInclude.add(chkLowercase);
  127. MessageFormat fmtBrackets = new MessageFormat(lang.getString("PWGEN_BRACKETS"));
  128. chkBrackets = new JCheckBox(fmtBrackets.format(new Object [] {" {},[],(), <> "}));
  129. chkBrackets.setMnemonic('B');
  130. chkBrackets.addItemListener(entropyChangeListener);
  131. pnlInclude.add(chkBrackets);
  132. chkExtended = new JCheckBox(lang.getString("PWGEN_EXTENDED"));
  133. chkExtended.setMnemonic('H');
  134. chkExtended.addItemListener(entropyChangeListener);
  135. pnlInclude.add(chkExtended);
  136. MessageFormat fmtSpecial = new MessageFormat(lang.getString("PWGEN_SPECIAL"));
  137. chkSpecial = new JCheckBox(fmtSpecial.format(new Object [] {"!,\",£,$,%,^", lang.getString("ETC")}));
  138. chkSpecial.setMnemonic('S');
  139. chkSpecial.addItemListener(entropyChangeListener);
  140. pnlInclude.add(chkSpecial);
  141. JPanel pnlFormat = new JPanel(new GridBagLayout());
  142. curY = 0;
  143. pnlFormat.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), lang.getString("PWGEN_SPECIALFORMAT")));
  144. content.add(pnlFormat);
  145. chkSpecialFormat = new JCheckBox(lang.getString("PWGEN_SPECIALFORMAT"));
  146. chkSpecialFormat.setBorder(BorderFactory.createLineBorder(Color.black));
  147. chkSpecialFormat.addActionListener(new ActionListener() {
  148. public void actionPerformed(ActionEvent e) {
  149. if(chkSpecialFormat.isSelected()) {
  150. txtSpecialFormat.setEnabled(true);
  151. txtSpecialFormat.setBackground(Color.white);
  152. } else {
  153. txtSpecialFormat.setEnabled(false);
  154. txtSpecialFormat.setBackground(Color.getHSBColor(0f, 0f, 0.87f));
  155. }
  156. }
  157. });
  158. Utils.setgrid(c,curY,0,1,1,GridBagConstraints.NONE,GridBagConstraints.NORTHWEST,0.8);
  159. pnlFormat.add(chkSpecialFormat,c);
  160. JButton btnSpecialFormatInfo = new JButton("");
  161. final ResourceBundle bundle = lang;
  162. btnSpecialFormatInfo.setToolTipText(lang.getString("INFORMATION"));
  163. btnSpecialFormatInfo.addActionListener(new ActionListener() {
  164. public void actionPerformed(ActionEvent e) {
  165. FrmPWGenSpecialFormat frm = new FrmPWGenSpecialFormat(thisDialog, bundle);
  166. frm.setLocation(thisDialog.getX() + ((thisDialog.getWidth() - frm.getWidth())/2), thisDialog.getY() + ((thisDialog.getHeight() - frm.getHeight())/2));
  167. frm.setVisible(true);
  168. }
  169. });
  170. btnSpecialFormatInfo.setHorizontalAlignment(SwingConstants.LEFT);
  171. try {
  172. ImageIcon icoName = new ImageIcon();
  173. URL URLicon = this.getClass().getResource("images/bulb_16.png");
  174. icoName.setImage(Toolkit.getDefaultToolkit().getImage(URLicon));
  175. btnSpecialFormatInfo.setIcon(icoName);
  176. } catch(Exception e) { }
  177. Utils.setgrid(c,curY,1,1,1,GridBagConstraints.NONE,GridBagConstraints.NORTHEAST,0.2);
  178. pnlFormat.add(btnSpecialFormatInfo,c);
  179. curY++;
  180. txtSpecialFormat = new JTextField(30);
  181. txtSpecialFormat.setEnabled(false);
  182. txtSpecialFormat.setBackground(Color.getHSBColor(0f, 0f, 0.87f));
  183. Utils.setgrid(c,curY,0,2,1,GridBagConstraints.HORIZONTAL,GridBagConstraints.NORTHWEST,1);
  184. pnlFormat.add(txtSpecialFormat,c);
  185. curY++;
  186. Box pnlGeneratedPasswords = Box.createVerticalBox();
  187. pnlGeneratedPasswords.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), lang.getString("GENERATEDPASSWORDS")));
  188. content.add(pnlGeneratedPasswords);
  189. logModel = new DefaultListModel();
  190. log = new JList(logModel);
  191. log.addListSelectionListener(new ListSelectionListener() {
  192. public void valueChanged(ListSelectionEvent e) {
  193. if(!logModel.isEmpty()) {
  194. String selectedPassword = log.getSelectedValue().toString();
  195. int pwStrength = PWStrengthChecker.checkStrength(selectedPassword);
  196. lblSelectedEntropyPWMeter.setText(pwStrength+"% - "+PWStrengthChecker.getStrengthDescription(pwStrength, lang));
  197. PWStrengthChecker.setPanelGradient(pnlSelectedEntropy, pwStrength);
  198. lblSelectedEntropyBitStrength.setText(PWStrengthChecker.calculateBitStrength(selectedPassword)+" bits");
  199. }
  200. }
  201. });
  202. JScrollPane logScroll = new JScrollPane(log);
  203. log.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
  204. logScroll.setViewportBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
  205. logScroll.setBorder(BorderFactory.createEmptyBorder(3,3,3,3));
  206. pnlGeneratedPasswords.add(logScroll);
  207. JPanel pnlAnalysis = new JPanel(new GridBagLayout());
  208. pnlAnalysis.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), lang.getString("PWGEN_ANALYSIS")));
  209. JButton btnAnalysisInfo = new JButton("");
  210. btnAnalysisInfo.setToolTipText(lang.getString("INFORMATION"));
  211. btnAnalysisInfo.addActionListener(new ActionListener() {
  212. public void actionPerformed(ActionEvent e) {
  213. Utils.openURL("http://wiki.lime49.com/index.php?title=Password_Generator#Password_Analysis");
  214. }
  215. });
  216. btnAnalysisInfo.setHorizontalAlignment(SwingConstants.LEFT);
  217. try {
  218. ImageIcon icoName = new ImageIcon();
  219. URL URLicon = this.getClass().getResource("images/bulb_16.png");
  220. icoName.setImage(Toolkit.getDefaultToolkit().getImage(URLicon));
  221. btnAnalysisInfo.setIcon(icoName);
  222. } catch(Exception e) { }
  223. JLabel lblMaxEntropy = new JLabel(lang.getString("PWGEN_MAXENTROPY"));
  224. pnlMaxEntropy = new GradientJPanel(new BorderLayout());
  225. lblMaxEntropyPWMeter = new JLabel("");
  226. lblMaxEntropyBitStrength = new JLabel("");
  227. pnlMaxEntropy.setBorder(BorderFactory.createLineBorder(Color.black));
  228. JLabel lblSelectedEntropy = new JLabel(lang.getString("PWGEN_ENTROPYSELECTED"));
  229. pnlSelectedEntropy = new GradientJPanel(new BorderLayout());
  230. curY++;
  231. lblSelectedEntropyPWMeter = new JLabel(lang.getString("NONESELECTED"));
  232. lblSelectedEntropyBitStrength = new JLabel("");
  233. pnlSelectedEntropy.setBorder(BorderFactory.createLineBorder(Color.black));
  234. calculateMaxEntropy();
  235. content.add(pnlAnalysis);
  236. curY = 0;
  237. Utils.setgrid(c,curY,1,1,1,GridBagConstraints.NONE,GridBagConstraints.NORTHEAST,1);
  238. pnlAnalysis.add(btnAnalysisInfo,c);
  239. curY++;
  240. Utils.setgrid(c,curY,0,1,1,GridBagConstraints.NONE,GridBagConstraints.NORTHWEST,0.5);
  241. pnlAnalysis.add(lblMaxEntropy,c);
  242. Utils.setgrid(c,curY,1,1,1,GridBagConstraints.HORIZONTAL,GridBagConstraints.NORTHEAST,1);
  243. pnlAnalysis.add(pnlMaxEntropy,c);
  244. pnlMaxEntropy.add(lblMaxEntropyPWMeter, BorderLayout.LINE_START);
  245. pnlMaxEntropy.add(lblMaxEntropyBitStrength, BorderLayout.LINE_END);
  246. curY++;
  247. Utils.setgrid(c,curY,0,1,1,GridBagConstraints.NONE,GridBagConstraints.NORTHWEST,0.5);
  248. pnlAnalysis.add(lblSelectedEntropy,c);
  249. Utils.setgrid(c,curY,1,1,1,GridBagConstraints.HORIZONTAL,GridBagConstraints.NORTHEAST,1);
  250. pnlAnalysis.add(pnlSelectedEntropy,c);
  251. pnlSelectedEntropy.add(lblSelectedEntropyPWMeter, BorderLayout.LINE_START);
  252. pnlSelectedEntropy.add(lblSelectedEntropyBitStrength, BorderLayout.LINE_END);
  253. JPanel pnlButtons = new JPanel(new FlowLayout(FlowLayout.TRAILING));
  254. content.add(pnlButtons);
  255. pnlButtons.add(Box.createHorizontalGlue());
  256. btnGen = new JButton(lang.getString("PWGEN_GENERATE"));
  257. btnGen.setMnemonic('G');
  258. btnGen.addActionListener(new ActionListener() {
  259. public void actionPerformed(ActionEvent e) { genPass(); }
  260. });
  261. btnGen.setMinimumSize(Constants.MINSIZE);
  262. btnGen.setMaximumSize(Constants.MAXSIZE);
  263. pnlButtons.add(btnGen);
  264. pnlButtons.add(Box.createHorizontalStrut(10));
  265. btnCopy = new JButton(lang.getString("COPY"));
  266. btnCopy.setMnemonic('C');
  267. btnCopy.addActionListener(new ActionListener() {
  268. public void actionPerformed(ActionEvent e) { copyToClip(); }
  269. });
  270. btnCopy.setMinimumSize(Constants.MINSIZE);
  271. btnCopy.setMaximumSize(Constants.MAXSIZE);
  272. pnlButtons.add(btnCopy);
  273. pnlButtons.add(Box.createHorizontalStrut(10));
  274. btnClose = new JButton(lang.getString("OK"));
  275. btnClose.addActionListener(new ActionListener() {
  276. public void actionPerformed(ActionEvent e) {
  277. selectedPassword = log.getSelectedValue() == null ? "" : log.getSelectedValue().toString();
  278. thisDialog.dispose();
  279. }
  280. });
  281. btnClose.setMinimumSize(Constants.MINSIZE);
  282. btnClose.setMaximumSize(Constants.MAXSIZE);
  283. pnlButtons.add(btnClose);
  284. this.setMinimumSize(new Dimension(500,400));
  285. this.pack();
  286. }
  287. /**
  288. * Generates a password according to the selected checkboxes and length spinner
  289. */
  290. private void genPass() {
  291. if(ValidateInput()) {
  292. int passLength = (Integer)spnLength.getValue();
  293. StringBuffer chars = new StringBuffer();
  294. if(chkUppercase.isSelected()) {
  295. chars.append(UPPERCASE);
  296. }
  297. if(chkLowercase.isSelected()) {
  298. chars.append(LOWERCASE);
  299. }
  300. if(chkDigits.isSelected()) {
  301. chars.append(DIGITS);
  302. }
  303. if(chkSpecial.isSelected()) {
  304. chars.append(SPECIAL);
  305. }
  306. if(chkBrackets.isSelected()) {
  307. chars.append(BRACKETS);
  308. }
  309. if(chkExtended.isSelected()) { // 161-255
  310. chars.append(EXTENDED);
  311. }
  312. char[] possChars = chars.toString().toCharArray();
  313. int numPossChars = possChars.length;
  314. Random seed = null;
  315. try {
  316. seed = SecureRandom.getInstance("SHA1PRNG");
  317. } catch(NoSuchAlgorithmException e) {
  318. System.out.println("SHA1PRNG algorithm not found, using standard random generator");
  319. seed = new Random();
  320. }
  321. // Fisher-Yates shuffle
  322. for(int i=numPossChars-1;i>0;i--) {
  323. int pos = seed.nextInt(i);
  324. char temp = possChars[i];
  325. possChars[i] = possChars[pos];
  326. possChars[pos] = temp;
  327. }
  328. if(Constants.DEBUG) {
  329. System.out.println(possChars);
  330. }
  331. char[] pass = new char[passLength];
  332. if(chkSpecialFormat.isSelected()) {
  333. String format = txtSpecialFormat.getText();
  334. int i=0;
  335. while(i<passLength) {
  336. char proposed = possChars[seed.nextInt(numPossChars)];
  337. if(format.length() > i) {
  338. switch(format.charAt(i)) {
  339. case 'd':
  340. if(DIGITS.indexOf(proposed) >=0) {
  341. pass[i] = proposed;
  342. i++;
  343. }
  344. break;
  345. case 'c':
  346. if(LOWERCASE.indexOf(proposed) >=0) {
  347. pass[i] = proposed;
  348. i++;
  349. }
  350. break;
  351. case 'C':
  352. if(UPPERCASE.indexOf(proposed) >=0) {
  353. pass[i] = proposed;
  354. i++;
  355. }
  356. break;
  357. case 'b':
  358. if(BRACKETS.indexOf(proposed) >=0) {
  359. pass[i] = proposed;
  360. i++;
  361. }
  362. break;
  363. case 's':
  364. if(SPECIAL.indexOf(proposed) >=0) {
  365. pass[i] = proposed;
  366. i++;
  367. }
  368. break;
  369. case 'e':
  370. if(EXTENDED.indexOf(proposed) >=0) {
  371. pass[i] = proposed;
  372. i++;
  373. }
  374. default:
  375. pass[i] = proposed;
  376. i++;
  377. break;
  378. }
  379. } else {
  380. pass[i] = proposed;
  381. i++;
  382. }
  383. }
  384. } else {
  385. for(int i=0;i<passLength;i++) {
  386. pass[i] = possChars[seed.nextInt(numPossChars)];
  387. }
  388. }
  389. logModel.addElement(new String(pass));
  390. log.setSelectedIndex(logModel.getSize()-1);
  391. log.ensureIndexIsVisible(logModel.getSize()-1);
  392. }
  393. }
  394. private void calculateMaxEntropy() {
  395. int poolsize = 0;
  396. if(chkUppercase.isSelected()) {
  397. poolsize += 26;
  398. }
  399. if(chkLowercase.isSelected()) {
  400. poolsize += 26;
  401. }
  402. if(chkDigits.isSelected()) {
  403. poolsize += 10;
  404. }
  405. if(chkSpecial.isSelected()) {
  406. poolsize += 20;
  407. }
  408. if(chkBrackets.isSelected()) {
  409. poolsize += 8;
  410. }
  411. if(chkExtended.isSelected()) { // 161-255
  412. poolsize += 94;
  413. }
  414. double bitStrength = Math.log(Math.pow(poolsize, (Integer)spnLength.getValue())) / Math.log(2);
  415. int score = (int)((double)poolsize/184*100);
  416. lblMaxEntropyPWMeter.setText(score+"% - "+PWStrengthChecker.getStrengthDescription(score, lang));
  417. lblMaxEntropyBitStrength.setText((int)Math.round(bitStrength)+" bits");
  418. PWStrengthChecker.setPanelGradient(pnlMaxEntropy, score);
  419. lblMaxEntropyPWMeter.invalidate();
  420. lblMaxEntropyPWMeter.repaint();
  421. lblMaxEntropyPWMeter.revalidate();
  422. }
  423. private boolean ValidateInput() {
  424. boolean havePossible = false;
  425. if(chkSpecialFormat.isSelected()) {
  426. String format = txtSpecialFormat.getText();
  427. boolean haveDigits = (format.indexOf('d') >= 0),
  428. haveLowercase = (format.indexOf('c') >= 0),
  429. haveUppercase = (format.indexOf('C') >= 0),
  430. haveBrackets = (format.indexOf('b') >= 0),
  431. haveSpecial = (format.indexOf('s') >= 0),
  432. haveExtended = (format.indexOf('e') >= 0),
  433. haveAny = (format.indexOf('*') >= 0);
  434. if(format.length() > 0) {
  435. if(haveAny) {
  436. havePossible = true;
  437. } else {
  438. if(chkDigits.isSelected() && haveDigits) {
  439. havePossible = true;
  440. } else if(chkLowercase.isSelected() && haveLowercase) {
  441. havePossible = true;
  442. } else if(chkUppercase.isSelected() && haveUppercase) {
  443. havePossible = true;
  444. } else if(chkBrackets.isSelected() && haveBrackets) {
  445. havePossible = true;
  446. } else if(chkSpecial.isSelected() && haveSpecial) {
  447. havePossible = true;
  448. } else if(chkExtended.isSelected() && haveExtended) {
  449. havePossible = true;
  450. }
  451. }
  452. }
  453. if(!havePossible) {
  454. JOptionPane.showMessageDialog(this, lang.getString("ERR_PWGEN_NOELIGIBLEFORMAT"), lang.getString("ERROR"), JOptionPane.ERROR_MESSAGE);
  455. }
  456. } else {
  457. if(chkDigits.isSelected() || chkLowercase.isSelected()|| chkUppercase.isSelected()|| chkBrackets.isSelected() || chkSpecial.isSelected() || chkExtended.isSelected()) {
  458. havePossible = true;
  459. } else {
  460. JOptionPane.showMessageDialog(this, lang.getString("ERR_PWGEN_NOELIGIBLE"), lang.getString("ERROR"), JOptionPane.ERROR_MESSAGE);
  461. }
  462. }
  463. return havePossible;
  464. }
  465. /**
  466. * Returns the selected password, or an empty string if none is selected
  467. * @return The selected password, or an empty string if none is selected
  468. */
  469. public String getSelectedPassword() {
  470. return selectedPassword;
  471. }
  472. /**
  473. * Copys the selected password to the clipboard
  474. */
  475. private void copyToClip() {
  476. //TODO: add secure clipboard, disable button when list empty
  477. Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
  478. clipboard.setContents(new StringSelection((String)log.getSelectedValue()), null);
  479. }
  480. private class EntropyChangeListener implements ItemListener {
  481. public void itemStateChanged(ItemEvent e) {
  482. calculateMaxEntropy();
  483. }
  484. }
  485. }