/* * Copyright 2017 Tobias Fleig (tobifleig gmail com) * All rights reserved. * * Usage of this source code is governed by the GNU GENERAL PUBLIC LICENSE version 3 or (at your option) any later version. * For the full license text see the file COPYING or https://github.com/tfg13/LanXchange/blob/master/COPYING */ package de.tobifleig.lxc.plaf.pc; import de.tobifleig.lxc.Configuration; import de.tobifleig.lxc.log.LXCLogBackend; import de.tobifleig.lxc.log.LXCLogger; import de.tobifleig.lxc.plaf.Platform; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.Iterator; /** * Generic PC platform for all platforms with direct write access to the main directory. * Shared by CLI and Swing platforms. * Provides automatic updates and manages the config file. */ public abstract class PCPlatform implements Platform { private static final int MAX_LOG_SIZE_CHARS = 134217728; // ~128MiB private static final int LOG_ROTATION_SIZE = 3; /** * path to cfg-file. */ private static final String CONFIG_PATH = "lxc.cfg"; protected final LXCLogger logger; public PCPlatform(String[] args) { // check permission for own folder try { File.createTempFile("testacl", null, new File(".")).delete(); // Can write } catch (IOException ex) { // Cannot write System.err.println("ERROR: Cannot write to my directory (" + new File(".").getAbsolutePath() + "). Try running LXC in your home directory."); getGui(args).showError("LXC is not allowed to create/modify files in the folder it is located. Please move to your home directory or start as administrator."); System.exit(1); } // init logging boolean debug = false; for (String s : args) { if (s.equals("-nolog")) { debug = true; break; } } LXCLogBackend.init(new File("."), MAX_LOG_SIZE_CHARS, LOG_ROTATION_SIZE, debug); logger = LXCLogBackend.getLogger("platform"); } @Override public boolean hasAutoUpdates() { return true; } @Override public void checkAndPerformUpdates(String[] args) { // Find out if updating is allowed, requested, forced and/or if the // verification should be disabled. boolean checkForUpdates = false; boolean forceUpdate = false; boolean overrideVerification = false; boolean allowDowngrade = false; boolean restartable = false; if (Configuration.containsKey("allowupdates")) { String result = Configuration.getStringSetting("allowupdates"); if ("yes".equals(result.toLowerCase()) || "true".equals(result.toLowerCase())) { checkForUpdates = true; } } else { // not set yet, default to true (yes) checkForUpdates = true; Configuration.putStringSetting("allowupdates", "true"); } // special settings for (String s : args) { if (s.equals("-update")) { checkForUpdates = true; } else if (s.equals("-forceupdate")) { forceUpdate = true; } else if (s.equals("-overrideVerification")) { overrideVerification = true; } else if (s.equals("-allowDowngrade")) { allowDowngrade = true; } else if (s.equals("-managed")) { // whoever launched LXC tells us he is able to restart us in // case of an update restartable = true; } } if (checkForUpdates || forceUpdate) { logger.info("Checking for Updates..."); // Ugly workaround, anonymous inner classes require (local) // variables to be final final boolean force = forceUpdate; final boolean noVerification = overrideVerification; final boolean managed = restartable; final boolean allowDowngradeF = allowDowngrade; // check in separate thread Runnable r = new Runnable() { @Override public void run() { try { LXCUpdater.checkAndPerformUpdate(getUpdaterGui(), force, noVerification, allowDowngradeF, managed); } catch (Exception ex) { logger.error("Updater crashed", ex); } } }; Thread t = new Thread(r); t.setName("update checker"); t.setDaemon(true); t.start(); } else { logger.info("Not checking for updates. (disabled via lxc.cfg)"); } } @Override public void readConfiguration(String[] args) { BufferedReader reader = null; try { File cfgFile = new File(CONFIG_PATH); // create on first start if (!cfgFile.exists()) { cfgFile.createNewFile(); } reader = new BufferedReader(new FileReader(cfgFile)); String line; int i = 0; // line number while ((line = reader.readLine()) != null) { // read line after line, add content to Configuration int equalSignIndex = line.indexOf('='); // search for "=" if (equalSignIndex == -1) { } else { String v1 = line.substring(0, equalSignIndex); // prefix (before "=") String v2 = line.substring(equalSignIndex + 1); // suffix (after "=") Configuration.putStringSetting(v1, v2); } } } catch (IOException ex) { // this is serious. exit logger.error("Cannot read/write configfile (cfg.txt)", ex); // display warning (gui not available yet) showEarlyError("Cannot write to own folder. Please move to your home directory or start as administrator."); System.exit(1); } finally { try { if (reader != null) { reader.close(); } } catch (IOException ex) { // ignore } } } @Override public void writeConfiguration() { FileWriter writer = null; try { writer = new FileWriter(CONFIG_PATH); Iterator<String> iter = Configuration.getKeyIterator(); while (iter.hasNext()) { String s = iter.next(); writer.append(s); writer.append("="); writer.append(Configuration.getStringSetting(s)); writer.append('\n'); } } catch (IOException ex) { logger.error("Cannot write config file.", ex); } finally { try { if (writer != null) { writer.close(); } } catch (IOException ex) { // ignore } } } @Override public boolean askForDownloadTargetSupported() { return true; } @Override public String getDefaultDownloadTarget() { // depends on configuration if (!Configuration.containsKey("defaulttarget")) { return null; // default = always ask } else { // check if valid File file = new File( Configuration.getStringSetting("defaulttarget")); if (file.isDirectory() && file.canWrite()) { return file.getAbsolutePath(); } } return null; // invalid path = ask } @Override public String[] getRequiredMulticastHelpers() { return new String[0]; } /** * Display critical errors that occurred during startup. * @param error the message */ public abstract void showEarlyError(String error); /** * Returns the updater gui. * @return the updater gui */ public abstract UpdaterGui getUpdaterGui(); }