package com.rarchives.ripme; import java.awt.*; import java.io.File; import java.io.IOException; import java.io.BufferedReader; import java.io.FileReader; import java.io.FileNotFoundException; import java.net.MalformedURLException; import java.net.URL; import java.util.Arrays; import java.util.List; import javax.swing.SwingUtilities; import org.apache.commons.cli.BasicParser; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.lang.SystemUtils; import org.apache.log4j.Logger; import com.rarchives.ripme.ripper.AbstractRipper; import com.rarchives.ripme.ui.History; import com.rarchives.ripme.ui.HistoryEntry; import com.rarchives.ripme.ui.MainWindow; import com.rarchives.ripme.ui.UpdateUtils; import com.rarchives.ripme.utils.Proxy; import com.rarchives.ripme.utils.RipUtils; import com.rarchives.ripme.utils.Utils; /** * Entry point to application. * This is where all the fun happens, with the main method. * Decides to display UI or to run silently via command-line. * * As the "controller" to all other classes, it parses command line parameters and loads the history. */ public class App { public static final Logger logger = Logger.getLogger(App.class); private static final History HISTORY = new History(); /** * Where everything starts. Takes in, and tries to parse as many commandline arguments as possible. * Otherwise, it launches a GUI. * * @param args Array of command line arguments. */ public static void main(String[] args) throws MalformedURLException { CommandLine cl = getArgs(args); if (args.length > 0 && cl.hasOption('v')){ logger.info(UpdateUtils.getThisJarVersion()); System.exit(0); } if (Utils.getConfigString("proxy.http", null) != null) { Proxy.setHTTPProxy(Utils.getConfigString("proxy.http", null)); } else if (Utils.getConfigString("proxy.socks", null) != null) { Proxy.setSocks(Utils.getConfigString("proxy.socks", null)); } if (GraphicsEnvironment.isHeadless() || args.length > 0) { handleArguments(args); } else { if (SystemUtils.IS_OS_MAC_OSX) { System.setProperty("apple.laf.useScreenMenuBar", "true"); System.setProperty("com.apple.mrj.application.apple.menu.about.name", "RipMe"); } Utils.configureLogger(); logger.info("Initialized ripme v" + UpdateUtils.getThisJarVersion()); MainWindow mw = new MainWindow(); SwingUtilities.invokeLater(mw); } } /** * Creates an abstract ripper and instructs it to rip. * @param url URL to be ripped * @throws Exception Nothing too specific here, just a catch-all. * */ private static void rip(URL url) throws Exception { AbstractRipper ripper = AbstractRipper.getRipper(url); ripper.setup(); ripper.rip(); } /** * For dealing with command-line arguments. * @param args Array of Command-line arguments */ private static void handleArguments(String[] args) { CommandLine cl = getArgs(args); //Help (list commands) if (cl.hasOption('h') || args.length == 0) { HelpFormatter hf = new HelpFormatter(); hf.printHelp("java -jar ripme.jar [OPTIONS]", getOptions()); System.exit(0); } Utils.configureLogger(); logger.info("Initialized ripme v" + UpdateUtils.getThisJarVersion()); //Allow file overwriting if (cl.hasOption('w')) { Utils.setConfigBoolean("file.overwrite", true); } //SOCKS proxy server if (cl.hasOption('s')) { String sservfull = cl.getOptionValue('s').trim(); Proxy.setSocks(sservfull); } //HTTP proxy server if (cl.hasOption('p')) { String proxyserverfull = cl.getOptionValue('p').trim(); Proxy.setHTTPProxy(proxyserverfull); } //Number of threads if (cl.hasOption('t')) { Utils.setConfigInteger("threads.size", Integer.parseInt(cl.getOptionValue('t'))); } //Ignore 404 if (cl.hasOption('4')) { Utils.setConfigBoolean("errors.skip404", true); } //Re-rip all previous albums if (cl.hasOption('r')) { // Re-rip all via command-line List history = Utils.getConfigList("download.history"); for (String urlString : history) { try { URL url = new URL(urlString.trim()); rip(url); } catch (Exception e) { logger.error("[!] Failed to rip URL " + urlString, e); continue; } try { Thread.sleep(500); } catch (InterruptedException e) { logger.warn("[!] Interrupted while re-ripping history"); System.exit(-1); } } // Exit System.exit(0); } //Re-rip all selected albums if (cl.hasOption('R')) { loadHistory(); if (HISTORY.toList().isEmpty()) { logger.error("There are no history entries to re-rip. Rip some albums first"); System.exit(-1); } int added = 0; for (HistoryEntry entry : HISTORY.toList()) { if (entry.selected) { added++; try { URL url = new URL(entry.url); rip(url); } catch (Exception e) { logger.error("[!] Failed to rip URL " + entry.url, e); continue; } try { Thread.sleep(500); } catch (InterruptedException e) { logger.warn("[!] Interrupted while re-ripping history"); System.exit(-1); } } } if (added == 0) { logger.error("No history entries have been 'Checked'\n" + "Check an entry by clicking the checkbox to the right of the URL or Right-click a URL to check/uncheck all items"); System.exit(-1); } } //Save the order of images in album if (cl.hasOption('d')) { Utils.setConfigBoolean("download.save_order", true); } //Don't save the order of images in album if (cl.hasOption('D')) { Utils.setConfigBoolean("download.save_order", false); } //In case specify both, break and exit since it isn't possible. if ((cl.hasOption('d'))&&(cl.hasOption('D'))) { logger.error("\nCannot specify '-d' and '-D' simultaneously"); System.exit(-1); } //Destination directory if (cl.hasOption('l')) { // change the default rips directory Utils.setConfigString("rips.directory", cl.getOptionValue('l')); } //Read URLs from File if (cl.hasOption('f')) { String filename = cl.getOptionValue('f'); try (BufferedReader br = new BufferedReader(new FileReader(filename))) { String url; while ((url = br.readLine()) != null) { if (url.startsWith("//") || url.startsWith("#")) { logger.debug("Skipping over line \"" + url + "\"because it is a comment"); } else { // loop through each url in the file and process each url individually. ripURL(url.trim(), !cl.hasOption("n")); } } } catch (FileNotFoundException fne) { logger.error("[!] File containing list of URLs not found. Cannot continue."); } catch (IOException ioe) { logger.error("[!] Failed reading file containing list of URLs. Cannot continue."); } } //The URL to rip. if (cl.hasOption('u')) { String url = cl.getOptionValue('u').trim(); ripURL(url, !cl.hasOption("n")); } if (cl.hasOption('j')) { UpdateUtils.updateProgramCLI(); } } /** * Attempt to rip targetURL. * @param targetURL URL to rip * @param saveConfig Whether or not you want to save the config (?) */ private static void ripURL(String targetURL, boolean saveConfig) { try { URL url = new URL(targetURL); rip(url); List history = Utils.getConfigList("download.history"); if (!history.contains(url.toExternalForm())) {//if you haven't already downloaded the file before history.add(url.toExternalForm());//add it to history so you won't have to redownload Utils.setConfigList("download.history", Arrays.asList(history.toArray())); if (saveConfig) { Utils.saveConfig(); } } } catch (MalformedURLException e) { logger.error("[!] Given URL is not valid. Expected URL format is http://domain.com/..."); // System.exit(-1); } catch (Exception e) { logger.error("[!] Error while ripping URL " + targetURL, e); // System.exit(-1); } } /** * Creates an Options object, returns it. * @return Returns all acceptable command-line options. */ private static Options getOptions() { Options opts = new Options(); opts.addOption("h", "help", false, "Print the help"); opts.addOption("u", "url", true, "URL of album to rip"); opts.addOption("t", "threads", true, "Number of download threads per rip"); opts.addOption("w", "overwrite", false, "Overwrite existing files"); opts.addOption("r", "rerip", false, "Re-rip all ripped albums"); opts.addOption("R", "rerip-selected", false, "Re-rip all selected albums"); opts.addOption("d", "saveorder", false, "Save the order of images in album"); opts.addOption("D", "nosaveorder", false, "Don't save order of images"); opts.addOption("4", "skip404", false, "Don't retry after a 404 (not found) error"); opts.addOption("l", "ripsdirectory", true, "Rips Directory (Default: ./rips)"); opts.addOption("n", "no-prop-file", false, "Do not create properties file."); opts.addOption("f", "urls-file", true, "Rip URLs from a file."); opts.addOption("v", "version", false, "Show current version"); opts.addOption("s", "socks-server", true, "Use socks server ([user:password]@host[:port])"); opts.addOption("p", "proxy-server", true, "Use HTTP Proxy server ([user:password]@host[:port])"); opts.addOption("j", "update", false, "Update ripme"); return opts; } /** * Tries to parse commandline arguments. * @param args Array of commandline arguments. * @return CommandLine object containing arguments. */ private static CommandLine getArgs(String[] args) { BasicParser parser = new BasicParser(); try { return parser.parse(getOptions(), args, false); } catch (ParseException e) { logger.error("[!] Error while parsing command-line arguments: " + Arrays.toString(args), e); System.exit(-1); return null; } } /** * Loads history from history file into memory. */ private static void loadHistory() { File historyFile = new File(Utils.getConfigDir() + File.separator + "history.json"); HISTORY.clear(); if (historyFile.exists()) { try { logger.info("Loading history from " + historyFile.getCanonicalPath()); HISTORY.fromFile(historyFile.getCanonicalPath()); } catch (IOException e) { logger.error("Failed to load history from file " + historyFile, e); logger.warn( "RipMe failed to load the history file at " + historyFile.getAbsolutePath() + "\n\n" + "Error: " + e.getMessage() + "\n\n" + "Closing RipMe will automatically overwrite the contents of this file,\n" + "so you may want to back the file up before closing RipMe!"); } } else { logger.info("Loading history from configuration"); HISTORY.fromList(Utils.getConfigList("download.history")); if (HISTORY.toList().isEmpty()) { // Loaded from config, still no entries. // Guess rip history based on rip folder String[] dirs = Utils.getWorkingDirectory().list((dir, file) -> new File(dir.getAbsolutePath() + File.separator + file).isDirectory()); for (String dir : dirs) { String url = RipUtils.urlFromDirectoryName(dir); if (url != null) { // We found one, add it to history HistoryEntry entry = new HistoryEntry(); entry.url = url; HISTORY.add(entry); } } } } } }