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