001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.tools; 003 004import static java.awt.event.InputEvent.ALT_DOWN_MASK; 005import static java.awt.event.InputEvent.CTRL_DOWN_MASK; 006import static java.awt.event.InputEvent.SHIFT_DOWN_MASK; 007import static java.awt.event.KeyEvent.VK_A; 008import static java.awt.event.KeyEvent.VK_C; 009import static java.awt.event.KeyEvent.VK_D; 010import static java.awt.event.KeyEvent.VK_DELETE; 011import static java.awt.event.KeyEvent.VK_DOWN; 012import static java.awt.event.KeyEvent.VK_ENTER; 013import static java.awt.event.KeyEvent.VK_ESCAPE; 014import static java.awt.event.KeyEvent.VK_F10; 015import static java.awt.event.KeyEvent.VK_F4; 016import static java.awt.event.KeyEvent.VK_LEFT; 017import static java.awt.event.KeyEvent.VK_NUM_LOCK; 018import static java.awt.event.KeyEvent.VK_PRINTSCREEN; 019import static java.awt.event.KeyEvent.VK_RIGHT; 020import static java.awt.event.KeyEvent.VK_SHIFT; 021import static java.awt.event.KeyEvent.VK_SPACE; 022import static java.awt.event.KeyEvent.VK_TAB; 023import static java.awt.event.KeyEvent.VK_UP; 024import static java.awt.event.KeyEvent.VK_V; 025import static java.awt.event.KeyEvent.VK_X; 026import static java.awt.event.KeyEvent.VK_Y; 027import static java.awt.event.KeyEvent.VK_Z; 028import static org.openstreetmap.josm.tools.I18n.tr; 029 030import java.io.File; 031import java.io.IOException; 032import java.security.InvalidKeyException; 033import java.security.KeyFactory; 034import java.security.KeyStore; 035import java.security.KeyStoreException; 036import java.security.NoSuchAlgorithmException; 037import java.security.NoSuchProviderException; 038import java.security.PublicKey; 039import java.security.SignatureException; 040import java.security.cert.CertificateException; 041import java.security.spec.InvalidKeySpecException; 042import java.security.spec.X509EncodedKeySpec; 043import java.util.ArrayList; 044import java.util.Collection; 045import java.util.Enumeration; 046 047import javax.swing.JOptionPane; 048 049import org.openstreetmap.josm.Main; 050 051/** 052 * {@code PlatformHook} implementation for Microsoft Windows systems. 053 * @since 1023 054 */ 055public class PlatformHookWindows extends PlatformHookUnixoid implements PlatformHook { 056 057 private static final byte[] INSECURE_PUBLIC_KEY = new byte[] { 058 0x30, (byte) 0x82, 0x1, 0x22, 0x30, 0xd, 0x6, 0x9, 0x2a, (byte) 0x86, 0x48, 059 (byte) 0x86, (byte) 0xf7, 0xd, 0x1, 0x1, 0x1, 0x5, 0x0, 0x3, (byte) 0x82, 0x1, 0xf, 0x0, 060 0x30, (byte) 0x82, 0x01, 0x0a, 0x02, (byte) 0x82, 0x01, 0x01, 0x00, (byte) 0x95, (byte) 0x95, (byte) 0x88, 061 (byte) 0x84, (byte) 0xc8, (byte) 0xd9, 0x6b, (byte) 0xc5, (byte) 0xda, 0x0b, 0x69, (byte) 0xbf, (byte) 0xfc, 062 0x7e, (byte) 0xb9, (byte) 0x96, 0x2c, (byte) 0xeb, (byte) 0x8f, (byte) 0xbc, 0x6e, 0x40, (byte) 0xe6, (byte) 0xe2, 063 (byte) 0xfc, (byte) 0xf1, 0x7f, 0x73, (byte) 0xa7, (byte) 0x9d, (byte) 0xde, (byte) 0xc7, (byte) 0x88, 0x57, 0x51, 064 (byte) 0x84, (byte) 0xed, (byte) 0x96, (byte) 0xfb, (byte) 0xe1, 0x38, (byte) 0xef, 0x08, 0x2b, (byte) 0xf3, 065 (byte) 0xc7, (byte) 0xc3, 0x5d, (byte) 0xfe, (byte) 0xf9, 0x51, (byte) 0xe6, 0x29, (byte) 0xfc, (byte) 0xe5, 0x0d, 066 (byte) 0xa1, 0x0d, (byte) 0xa8, (byte) 0xb4, (byte) 0xae, 0x26, 0x18, 0x19, 0x4d, 0x6c, 0x0c, 0x3b, 0x12, (byte) 0xba, 067 (byte) 0xbc, 0x5f, 0x32, (byte) 0xb3, (byte) 0xbe, (byte) 0x9d, 0x17, 0x0d, 0x4d, 0x2f, 0x1a, 0x48, (byte) 0xb7, 068 (byte) 0xac, (byte) 0xf7, 0x1a, 0x43, 0x01, (byte) 0x97, (byte) 0xf4, (byte) 0xf8, 0x4c, (byte) 0xbb, 0x6a, (byte) 0xbc, 069 0x33, (byte) 0xe1, 0x73, 0x1e, (byte) 0x86, (byte) 0xfb, 0x2e, (byte) 0xb1, 0x63, 0x75, (byte) 0x85, (byte) 0xdc, 070 (byte) 0x82, 0x6c, 0x28, (byte) 0xf1, (byte) 0xe3, (byte) 0x90, 0x63, (byte) 0x9d, 0x3d, 0x48, (byte) 0x8a, (byte) 0x8c, 071 0x47, (byte) 0xe2, 0x10, 0x0b, (byte) 0xef, (byte) 0x91, (byte) 0x94, (byte) 0xb0, 0x6c, 0x4c, (byte) 0x80, 0x76, 0x03, 072 (byte) 0xe1, (byte) 0xb6, (byte) 0x90, (byte) 0x87, (byte) 0xd9, (byte) 0xae, (byte) 0xf4, (byte) 0x8e, (byte) 0xe0, 073 (byte) 0x9f, (byte) 0xe7, 0x3a, 0x2c, 0x2f, 0x21, (byte) 0xd4, 0x46, (byte) 0xba, (byte) 0x95, 0x70, (byte) 0xa9, 0x5b, 074 0x20, 0x2a, (byte) 0xfa, 0x52, 0x3e, (byte) 0x9d, (byte) 0xd9, (byte) 0xef, 0x28, (byte) 0xc5, (byte) 0xd1, 0x60, 075 (byte) 0x89, 0x68, 0x6e, 0x7f, (byte) 0xd7, (byte) 0x9e, (byte) 0x89, 0x4c, (byte) 0xeb, 0x4d, (byte) 0xd2, (byte) 0xc6, 076 (byte) 0xf4, 0x2d, 0x02, 0x5d, (byte) 0xda, (byte) 0xde, 0x33, (byte) 0xfe, (byte) 0xc1, 0x7e, (byte) 0xde, 0x4f, 0x1f, 077 (byte) 0x9b, 0x6e, 0x6f, 0x0f, 0x66, 0x71, 0x19, (byte) 0xe9, 0x43, 0x3c, (byte) 0x83, 0x0a, 0x0f, 0x28, 0x21, (byte) 0xc8, 078 0x38, (byte) 0xd3, 0x4e, 0x48, (byte) 0xdf, (byte) 0xd4, (byte) 0x99, (byte) 0xb5, (byte) 0xc6, (byte) 0x8d, (byte) 0xd4, 079 (byte) 0xc1, 0x69, 0x58, 0x79, (byte) 0x82, 0x32, (byte) 0x82, (byte) 0xd4, (byte) 0x86, (byte) 0xe2, 0x04, 0x08, 0x63, 080 (byte) 0x87, (byte) 0xf0, 0x2a, (byte) 0xf6, (byte) 0xec, 0x3e, 0x51, 0x0f, (byte) 0xda, (byte) 0xb4, 0x67, 0x19, 0x5e, 081 0x16, 0x02, (byte) 0x9f, (byte) 0xf1, 0x19, 0x0c, 0x3e, (byte) 0xb8, 0x04, 0x49, 0x07, 0x53, 0x02, 0x03, 0x01, 0x00, 0x01 082 }; 083 084 private static final String WINDOWS_ROOT = "Windows-ROOT"; 085 086 @Override 087 public void openUrl(String url) throws IOException { 088 Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + url); 089 } 090 091 @Override 092 public void initSystemShortcuts() { 093 //Shortcut.registerSystemCut("system:menuexit", tr("reserved"), VK_Q, CTRL_DOWN_MASK); 094 Shortcut.registerSystemShortcut("system:duplicate", tr("reserved"), VK_D, CTRL_DOWN_MASK); // not really system, but to avoid odd results 095 096 // Windows 7 shortcuts: http://windows.microsoft.com/en-US/windows7/Keyboard-shortcuts 097 098 // Shortcuts with setAutomatic(): items with automatic shortcuts will not be added to the menu bar at all 099 100 // Don't know why Ctrl-Alt-Del isn't even listed on official Microsoft support page 101 Shortcut.registerSystemShortcut("system:reset", tr("reserved"), VK_DELETE, CTRL_DOWN_MASK | ALT_DOWN_MASK).setAutomatic(); 102 103 // Ease of Access keyboard shortcuts 104 Shortcut.registerSystemShortcut("microsoft-reserved-01", tr("reserved"), VK_PRINTSCREEN, ALT_DOWN_MASK | SHIFT_DOWN_MASK).setAutomatic(); // Turn High Contrast on or off 105 Shortcut.registerSystemShortcut("microsoft-reserved-02", tr("reserved"), VK_NUM_LOCK, ALT_DOWN_MASK | SHIFT_DOWN_MASK).setAutomatic(); // Turn Mouse Keys on or off 106 //Shortcut.registerSystemCut("microsoft-reserved-03", tr("reserved"), VK_U, );// Open the Ease of Access Center (TODO: Windows-U, how to handle it in Java ?) 107 108 // General keyboard shortcuts 109 //Shortcut.registerSystemShortcut("system:help", tr("reserved"), VK_F1, 0); // Display Help 110 Shortcut.registerSystemShortcut("system:copy", tr("reserved"), VK_C, CTRL_DOWN_MASK); // Copy the selected item 111 Shortcut.registerSystemShortcut("system:cut", tr("reserved"), VK_X, CTRL_DOWN_MASK); // Cut the selected item 112 Shortcut.registerSystemShortcut("system:paste", tr("reserved"), VK_V, CTRL_DOWN_MASK); // Paste the selected item 113 Shortcut.registerSystemShortcut("system:undo", tr("reserved"), VK_Z, CTRL_DOWN_MASK); // Undo an action 114 Shortcut.registerSystemShortcut("system:redo", tr("reserved"), VK_Y, CTRL_DOWN_MASK); // Redo an action 115 //Shortcut.registerSystemCut("microsoft-reserved-10", tr("reserved"), VK_DELETE, 0); // Delete the selected item and move it to the Recycle Bin 116 //Shortcut.registerSystemCut("microsoft-reserved-11", tr("reserved"), VK_DELETE, SHIFT_DOWN_MASK); // Delete the selected item without moving it to the Recycle Bin first 117 //Shortcut.registerSystemCut("system:rename", tr("reserved"), VK_F2, 0); // Rename the selected item 118 Shortcut.registerSystemShortcut("system:movefocusright", tr("reserved"), VK_RIGHT, CTRL_DOWN_MASK); // Move the cursor to the beginning of the next word 119 Shortcut.registerSystemShortcut("system:movefocusleft", tr("reserved"), VK_LEFT, CTRL_DOWN_MASK); // Move the cursor to the beginning of the previous word 120 Shortcut.registerSystemShortcut("system:movefocusdown", tr("reserved"), VK_DOWN, CTRL_DOWN_MASK); // Move the cursor to the beginning of the next paragraph 121 Shortcut.registerSystemShortcut("system:movefocusup", tr("reserved"), VK_UP, CTRL_DOWN_MASK); // Move the cursor to the beginning of the previous paragraph 122 //Shortcut.registerSystemCut("microsoft-reserved-17", tr("reserved"), VK_RIGHT, CTRL_DOWN_MASK | SHIFT_DOWN_MASK); // Select a block of text 123 //Shortcut.registerSystemCut("microsoft-reserved-18", tr("reserved"), VK_LEFT, CTRL_DOWN_MASK | SHIFT_DOWN_MASK); // Select a block of text 124 //Shortcut.registerSystemCut("microsoft-reserved-19", tr("reserved"), VK_DOWN, CTRL_DOWN_MASK | SHIFT_DOWN_MASK); // Select a block of text 125 //Shortcut.registerSystemCut("microsoft-reserved-20", tr("reserved"), VK_UP, CTRL_DOWN_MASK | SHIFT_DOWN_MASK); // Select a block of text 126 //Shortcut.registerSystemCut("microsoft-reserved-21", tr("reserved"), VK_RIGHT, SHIFT_DOWN_MASK); // Select more than one item in a window or on the desktop, or select text within a document 127 //Shortcut.registerSystemCut("microsoft-reserved-22", tr("reserved"), VK_LEFT, SHIFT_DOWN_MASK); // Select more than one item in a window or on the desktop, or select text within a document 128 //Shortcut.registerSystemCut("microsoft-reserved-23", tr("reserved"), VK_DOWN, SHIFT_DOWN_MASK); // Select more than one item in a window or on the desktop, or select text within a document 129 //Shortcut.registerSystemCut("microsoft-reserved-24", tr("reserved"), VK_UP, SHIFT_DOWN_MASK); // Select more than one item in a window or on the desktop, or select text within a document 130 //Shortcut.registerSystemCut("microsoft-reserved-25", tr("reserved"), VK_RIGHT+, CTRL_DOWN_MASK); // Select multiple individual items in a window or on the desktop (TODO: ctrl+arrow+spacebar, how to handle it in Java ?) 131 //Shortcut.registerSystemCut("microsoft-reserved-26", tr("reserved"), VK_LEFT+, CTRL_DOWN_MASK); // Select multiple individual items in a window or on the desktop (TODO: ctrl+arrow+spacebar, how to handle it in Java ?) 132 //Shortcut.registerSystemCut("microsoft-reserved-27", tr("reserved"), VK_DOWN+, CTRL_DOWN_MASK); // Select multiple individual items in a window or on the desktop (TODO: ctrl+arrow+spacebar, how to handle it in Java ?) 133 //Shortcut.registerSystemCut("microsoft-reserved-28", tr("reserved"), VK_UP+, CTRL_DOWN_MASK); // Select multiple individual items in a window or on the desktop (TODO: ctrl+arrow+spacebar, how to handle it in Java ?) 134 Shortcut.registerSystemShortcut("system:selectall", tr("reserved"), VK_A, CTRL_DOWN_MASK); // Select all items in a document or window 135 //Shortcut.registerSystemCut("system:search", tr("reserved"), VK_F3, 0); // Search for a file or folder 136 Shortcut.registerSystemShortcut("microsoft-reserved-31", tr("reserved"), VK_ENTER, ALT_DOWN_MASK).setAutomatic(); // Display properties for the selected item 137 Shortcut.registerSystemShortcut("system:exit", tr("reserved"), VK_F4, ALT_DOWN_MASK).setAutomatic(); // Close the active item, or exit the active program 138 Shortcut.registerSystemShortcut("microsoft-reserved-33", tr("reserved"), VK_SPACE, ALT_DOWN_MASK).setAutomatic(); // Open the shortcut menu for the active window 139 //Shortcut.registerSystemCut("microsoft-reserved-34", tr("reserved"), VK_F4, CTRL_DOWN_MASK); // Close the active document (in programs that allow you to have multiple documents open simultaneously) 140 Shortcut.registerSystemShortcut("microsoft-reserved-35", tr("reserved"), VK_TAB, ALT_DOWN_MASK).setAutomatic(); // Switch between open items 141 Shortcut.registerSystemShortcut("microsoft-reserved-36", tr("reserved"), VK_TAB, CTRL_DOWN_MASK | ALT_DOWN_MASK).setAutomatic(); // Use the arrow keys to switch between open items 142 //Shortcut.registerSystemCut("microsoft-reserved-37", tr("reserved"), VK_TAB, ); // Cycle through programs on the taskbar by using Aero Flip 3-D (TODO: Windows-Tab, how to handle it in Java ?) 143 //Shortcut.registerSystemCut("microsoft-reserved-38", tr("reserved"), VK_TAB, CTRL_DOWN_MASK | ); // Use the arrow keys to cycle through programs on the taskbar by using Aero Flip 3-D (TODO: Ctrl-Windows-Tab, how to handle it in Java ?) 144 Shortcut.registerSystemShortcut("microsoft-reserved-39", tr("reserved"), VK_ESCAPE, ALT_DOWN_MASK).setAutomatic(); // Cycle through items in the order in which they were opened 145 //Shortcut.registerSystemCut("microsoft-reserved-40", tr("reserved"), VK_F6, 0); // Cycle through screen elements in a window or on the desktop 146 //Shortcut.registerSystemCut("microsoft-reserved-41", tr("reserved"), VK_F4, 0); // Display the address bar list in Windows Explorer 147 Shortcut.registerSystemShortcut("microsoft-reserved-42", tr("reserved"), VK_F10, SHIFT_DOWN_MASK); // Display the shortcut menu for the selected item 148 Shortcut.registerSystemShortcut("microsoft-reserved-43", tr("reserved"), VK_ESCAPE, CTRL_DOWN_MASK).setAutomatic(); // Open the Start menu 149 //Shortcut.registerSystemShortcut("microsoft-reserved-44", tr("reserved"), VK_F10, 0); // Activate the menu bar in the active program 150 //Shortcut.registerSystemCut("microsoft-reserved-45", tr("reserved"), VK_RIGHT, 0); // Open the next menu to the right, or open a submenu 151 //Shortcut.registerSystemCut("microsoft-reserved-46", tr("reserved"), VK_LEFT, 0); // Open the next menu to the left, or close a submenu 152 //Shortcut.registerSystemCut("microsoft-reserved-47", tr("reserved"), VK_F5, 0); // Refresh the active window 153 //Shortcut.registerSystemCut("microsoft-reserved-48", tr("reserved"), VK_UP, ALT_DOWN_MASK); // View the folder one level up in Windows Explorer 154 //Shortcut.registerSystemCut("microsoft-reserved-49", tr("reserved"), VK_ESCAPE, 0); // Cancel the current task 155 Shortcut.registerSystemShortcut("microsoft-reserved-50", tr("reserved"), VK_ESCAPE, CTRL_DOWN_MASK | SHIFT_DOWN_MASK).setAutomatic(); // Open Task Manager 156 Shortcut.registerSystemShortcut("microsoft-reserved-51", tr("reserved"), VK_SHIFT, ALT_DOWN_MASK).setAutomatic(); // Switch the input language when multiple input languages are enabled 157 Shortcut.registerSystemShortcut("microsoft-reserved-52", tr("reserved"), VK_SHIFT, CTRL_DOWN_MASK).setAutomatic(); // Switch the keyboard layout when multiple keyboard layouts are enabled 158 //Shortcut.registerSystemCut("microsoft-reserved-53", tr("reserved"), ); // Change the reading direction of text in right-to-left reading languages (TODO: unclear) 159 } 160 161 @Override 162 public String getDefaultStyle() { 163 return "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"; 164 } 165 166 @Override 167 public boolean rename(File from, File to) { 168 if (to.exists()) 169 to.delete(); 170 return from.renameTo(to); 171 } 172 173 @Override 174 public String getOSDescription() { 175 return Utils.strip(System.getProperty("os.name")) + " " + 176 ((System.getenv("ProgramFiles(x86)") == null) ? "32" : "64") + "-Bit"; 177 } 178 179 /** 180 * Loads Windows-ROOT keystore. 181 * @return Windows-ROOT keystore 182 * @throws NoSuchAlgorithmException if the algorithm used to check the integrity of the keystore cannot be found 183 * @throws CertificateException if any of the certificates in the keystore could not be loaded 184 * @throws IOException if there is an I/O or format problem with the keystore data, if a password is required but not given 185 * @throws KeyStoreException if no Provider supports a KeyStore implementation for the type "Windows-ROOT" 186 * @since 7343 187 */ 188 public static KeyStore getRootKeystore() throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException { 189 KeyStore ks = KeyStore.getInstance(WINDOWS_ROOT); 190 ks.load(null, null); 191 return ks; 192 } 193 194 /** 195 * Removes potential insecure certificates installed with previous versions of JOSM on Windows. 196 * @throws NoSuchAlgorithmException on unsupported signature algorithms 197 * @throws CertificateException if any of the certificates in the Windows keystore could not be loaded 198 * @throws KeyStoreException if no Provider supports a KeyStoreSpi implementation for the type "Windows-ROOT" 199 * @throws IOException if there is an I/O or format problem with the keystore data, if a password is required but not given 200 * @since 7335 201 */ 202 public static void removeInsecureCertificates() throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException { 203 // We offered before a public private key we need now to remove from Windows PCs as it might be a huge security risk (see #10230) 204 PublicKey insecurePubKey = null; 205 try { 206 insecurePubKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(INSECURE_PUBLIC_KEY)); 207 } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { 208 Main.error(e); 209 return; 210 } 211 KeyStore ks = getRootKeystore(); 212 Enumeration<String> en = ks.aliases(); 213 Collection<String> insecureCertificates = new ArrayList<>(); 214 while (en.hasMoreElements()) { 215 String alias = en.nextElement(); 216 // Look for certificates associated with a private key 217 if (ks.isKeyEntry(alias)) { 218 try { 219 ks.getCertificate(alias).verify(insecurePubKey); 220 // If no exception, this is a certificate signed with the insecure key -> remove it 221 insecureCertificates.add(alias); 222 } catch (InvalidKeyException | NoSuchProviderException | SignatureException e) { 223 // If exception this is not a certificate related to JOSM, just trace it 224 Main.trace(alias + " --> " + e.getClass().getName()); 225 } 226 } 227 } 228 // Remove insecure certificates 229 if (!insecureCertificates.isEmpty()) { 230 StringBuilder message = new StringBuilder("<html>"); 231 message.append(tr("A previous version of JOSM has installed a custom certificate "+ 232 "in order to provide HTTPS support for Remote Control:")); 233 message.append("<br><ul>"); 234 for (String alias : insecureCertificates) { 235 message.append("<li>"); 236 message.append(alias); 237 message.append("</li>"); 238 } 239 message.append("</ul>"); 240 message.append(tr("It appears it could be an important <b>security risk</b>.<br><br>"+ 241 "You are now going to be prompted by Windows to remove this insecure certificate.<br>"+ 242 "For your own safety, <b>please click Yes</b> in next dialog.")); 243 message.append("</html>"); 244 JOptionPane.showMessageDialog(Main.parent, message.toString(), tr("Warning"), JOptionPane.WARNING_MESSAGE); 245 for (String alias : insecureCertificates) { 246 Main.warn(tr("Removing insecure certificate from {0} keystore: {1}", WINDOWS_ROOT, alias)); 247 try { 248 ks.deleteEntry(alias); 249 } catch (KeyStoreException e) { 250 Main.error(tr("Unable to remove insecure certificate from keystore: {0}", e.getMessage())); 251 } 252 } 253 } 254 } 255 256 @Override 257 public boolean setupHttpsCertificate(String entryAlias, KeyStore.TrustedCertificateEntry trustedCert) 258 throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException { 259 KeyStore ks = getRootKeystore(); 260 // Look for certificate to install 261 String alias = ks.getCertificateAlias(trustedCert.getTrustedCertificate()); 262 if (alias != null) { 263 // JOSM certificate found, return 264 Main.debug(tr("JOSM localhost certificate found in {0} keystore: {1}", WINDOWS_ROOT, alias)); 265 return false; 266 } 267 // JOSM certificate not found, warn user 268 StringBuilder message = new StringBuilder("<html>"); 269 message.append(tr("Remote Control is configured to provide HTTPS support.<br>"+ 270 "This requires to add a custom certificate generated by JOSM to the Windows Root CA store.<br><br>"+ 271 "You are now going to be prompted by Windows to confirm this operation.<br>"+ 272 "To enable proper HTTPS support, <b>please click Yes</b> in next dialog.<br><br>"+ 273 "If unsure, you can also click No then disable HTTPS support in Remote Control preferences.")); 274 message.append("</html>"); 275 JOptionPane.showMessageDialog(Main.parent, message.toString(), 276 tr("HTTPS support in Remote Control"), JOptionPane.INFORMATION_MESSAGE); 277 // install it to Windows-ROOT keystore, used by IE, Chrome and Safari, but not by Firefox 278 Main.info(tr("Adding JOSM localhost certificate to {0} keystore", WINDOWS_ROOT)); 279 ks.setEntry(entryAlias, trustedCert, null); 280 return true; 281 } 282}