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.awt.GraphicsEnvironment; 031import java.io.File; 032import java.io.IOException; 033import java.nio.file.DirectoryStream; 034import java.nio.file.FileSystems; 035import java.nio.file.Files; 036import java.nio.file.Path; 037import java.security.InvalidKeyException; 038import java.security.KeyFactory; 039import java.security.KeyStore; 040import java.security.KeyStoreException; 041import java.security.NoSuchAlgorithmException; 042import java.security.NoSuchProviderException; 043import java.security.PublicKey; 044import java.security.SignatureException; 045import java.security.cert.CertificateException; 046import java.security.spec.InvalidKeySpecException; 047import java.security.spec.X509EncodedKeySpec; 048import java.util.ArrayList; 049import java.util.Collection; 050import java.util.Enumeration; 051import java.util.List; 052 053import javax.swing.JOptionPane; 054 055import org.openstreetmap.josm.Main; 056 057/** 058 * {@code PlatformHook} implementation for Microsoft Windows systems. 059 * @since 1023 060 */ 061public class PlatformHookWindows extends PlatformHookUnixoid implements PlatformHook { 062 063 private static final byte[] INSECURE_PUBLIC_KEY = new byte[] { 064 0x30, (byte) 0x82, 0x1, 0x22, 0x30, 0xd, 0x6, 0x9, 0x2a, (byte) 0x86, 0x48, 065 (byte) 0x86, (byte) 0xf7, 0xd, 0x1, 0x1, 0x1, 0x5, 0x0, 0x3, (byte) 0x82, 0x1, 0xf, 0x0, 066 0x30, (byte) 0x82, 0x01, 0x0a, 0x02, (byte) 0x82, 0x01, 0x01, 0x00, (byte) 0x95, (byte) 0x95, (byte) 0x88, 067 (byte) 0x84, (byte) 0xc8, (byte) 0xd9, 0x6b, (byte) 0xc5, (byte) 0xda, 0x0b, 0x69, (byte) 0xbf, (byte) 0xfc, 068 0x7e, (byte) 0xb9, (byte) 0x96, 0x2c, (byte) 0xeb, (byte) 0x8f, (byte) 0xbc, 0x6e, 0x40, (byte) 0xe6, (byte) 0xe2, 069 (byte) 0xfc, (byte) 0xf1, 0x7f, 0x73, (byte) 0xa7, (byte) 0x9d, (byte) 0xde, (byte) 0xc7, (byte) 0x88, 0x57, 0x51, 070 (byte) 0x84, (byte) 0xed, (byte) 0x96, (byte) 0xfb, (byte) 0xe1, 0x38, (byte) 0xef, 0x08, 0x2b, (byte) 0xf3, 071 (byte) 0xc7, (byte) 0xc3, 0x5d, (byte) 0xfe, (byte) 0xf9, 0x51, (byte) 0xe6, 0x29, (byte) 0xfc, (byte) 0xe5, 0x0d, 072 (byte) 0xa1, 0x0d, (byte) 0xa8, (byte) 0xb4, (byte) 0xae, 0x26, 0x18, 0x19, 0x4d, 0x6c, 0x0c, 0x3b, 0x12, (byte) 0xba, 073 (byte) 0xbc, 0x5f, 0x32, (byte) 0xb3, (byte) 0xbe, (byte) 0x9d, 0x17, 0x0d, 0x4d, 0x2f, 0x1a, 0x48, (byte) 0xb7, 074 (byte) 0xac, (byte) 0xf7, 0x1a, 0x43, 0x01, (byte) 0x97, (byte) 0xf4, (byte) 0xf8, 0x4c, (byte) 0xbb, 0x6a, (byte) 0xbc, 075 0x33, (byte) 0xe1, 0x73, 0x1e, (byte) 0x86, (byte) 0xfb, 0x2e, (byte) 0xb1, 0x63, 0x75, (byte) 0x85, (byte) 0xdc, 076 (byte) 0x82, 0x6c, 0x28, (byte) 0xf1, (byte) 0xe3, (byte) 0x90, 0x63, (byte) 0x9d, 0x3d, 0x48, (byte) 0x8a, (byte) 0x8c, 077 0x47, (byte) 0xe2, 0x10, 0x0b, (byte) 0xef, (byte) 0x91, (byte) 0x94, (byte) 0xb0, 0x6c, 0x4c, (byte) 0x80, 0x76, 0x03, 078 (byte) 0xe1, (byte) 0xb6, (byte) 0x90, (byte) 0x87, (byte) 0xd9, (byte) 0xae, (byte) 0xf4, (byte) 0x8e, (byte) 0xe0, 079 (byte) 0x9f, (byte) 0xe7, 0x3a, 0x2c, 0x2f, 0x21, (byte) 0xd4, 0x46, (byte) 0xba, (byte) 0x95, 0x70, (byte) 0xa9, 0x5b, 080 0x20, 0x2a, (byte) 0xfa, 0x52, 0x3e, (byte) 0x9d, (byte) 0xd9, (byte) 0xef, 0x28, (byte) 0xc5, (byte) 0xd1, 0x60, 081 (byte) 0x89, 0x68, 0x6e, 0x7f, (byte) 0xd7, (byte) 0x9e, (byte) 0x89, 0x4c, (byte) 0xeb, 0x4d, (byte) 0xd2, (byte) 0xc6, 082 (byte) 0xf4, 0x2d, 0x02, 0x5d, (byte) 0xda, (byte) 0xde, 0x33, (byte) 0xfe, (byte) 0xc1, 0x7e, (byte) 0xde, 0x4f, 0x1f, 083 (byte) 0x9b, 0x6e, 0x6f, 0x0f, 0x66, 0x71, 0x19, (byte) 0xe9, 0x43, 0x3c, (byte) 0x83, 0x0a, 0x0f, 0x28, 0x21, (byte) 0xc8, 084 0x38, (byte) 0xd3, 0x4e, 0x48, (byte) 0xdf, (byte) 0xd4, (byte) 0x99, (byte) 0xb5, (byte) 0xc6, (byte) 0x8d, (byte) 0xd4, 085 (byte) 0xc1, 0x69, 0x58, 0x79, (byte) 0x82, 0x32, (byte) 0x82, (byte) 0xd4, (byte) 0x86, (byte) 0xe2, 0x04, 0x08, 0x63, 086 (byte) 0x87, (byte) 0xf0, 0x2a, (byte) 0xf6, (byte) 0xec, 0x3e, 0x51, 0x0f, (byte) 0xda, (byte) 0xb4, 0x67, 0x19, 0x5e, 087 0x16, 0x02, (byte) 0x9f, (byte) 0xf1, 0x19, 0x0c, 0x3e, (byte) 0xb8, 0x04, 0x49, 0x07, 0x53, 0x02, 0x03, 0x01, 0x00, 0x01 088 }; 089 090 private static final String WINDOWS_ROOT = "Windows-ROOT"; 091 092 @Override 093 public void afterPrefStartupHook() { 094 extendFontconfig("fontconfig.properties.src"); 095 } 096 097 @Override 098 public void openUrl(String url) throws IOException { 099 Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + url); 100 } 101 102 @Override 103 public void initSystemShortcuts() { 104 //Shortcut.registerSystemCut("system:menuexit", tr("reserved"), VK_Q, CTRL_DOWN_MASK); 105 Shortcut.registerSystemShortcut("system:duplicate", tr("reserved"), VK_D, CTRL_DOWN_MASK); // not really system, but to avoid odd results 106 107 // Windows 7 shortcuts: http://windows.microsoft.com/en-US/windows7/Keyboard-shortcuts 108 109 // Shortcuts with setAutomatic(): items with automatic shortcuts will not be added to the menu bar at all 110 111 // Don't know why Ctrl-Alt-Del isn't even listed on official Microsoft support page 112 Shortcut.registerSystemShortcut("system:reset", tr("reserved"), VK_DELETE, CTRL_DOWN_MASK | ALT_DOWN_MASK).setAutomatic(); 113 114 // Ease of Access keyboard shortcuts 115 Shortcut.registerSystemShortcut("microsoft-reserved-01", tr("reserved"), VK_PRINTSCREEN, ALT_DOWN_MASK | SHIFT_DOWN_MASK).setAutomatic(); // Turn High Contrast on or off 116 Shortcut.registerSystemShortcut("microsoft-reserved-02", tr("reserved"), VK_NUM_LOCK, ALT_DOWN_MASK | SHIFT_DOWN_MASK).setAutomatic(); // Turn Mouse Keys on or off 117 //Shortcut.registerSystemCut("microsoft-reserved-03", tr("reserved"), VK_U, );// Open the Ease of Access Center (TODO: Windows-U, how to handle it in Java ?) 118 119 // General keyboard shortcuts 120 //Shortcut.registerSystemShortcut("system:help", tr("reserved"), VK_F1, 0); // Display Help 121 Shortcut.registerSystemShortcut("system:copy", tr("reserved"), VK_C, CTRL_DOWN_MASK); // Copy the selected item 122 Shortcut.registerSystemShortcut("system:cut", tr("reserved"), VK_X, CTRL_DOWN_MASK); // Cut the selected item 123 Shortcut.registerSystemShortcut("system:paste", tr("reserved"), VK_V, CTRL_DOWN_MASK); // Paste the selected item 124 Shortcut.registerSystemShortcut("system:undo", tr("reserved"), VK_Z, CTRL_DOWN_MASK); // Undo an action 125 Shortcut.registerSystemShortcut("system:redo", tr("reserved"), VK_Y, CTRL_DOWN_MASK); // Redo an action 126 //Shortcut.registerSystemCut("microsoft-reserved-10", tr("reserved"), VK_DELETE, 0); // Delete the selected item and move it to the Recycle Bin 127 //Shortcut.registerSystemCut("microsoft-reserved-11", tr("reserved"), VK_DELETE, SHIFT_DOWN_MASK); // Delete the selected item without moving it to the Recycle Bin first 128 //Shortcut.registerSystemCut("system:rename", tr("reserved"), VK_F2, 0); // Rename the selected item 129 Shortcut.registerSystemShortcut("system:movefocusright", tr("reserved"), VK_RIGHT, CTRL_DOWN_MASK); // Move the cursor to the beginning of the next word 130 Shortcut.registerSystemShortcut("system:movefocusleft", tr("reserved"), VK_LEFT, CTRL_DOWN_MASK); // Move the cursor to the beginning of the previous word 131 Shortcut.registerSystemShortcut("system:movefocusdown", tr("reserved"), VK_DOWN, CTRL_DOWN_MASK); // Move the cursor to the beginning of the next paragraph 132 Shortcut.registerSystemShortcut("system:movefocusup", tr("reserved"), VK_UP, CTRL_DOWN_MASK); // Move the cursor to the beginning of the previous paragraph 133 //Shortcut.registerSystemCut("microsoft-reserved-17", tr("reserved"), VK_RIGHT, CTRL_DOWN_MASK | SHIFT_DOWN_MASK); // Select a block of text 134 //Shortcut.registerSystemCut("microsoft-reserved-18", tr("reserved"), VK_LEFT, CTRL_DOWN_MASK | SHIFT_DOWN_MASK); // Select a block of text 135 //Shortcut.registerSystemCut("microsoft-reserved-19", tr("reserved"), VK_DOWN, CTRL_DOWN_MASK | SHIFT_DOWN_MASK); // Select a block of text 136 //Shortcut.registerSystemCut("microsoft-reserved-20", tr("reserved"), VK_UP, CTRL_DOWN_MASK | SHIFT_DOWN_MASK); // Select a block of text 137 //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 138 //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 139 //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 140 //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 141 //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 ?) 142 //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 ?) 143 //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 ?) 144 //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 ?) 145 Shortcut.registerSystemShortcut("system:selectall", tr("reserved"), VK_A, CTRL_DOWN_MASK); // Select all items in a document or window 146 //Shortcut.registerSystemCut("system:search", tr("reserved"), VK_F3, 0); // Search for a file or folder 147 Shortcut.registerSystemShortcut("microsoft-reserved-31", tr("reserved"), VK_ENTER, ALT_DOWN_MASK).setAutomatic(); // Display properties for the selected item 148 Shortcut.registerSystemShortcut("system:exit", tr("reserved"), VK_F4, ALT_DOWN_MASK).setAutomatic(); // Close the active item, or exit the active program 149 Shortcut.registerSystemShortcut("microsoft-reserved-33", tr("reserved"), VK_SPACE, ALT_DOWN_MASK).setAutomatic(); // Open the shortcut menu for the active window 150 //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) 151 Shortcut.registerSystemShortcut("microsoft-reserved-35", tr("reserved"), VK_TAB, ALT_DOWN_MASK).setAutomatic(); // Switch between open items 152 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 153 //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 ?) 154 //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 ?) 155 Shortcut.registerSystemShortcut("microsoft-reserved-39", tr("reserved"), VK_ESCAPE, ALT_DOWN_MASK).setAutomatic(); // Cycle through items in the order in which they were opened 156 //Shortcut.registerSystemCut("microsoft-reserved-40", tr("reserved"), VK_F6, 0); // Cycle through screen elements in a window or on the desktop 157 //Shortcut.registerSystemCut("microsoft-reserved-41", tr("reserved"), VK_F4, 0); // Display the address bar list in Windows Explorer 158 Shortcut.registerSystemShortcut("microsoft-reserved-42", tr("reserved"), VK_F10, SHIFT_DOWN_MASK); // Display the shortcut menu for the selected item 159 Shortcut.registerSystemShortcut("microsoft-reserved-43", tr("reserved"), VK_ESCAPE, CTRL_DOWN_MASK).setAutomatic(); // Open the Start menu 160 //Shortcut.registerSystemShortcut("microsoft-reserved-44", tr("reserved"), VK_F10, 0); // Activate the menu bar in the active program 161 //Shortcut.registerSystemCut("microsoft-reserved-45", tr("reserved"), VK_RIGHT, 0); // Open the next menu to the right, or open a submenu 162 //Shortcut.registerSystemCut("microsoft-reserved-46", tr("reserved"), VK_LEFT, 0); // Open the next menu to the left, or close a submenu 163 //Shortcut.registerSystemCut("microsoft-reserved-47", tr("reserved"), VK_F5, 0); // Refresh the active window 164 //Shortcut.registerSystemCut("microsoft-reserved-48", tr("reserved"), VK_UP, ALT_DOWN_MASK); // View the folder one level up in Windows Explorer 165 //Shortcut.registerSystemCut("microsoft-reserved-49", tr("reserved"), VK_ESCAPE, 0); // Cancel the current task 166 Shortcut.registerSystemShortcut("microsoft-reserved-50", tr("reserved"), VK_ESCAPE, CTRL_DOWN_MASK | SHIFT_DOWN_MASK).setAutomatic(); // Open Task Manager 167 Shortcut.registerSystemShortcut("microsoft-reserved-51", tr("reserved"), VK_SHIFT, ALT_DOWN_MASK).setAutomatic(); // Switch the input language when multiple input languages are enabled 168 Shortcut.registerSystemShortcut("microsoft-reserved-52", tr("reserved"), VK_SHIFT, CTRL_DOWN_MASK).setAutomatic(); // Switch the keyboard layout when multiple keyboard layouts are enabled 169 //Shortcut.registerSystemCut("microsoft-reserved-53", tr("reserved"), ); // Change the reading direction of text in right-to-left reading languages (TODO: unclear) 170 } 171 172 @Override 173 public String getDefaultStyle() { 174 return "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"; 175 } 176 177 @Override 178 public boolean rename(File from, File to) { 179 if (to.exists()) 180 to.delete(); 181 return from.renameTo(to); 182 } 183 184 @Override 185 public String getOSDescription() { 186 return Utils.strip(System.getProperty("os.name")) + " " + 187 ((System.getenv("ProgramFiles(x86)") == null) ? "32" : "64") + "-Bit"; 188 } 189 190 /** 191 * Loads Windows-ROOT keystore. 192 * @return Windows-ROOT keystore 193 * @throws NoSuchAlgorithmException if the algorithm used to check the integrity of the keystore cannot be found 194 * @throws CertificateException if any of the certificates in the keystore could not be loaded 195 * @throws IOException if there is an I/O or format problem with the keystore data, if a password is required but not given 196 * @throws KeyStoreException if no Provider supports a KeyStore implementation for the type "Windows-ROOT" 197 * @since 7343 198 */ 199 public static KeyStore getRootKeystore() throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException { 200 KeyStore ks = KeyStore.getInstance(WINDOWS_ROOT); 201 ks.load(null, null); 202 return ks; 203 } 204 205 /** 206 * Removes potential insecure certificates installed with previous versions of JOSM on Windows. 207 * @throws NoSuchAlgorithmException on unsupported signature algorithms 208 * @throws CertificateException if any of the certificates in the Windows keystore could not be loaded 209 * @throws KeyStoreException if no Provider supports a KeyStoreSpi implementation for the type "Windows-ROOT" 210 * @throws IOException if there is an I/O or format problem with the keystore data, if a password is required but not given 211 * @since 7335 212 */ 213 public static void removeInsecureCertificates() throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException { 214 // 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) 215 PublicKey insecurePubKey = null; 216 try { 217 insecurePubKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(INSECURE_PUBLIC_KEY)); 218 } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { 219 Main.error(e); 220 return; 221 } 222 KeyStore ks = getRootKeystore(); 223 Enumeration<String> en = ks.aliases(); 224 Collection<String> insecureCertificates = new ArrayList<>(); 225 while (en.hasMoreElements()) { 226 String alias = en.nextElement(); 227 // Look for certificates associated with a private key 228 if (ks.isKeyEntry(alias)) { 229 try { 230 ks.getCertificate(alias).verify(insecurePubKey); 231 // If no exception, this is a certificate signed with the insecure key -> remove it 232 insecureCertificates.add(alias); 233 } catch (InvalidKeyException | NoSuchProviderException | SignatureException e) { 234 // If exception this is not a certificate related to JOSM, just trace it 235 Main.trace(alias + " --> " + e.getClass().getName()); 236 } 237 } 238 } 239 // Remove insecure certificates 240 if (!insecureCertificates.isEmpty()) { 241 StringBuilder message = new StringBuilder("<html>"); 242 message.append(tr("A previous version of JOSM has installed a custom certificate "+ 243 "in order to provide HTTPS support for Remote Control:")); 244 message.append("<br><ul>"); 245 for (String alias : insecureCertificates) { 246 message.append("<li>"); 247 message.append(alias); 248 message.append("</li>"); 249 } 250 message.append("</ul>"); 251 message.append(tr("It appears it could be an important <b>security risk</b>.<br><br>"+ 252 "You are now going to be prompted by Windows to remove this insecure certificate.<br>"+ 253 "For your own safety, <b>please click Yes</b> in next dialog.")); 254 message.append("</html>"); 255 JOptionPane.showMessageDialog(Main.parent, message.toString(), tr("Warning"), JOptionPane.WARNING_MESSAGE); 256 for (String alias : insecureCertificates) { 257 Main.warn(tr("Removing insecure certificate from {0} keystore: {1}", WINDOWS_ROOT, alias)); 258 try { 259 ks.deleteEntry(alias); 260 } catch (KeyStoreException e) { 261 Main.error(tr("Unable to remove insecure certificate from keystore: {0}", e.getMessage())); 262 } 263 } 264 } 265 } 266 267 @Override 268 public boolean setupHttpsCertificate(String entryAlias, KeyStore.TrustedCertificateEntry trustedCert) 269 throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException { 270 KeyStore ks = getRootKeystore(); 271 // Look for certificate to install 272 String alias = ks.getCertificateAlias(trustedCert.getTrustedCertificate()); 273 if (alias != null) { 274 // JOSM certificate found, return 275 Main.debug(tr("JOSM localhost certificate found in {0} keystore: {1}", WINDOWS_ROOT, alias)); 276 return false; 277 } 278 if (!GraphicsEnvironment.isHeadless()) { 279 // JOSM certificate not found, warn user 280 StringBuilder message = new StringBuilder("<html>"); 281 message.append(tr("Remote Control is configured to provide HTTPS support.<br>"+ 282 "This requires to add a custom certificate generated by JOSM to the Windows Root CA store.<br><br>"+ 283 "You are now going to be prompted by Windows to confirm this operation.<br>"+ 284 "To enable proper HTTPS support, <b>please click Yes</b> in next dialog.<br><br>"+ 285 "If unsure, you can also click No then disable HTTPS support in Remote Control preferences.")); 286 message.append("</html>"); 287 JOptionPane.showMessageDialog(Main.parent, message.toString(), 288 tr("HTTPS support in Remote Control"), JOptionPane.INFORMATION_MESSAGE); 289 } 290 // install it to Windows-ROOT keystore, used by IE, Chrome and Safari, but not by Firefox 291 Main.info(tr("Adding JOSM localhost certificate to {0} keystore", WINDOWS_ROOT)); 292 ks.setEntry(entryAlias, trustedCert, null); 293 return true; 294 } 295 296 @Override 297 public File getDefaultCacheDirectory() { 298 String p = System.getenv("LOCALAPPDATA"); 299 if (p == null || p.isEmpty()) { 300 // Fallback for Windows OS earlier than Windows Vista, where the variable is not defined 301 p = System.getenv("APPDATA"); 302 } 303 return new File(new File(p, "JOSM"), "cache"); 304 } 305 306 @Override 307 public File getDefaultPrefDirectory() { 308 return new File(System.getenv("APPDATA"), "JOSM"); 309 } 310 311 @Override 312 public Collection<String> getInstalledFonts() { 313 // Cannot use GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames() 314 // because we have to set the system property before Java initializes its fonts. 315 // Use more low-level method to find the installed fonts. 316 List<String> fontsAvail = new ArrayList<>(); 317 Path fontPath = FileSystems.getDefault().getPath(System.getenv("SYSTEMROOT"), "Fonts"); 318 try (DirectoryStream<Path> ds = Files.newDirectoryStream(fontPath)) { 319 for (Path p : ds) { 320 fontsAvail.add(p.getFileName().toString().toUpperCase()); 321 } 322 fontsAvail.add(""); // for devanagari 323 } catch (IOException ex) { 324 Main.error(ex, false); 325 Main.warn("extended font config - failed to load available Fonts"); 326 fontsAvail = null; 327 } 328 return fontsAvail; 329 } 330 331 @Override 332 public Collection<FontEntry> getAdditionalFonts() { 333 Collection<FontEntry> def = new ArrayList<>(); 334 def.add(new FontEntry("devanagari", "", "")); // just include in fallback list 335 // font already defined in template 336 337 // Windows scripts: https://msdn.microsoft.com/en-us/goglobal/bb688099.aspx 338 // IE default fonts: https://msdn.microsoft.com/en-us/library/ie/dn467844(v=vs.85).aspx 339 340 // Windows 8/8.1 and later 341 def.add(new FontEntry("javanese", "Javanese Text", "JAVATEXT.TTF")); // ISO 639: jv 342 def.add(new FontEntry("leelawadee", "Leelawadee", "LEELAWAD.TTF")); // ISO 639: bug 343 def.add(new FontEntry("myanmar", "Myanmar Text", "MMRTEXT.TTF")); // ISO 639: my 344 def.add(new FontEntry("nirmala", "Nirmala UI", "NIRMALA.TTF")); // ISO 639: sat,srb 345 def.add(new FontEntry("segoeui", "Segoe UI", "SEGOEUI.TTF")); // ISO 639: lis 346 347 // Windows 7 and later 348 def.add(new FontEntry("nko_tifinagh_vai_osmanya", "Ebrima", "EBRIMA.TTF")); // ISO 639: ber. Nko only since Win 8 349 def.add(new FontEntry("khmer1", "Khmer UI", "KHMERUI.TTF")); // ISO 639: km 350 def.add(new FontEntry("lao1", "Lao UI", "LAOUI.TTF")); // ISO 639: lo 351 def.add(new FontEntry("tai_le", "Microsoft Tai Le", "TAILE.TTF")); // ISO 639: khb 352 def.add(new FontEntry("new_tai_lue", "Microsoft New Tai Lue", "NTHAILU.TTF")); // ISO 639: khb 353 354 // Windows Vista and later: 355 def.add(new FontEntry("ethiopic", "Nyala", "NYALA.TTF")); // ISO 639: am,gez,ti 356 def.add(new FontEntry("tibetan", "Microsoft Himalaya", "HIMALAYA.TTF")); // ISO 639: bo,dz 357 def.add(new FontEntry("cherokee", "Plantagenet Cherokee", "PLANTC.TTF")); // ISO 639: chr 358 def.add(new FontEntry("unified_canadian", "Euphemia", "EUPHEMIA.TTF")); // ISO 639: cr,in 359 def.add(new FontEntry("khmer2", "DaunPenh", "DAUNPENH.TTF")); // ISO 639: km 360 def.add(new FontEntry("khmer3", "MoolBoran", "MOOLBOR.TTF")); // ISO 639: km 361 def.add(new FontEntry("lao_thai", "DokChampa", "DOKCHAMP.TTF")); // ISO 639: lo 362 def.add(new FontEntry("mongolian", "Mongolian Baiti", "MONBAITI.TTF")); // ISO 639: mn 363 def.add(new FontEntry("oriya", "Kalinga", "KALINGA.TTF")); // ISO 639: or 364 def.add(new FontEntry("sinhala", "Iskoola Pota", "ISKPOTA.TTF")); // ISO 639: si 365 def.add(new FontEntry("yi", "Yi Baiti", "MSYI.TTF")); // ISO 639: ii 366 367 // Windows XP and later 368 def.add(new FontEntry("gujarati", "Shruti", "SHRUTI.TTF")); 369 def.add(new FontEntry("kannada", "Tunga", "TUNGA.TTF")); 370 def.add(new FontEntry("gurmukhi", "Raavi", "RAAVI.TTF")); 371 def.add(new FontEntry("telugu", "Gautami", "GAUTAMI.TTF")); 372 def.add(new FontEntry("bengali", "Vrinda", "VRINDA.TTF")); // since XP SP2 373 def.add(new FontEntry("syriac", "Estrangelo Edessa", "ESTRE.TTF")); // ISO 639: arc 374 def.add(new FontEntry("thaana", "MV Boli", "MVBOLI.TTF")); // ISO 639: dv 375 def.add(new FontEntry("malayalam", "Kartika", "KARTIKA.TTF")); // ISO 639: ml; since XP SP2 376 377 // Windows 2000 and later 378 def.add(new FontEntry("tamil", "Latha", "LATHA.TTF")); 379 380 // Comes with MS Office & Outlook 2000. Good unicode coverage, so add if available. 381 def.add(new FontEntry("arialuni", "Arial Unicode MS", "ARIALUNI.TTF")); 382 383 return def; 384 } 385}