View Javadoc
1   /*
2    * DavMail POP/IMAP/SMTP/CalDav/LDAP Exchange Gateway
3    * Copyright (C) 2010  Mickael Guessant
4    *
5    * This program is free software; you can redistribute it and/or
6    * modify it under the terms of the GNU General Public License
7    * as published by the Free Software Foundation; either version 2
8    * of the License, or (at your option) any later version.
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License
16   * along with this program; if not, write to the Free Software
17   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18   */
19  
20  package davmail.exchange.auth;
21  
22  import davmail.BundleMessage;
23  import davmail.ui.browser.DesktopBrowser;
24  import davmail.ui.tray.DavGatewayTray;
25  
26  import javax.swing.*;
27  import javax.swing.event.HyperlinkEvent;
28  import javax.swing.text.html.HTMLEditorKit;
29  import javax.swing.text.html.StyleSheet;
30  import java.awt.*;
31  import java.net.URISyntaxException;
32  import java.awt.datatransfer.Clipboard;
33  import java.awt.datatransfer.StringSelection;
34  
35  public class O365ManualAuthenticatorDialog extends JDialog {
36      final JTextField codeField = new JTextField(30);
37      protected String code;
38  
39      /**
40       * Get Oauth authentication code.
41       *
42       * @return authentication code
43       */
44      public String getCode() {
45          if (code != null && code.contains("code=") && code.contains("&session_state=")) {
46              code = code.substring(code.indexOf("code=")+5, code.indexOf("&session_state="));
47          }
48          return code;
49      }
50  
51      /**
52       * Get credentials.
53       *
54       * @param initUrl Kerberos prompt from callback handler
55       */
56      public O365ManualAuthenticatorDialog(String initUrl) {
57          setAlwaysOnTop(true);
58  
59          setTitle(BundleMessage.format("UI_O365_MANUAL_PROMPT"));
60  
61          try {
62              setIconImages(DavGatewayTray.getFrameIcons());
63          } catch (NoSuchMethodError error) {
64              DavGatewayTray.debug(new BundleMessage("LOG_UNABLE_TO_SET_ICON_IMAGE"));
65          }
66  
67          JPanel messagePanel = new JPanel();
68          messagePanel.setLayout(new BoxLayout(messagePanel, BoxLayout.X_AXIS));
69  
70          JLabel imageLabel = new JLabel();
71          imageLabel.setIcon(UIManager.getIcon("OptionPane.questionIcon"));
72          messagePanel.add(imageLabel);
73  
74          messagePanel.add(getEditorPane(BundleMessage.format("UI_0365_AUTHENTICATION_PROMPT", initUrl)));
75  
76  
77          JPanel credentialPanel = new JPanel();
78          credentialPanel.setLayout(new BoxLayout(credentialPanel, BoxLayout.X_AXIS));
79  
80          JLabel promptLabel = new JLabel(BundleMessage.format("UI_0365_AUTHENTICATION_CODE"));
81          promptLabel.setHorizontalAlignment(SwingConstants.RIGHT);
82          promptLabel.setVerticalAlignment(SwingConstants.CENTER);
83  
84          credentialPanel.add(promptLabel);
85  
86          codeField.setMaximumSize(codeField.getPreferredSize());
87          addContextMenu(codeField);
88          codeField.addActionListener(evt -> {
89              code = codeField.getText();
90              setVisible(false);
91          });
92          credentialPanel.add(codeField);
93  
94          JPanel centerPanel = new JPanel();
95          centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.Y_AXIS));
96          centerPanel.add(messagePanel);
97          centerPanel.add(getOpenButtonPanel(initUrl));
98          centerPanel.add(getEditorPane(BundleMessage.format("UI_0365_AUTHENTICATION_CODE_PROMPT")));
99          centerPanel.add(credentialPanel);
100         centerPanel.add(Box.createVerticalGlue());
101 
102         //add(messagePanel, BorderLayout.NORTH);
103         add(centerPanel, BorderLayout.CENTER);
104         add(getSendButtonPanel(), BorderLayout.SOUTH);
105         setModal(true);
106 
107         pack();
108         // center frame
109         setLocation(getToolkit().getScreenSize().width / 2 -
110                         getSize().width / 2,
111                 getToolkit().getScreenSize().height / 2 -
112                         getSize().height / 2);
113         setAlwaysOnTop(true);
114         setVisible(true);
115     }
116 
117     private void addContextMenu(final JTextField textField) {
118         JPopupMenu popupMenu = new JPopupMenu();
119 
120         JMenuItem cutItem = new JMenuItem(BundleMessage.format("UI_MENU_CUT"));
121         cutItem.addActionListener(evt -> textField.cut());
122         popupMenu.add(cutItem);
123 
124         JMenuItem copyItem = new JMenuItem(BundleMessage.format("UI_MENU_COPY"));
125         copyItem.addActionListener(evt -> textField.copy());
126         popupMenu.add(copyItem);
127 
128         JMenuItem pasteItem = new JMenuItem(BundleMessage.format("UI_MENU_PASTE"));
129         pasteItem.addActionListener(evt -> textField.paste());
130         popupMenu.add(pasteItem);
131 
132         popupMenu.addSeparator();
133 
134         JMenuItem selectAllItem = new JMenuItem(BundleMessage.format("UI_MENU_SELECT_ALL"));
135         selectAllItem.addActionListener(evt -> textField.selectAll());
136         popupMenu.add(selectAllItem);
137 
138         textField.setComponentPopupMenu(popupMenu);
139     }
140 
141     private JEditorPane getEditorPane(String text) {
142         JEditorPane jEditorPane = new JEditorPane();
143         HTMLEditorKit htmlEditorKit = new HTMLEditorKit();
144         StyleSheet stylesheet = htmlEditorKit.getStyleSheet();
145         Font font = jEditorPane.getFont();
146         stylesheet.addRule("body { font-size:small;font-family: " + ((font==null)?"Arial":font.getFamily()) + '}');
147         jEditorPane.setEditorKit(htmlEditorKit);
148         jEditorPane.setContentType("text/html");
149         jEditorPane.setText(text);
150 
151         jEditorPane.setEditable(false);
152         jEditorPane.setOpaque(false);
153         jEditorPane.addHyperlinkListener(hle -> {
154             if (HyperlinkEvent.EventType.ACTIVATED.equals(hle.getEventType())) {
155                 try {
156                     DesktopBrowser.browse(hle.getURL().toURI());
157                 } catch (URISyntaxException e) {
158                     DavGatewayTray.error(new BundleMessage("LOG_UNABLE_TO_OPEN_LINK"), e);
159                 }
160             }
161         });
162         return jEditorPane;
163     }
164 
165     protected JPanel getOpenButtonPanel(final String initUrl) {
166         JPanel buttonPanel = new JPanel();
167         JButton openButton = new JButton(BundleMessage.format("UI_BUTTON_OPEN"));
168         JButton copyButton = new JButton(BundleMessage.format("UI_BUTTON_COPY"));
169         openButton.addActionListener(evt -> DesktopBrowser.browse(initUrl));
170         copyButton.addActionListener(evt -> {
171             Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
172             clipboard.setContents(new StringSelection(initUrl), null);
173         });
174 
175         buttonPanel.add(openButton);
176         buttonPanel.add(copyButton);
177         return buttonPanel;
178     }
179 
180     protected JPanel getSendButtonPanel() {
181         JPanel buttonPanel = new JPanel();
182         JButton sendButton = new JButton(BundleMessage.format("UI_BUTTON_SEND"));
183         JButton cancelButton = new JButton(BundleMessage.format("UI_BUTTON_CANCEL"));
184         sendButton.addActionListener(evt -> {
185             code = codeField.getText();
186             setVisible(false);
187         });
188         cancelButton.addActionListener(evt -> {
189             code = null;
190             setVisible(false);
191         });
192 
193         buttonPanel.add(sendButton);
194         buttonPanel.add(cancelButton);
195         return buttonPanel;
196     }
197 }