2014-02-26 08:44:22 +01:00
|
|
|
package com.rarchives.ripme.utils;
|
|
|
|
|
|
|
|
import java.io.File;
|
|
|
|
import java.io.IOException;
|
2014-06-12 07:21:09 +02:00
|
|
|
import java.io.InputStream;
|
2014-04-27 19:09:52 +02:00
|
|
|
import java.lang.reflect.Constructor;
|
2014-03-04 14:35:35 +01:00
|
|
|
import java.net.URISyntaxException;
|
|
|
|
import java.net.URL;
|
2014-04-30 06:57:56 +02:00
|
|
|
import java.net.URLDecoder;
|
2014-03-04 14:35:35 +01:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Enumeration;
|
2014-04-06 12:27:30 +02:00
|
|
|
import java.util.List;
|
2014-03-04 14:35:35 +01:00
|
|
|
import java.util.jar.JarEntry;
|
|
|
|
import java.util.jar.JarFile;
|
2014-02-26 08:44:22 +01:00
|
|
|
|
2014-05-11 09:38:15 +02:00
|
|
|
import javax.sound.sampled.AudioSystem;
|
|
|
|
import javax.sound.sampled.Clip;
|
|
|
|
import javax.sound.sampled.Line;
|
|
|
|
import javax.sound.sampled.LineEvent;
|
|
|
|
import javax.sound.sampled.LineListener;
|
|
|
|
|
2014-02-26 08:44:22 +01:00
|
|
|
import org.apache.commons.configuration.ConfigurationException;
|
|
|
|
import org.apache.commons.configuration.PropertiesConfiguration;
|
2014-06-12 07:21:09 +02:00
|
|
|
import org.apache.log4j.LogManager;
|
2014-02-27 04:54:44 +01:00
|
|
|
import org.apache.log4j.Logger;
|
2014-06-12 07:21:09 +02:00
|
|
|
import org.apache.log4j.PropertyConfigurator;
|
2014-02-26 08:44:22 +01:00
|
|
|
|
2014-04-27 19:09:52 +02:00
|
|
|
import com.rarchives.ripme.ripper.AbstractRipper;
|
|
|
|
|
2014-03-09 09:20:22 +01:00
|
|
|
/**
|
|
|
|
* Common utility functions used in various places throughout the project.
|
|
|
|
*/
|
2014-02-26 08:44:22 +01:00
|
|
|
public class Utils {
|
|
|
|
|
2014-03-09 09:20:22 +01:00
|
|
|
public static final String RIP_DIRECTORY = "rips";
|
2014-03-24 16:02:32 +01:00
|
|
|
private static final String configFile = "rip.properties";
|
2014-02-27 04:54:44 +01:00
|
|
|
private static final Logger logger = Logger.getLogger(Utils.class);
|
2014-02-26 08:44:22 +01:00
|
|
|
|
2014-04-06 11:41:04 +02:00
|
|
|
private static PropertiesConfiguration config;
|
2014-02-27 10:28:23 +01:00
|
|
|
static {
|
|
|
|
try {
|
2014-04-06 11:41:04 +02:00
|
|
|
String configPath = getConfigPath();
|
|
|
|
File f = new File(configPath);
|
|
|
|
if (!f.exists()) {
|
|
|
|
// Use default bundled with .jar
|
|
|
|
configPath = configFile;
|
|
|
|
}
|
|
|
|
config = new PropertiesConfiguration(configPath);
|
|
|
|
logger.info("Loaded " + config.getPath());
|
2015-02-21 17:30:58 +01:00
|
|
|
if (f.exists()){
|
|
|
|
// Config was loaded from file
|
|
|
|
if ( !config.containsKey("twitter.auth")
|
|
|
|
|| !config.containsKey("twitter.max_requests")
|
|
|
|
|| !config.containsKey("tumblr.auth")
|
|
|
|
|| !config.containsKey("error.skip404")
|
|
|
|
|| !config.containsKey("gw.api")
|
|
|
|
|| !config.containsKey("page.timeout")
|
|
|
|
|| !config.containsKey("download.max_size")
|
|
|
|
) {
|
|
|
|
// Config is missing key fields
|
|
|
|
// Need to reload the default config
|
|
|
|
// See https://github.com/4pr0n/ripme/issues/158
|
|
|
|
logger.warn("Config does not contain key fields, deleting old config");
|
|
|
|
f.delete();
|
|
|
|
config = new PropertiesConfiguration(configFile);
|
|
|
|
logger.info("Loaded " + config.getPath());
|
|
|
|
}
|
|
|
|
}
|
2014-04-06 11:41:04 +02:00
|
|
|
} catch (Exception e) {
|
2014-02-28 04:49:28 +01:00
|
|
|
logger.error("[!] Failed to load properties file from " + configFile, e);
|
2014-02-27 10:28:23 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-09 09:20:22 +01:00
|
|
|
/**
|
|
|
|
* Get the root rips directory.
|
|
|
|
* @return
|
|
|
|
* Root directory to save rips to.
|
|
|
|
* @throws IOException
|
|
|
|
*/
|
2014-04-06 11:41:04 +02:00
|
|
|
public static File getWorkingDirectory() {
|
|
|
|
String currentDir = ".";
|
|
|
|
try {
|
|
|
|
currentDir = new File(".").getCanonicalPath() + File.separator + RIP_DIRECTORY + File.separator;
|
|
|
|
} catch (IOException e) {
|
|
|
|
logger.error("Error while finding working dir: ", e);
|
|
|
|
}
|
|
|
|
if (config != null) {
|
|
|
|
currentDir = getConfigString("rips.directory", currentDir);
|
|
|
|
}
|
|
|
|
File workingDir = new File(currentDir);
|
2014-02-26 08:44:22 +01:00
|
|
|
if (!workingDir.exists()) {
|
|
|
|
workingDir.mkdirs();
|
|
|
|
}
|
|
|
|
return workingDir;
|
|
|
|
}
|
2014-02-27 04:54:44 +01:00
|
|
|
|
|
|
|
public static String getConfigString(String key, String defaultValue) {
|
2014-02-27 10:28:23 +01:00
|
|
|
return config.getString(key, defaultValue);
|
2014-02-26 08:44:22 +01:00
|
|
|
}
|
2014-02-27 04:54:44 +01:00
|
|
|
public static int getConfigInteger(String key, int defaultValue) {
|
2014-02-27 10:28:23 +01:00
|
|
|
return config.getInt(key, defaultValue);
|
2014-02-26 08:44:22 +01:00
|
|
|
}
|
2014-02-27 04:54:44 +01:00
|
|
|
public static boolean getConfigBoolean(String key, boolean defaultValue) {
|
2014-02-27 10:28:23 +01:00
|
|
|
return config.getBoolean(key, defaultValue);
|
|
|
|
}
|
2014-04-06 12:27:30 +02:00
|
|
|
public static List<String> getConfigList(String key) {
|
|
|
|
List<String> result = new ArrayList<String>();
|
|
|
|
for (Object obj : config.getList(key, new ArrayList<String>())) {
|
|
|
|
if (obj instanceof String) {
|
|
|
|
result.add( (String) obj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
public static void setConfigBoolean(String key, boolean value) { config.setProperty(key, value); }
|
|
|
|
public static void setConfigString(String key, String value) { config.setProperty(key, value); }
|
|
|
|
public static void setConfigInteger(String key, int value) { config.setProperty(key, value); }
|
|
|
|
public static void setConfigList(String key, List<Object> list) {
|
|
|
|
config.clearProperty(key);
|
|
|
|
config.addProperty(key, list);
|
|
|
|
}
|
2015-09-17 12:11:50 +02:00
|
|
|
public static void setConfigList(String key, Enumeration<Object> enumeration) {
|
|
|
|
config.clearProperty(key);
|
|
|
|
List<Object> list = new ArrayList<Object>();
|
|
|
|
while (enumeration.hasMoreElements()) {
|
|
|
|
list.add(enumeration.nextElement());
|
|
|
|
}
|
|
|
|
config.addProperty(key, list);
|
|
|
|
}
|
2014-04-06 12:27:30 +02:00
|
|
|
|
2014-04-06 11:41:04 +02:00
|
|
|
public static void saveConfig() {
|
|
|
|
try {
|
2014-04-06 12:39:30 +02:00
|
|
|
config.save(getConfigPath());
|
|
|
|
logger.info("Saved configuration to " + getConfigPath());
|
2014-04-06 11:41:04 +02:00
|
|
|
} catch (ConfigurationException e) {
|
|
|
|
logger.error("Error while saving configuration: ", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private static String getConfigPath() {
|
2014-04-06 12:39:30 +02:00
|
|
|
try {
|
|
|
|
return new File(".").getCanonicalPath() + File.separator + configFile;
|
|
|
|
} catch (Exception e) {
|
|
|
|
return "." + File.separator + configFile;
|
|
|
|
}
|
2014-02-27 04:54:44 +01:00
|
|
|
}
|
|
|
|
|
2014-02-28 12:04:03 +01:00
|
|
|
/**
|
|
|
|
* Removes the current working directory (CWD) from a File.
|
|
|
|
* @param saveAs
|
|
|
|
* The File path
|
|
|
|
* @return
|
|
|
|
* saveAs in relation to the CWD
|
|
|
|
*/
|
|
|
|
public static String removeCWD(File saveAs) {
|
2015-10-11 22:19:31 +02:00
|
|
|
String prettySaveAs = saveAs.toString();
|
2014-02-28 12:04:03 +01:00
|
|
|
try {
|
2014-04-06 11:41:04 +02:00
|
|
|
prettySaveAs = saveAs.getCanonicalPath();
|
2014-02-28 12:04:03 +01:00
|
|
|
String cwd = new File(".").getCanonicalPath() + File.separator;
|
2014-04-06 11:41:04 +02:00
|
|
|
prettySaveAs = prettySaveAs.replace(
|
2014-02-28 12:04:03 +01:00
|
|
|
cwd,
|
2014-04-06 11:41:04 +02:00
|
|
|
"." + File.separator);
|
2014-02-28 12:04:03 +01:00
|
|
|
} catch (Exception e) {
|
2014-04-06 11:41:04 +02:00
|
|
|
logger.error("Exception: ", e);
|
2014-02-28 12:04:03 +01:00
|
|
|
}
|
|
|
|
return prettySaveAs;
|
|
|
|
}
|
2015-10-11 22:19:31 +02:00
|
|
|
|
2014-03-13 20:13:01 +01:00
|
|
|
public static String stripURLParameter(String url, String parameter) {
|
|
|
|
int paramIndex = url.indexOf("?" + parameter);
|
|
|
|
boolean wasFirstParam = true;
|
|
|
|
if(paramIndex < 0) {
|
|
|
|
wasFirstParam = false;
|
|
|
|
paramIndex = url.indexOf("&" + parameter);
|
|
|
|
}
|
2015-10-11 22:19:31 +02:00
|
|
|
|
2014-03-13 20:13:01 +01:00
|
|
|
if(paramIndex > 0) {
|
|
|
|
int nextParam = url.indexOf("&", paramIndex+1);
|
|
|
|
if(nextParam != -1) {
|
|
|
|
String c = "&";
|
|
|
|
if(wasFirstParam) c = "?";
|
|
|
|
url = url.substring(0, paramIndex) + c + url.substring(nextParam+1, url.length());
|
|
|
|
} else {
|
|
|
|
url = url.substring(0, paramIndex);
|
|
|
|
}
|
|
|
|
}
|
2015-10-11 22:19:31 +02:00
|
|
|
|
2014-03-13 20:13:01 +01:00
|
|
|
return url;
|
|
|
|
}
|
2014-02-28 12:04:03 +01:00
|
|
|
|
2014-03-09 09:20:22 +01:00
|
|
|
/**
|
|
|
|
* Removes the current working directory from a given filename
|
|
|
|
* @param file
|
|
|
|
* @return
|
|
|
|
* 'file' without the leading current working directory
|
|
|
|
*/
|
2014-02-28 12:04:03 +01:00
|
|
|
public static String removeCWD(String file) {
|
|
|
|
return removeCWD(new File(file));
|
|
|
|
}
|
2014-03-04 14:35:35 +01:00
|
|
|
|
2014-03-09 09:20:22 +01:00
|
|
|
/**
|
|
|
|
* Get a list of all Classes within a package.
|
|
|
|
* Works with file system projects and jar files!
|
|
|
|
* Borrowed from StackOverflow, but I don't have a link :[
|
|
|
|
* @param pkgname
|
|
|
|
* The name of the package
|
|
|
|
* @return
|
|
|
|
* List of classes within the package
|
|
|
|
*/
|
2014-03-04 14:35:35 +01:00
|
|
|
public static ArrayList<Class<?>> getClassesForPackage(String pkgname) {
|
|
|
|
ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
|
|
|
|
String relPath = pkgname.replace('.', '/');
|
|
|
|
URL resource = ClassLoader.getSystemClassLoader().getResource(relPath);
|
|
|
|
if (resource == null) {
|
|
|
|
throw new RuntimeException("No resource for " + relPath);
|
|
|
|
}
|
|
|
|
|
|
|
|
String fullPath = resource.getFile();
|
|
|
|
File directory = null;
|
|
|
|
try {
|
|
|
|
directory = new File(resource.toURI());
|
|
|
|
} catch (URISyntaxException e) {
|
|
|
|
throw new RuntimeException(pkgname + " (" + resource + ") does not appear to be a valid URL / URI. Strange, since we got it from the system...", e);
|
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
|
directory = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (directory != null && directory.exists()) {
|
|
|
|
// Get the list of the files contained in the package
|
|
|
|
String[] files = directory.list();
|
|
|
|
for (String file : files) {
|
|
|
|
if (file.endsWith(".class") && !file.contains("$")) {
|
|
|
|
String className = pkgname + '.' + file.substring(0, file.length() - 6);
|
|
|
|
try {
|
|
|
|
classes.add(Class.forName(className));
|
|
|
|
} catch (ClassNotFoundException e) {
|
|
|
|
throw new RuntimeException("ClassNotFoundException loading " + className);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2014-04-21 02:35:17 +02:00
|
|
|
// Load from JAR
|
2014-03-04 14:35:35 +01:00
|
|
|
try {
|
2014-04-05 22:52:27 +02:00
|
|
|
String jarPath = fullPath
|
|
|
|
.replaceFirst("[.]jar[!].*", ".jar")
|
2014-04-30 06:57:56 +02:00
|
|
|
.replaceFirst("file:", "");
|
|
|
|
jarPath = URLDecoder.decode(jarPath, "UTF-8");
|
2014-03-04 14:35:35 +01:00
|
|
|
JarFile jarFile = new JarFile(jarPath);
|
|
|
|
Enumeration<JarEntry> entries = jarFile.entries();
|
|
|
|
while(entries.hasMoreElements()) {
|
2014-04-21 02:35:17 +02:00
|
|
|
JarEntry nextElement = entries.nextElement();
|
|
|
|
String entryName = nextElement.getName();
|
2014-03-04 14:35:35 +01:00
|
|
|
if(entryName.startsWith(relPath)
|
2014-04-21 02:35:17 +02:00
|
|
|
&& entryName.length() > (relPath.length() + "/".length())
|
|
|
|
&& !nextElement.isDirectory()) {
|
2014-03-04 14:35:35 +01:00
|
|
|
String className = entryName.replace('/', '.').replace('\\', '.').replace(".class", "");
|
|
|
|
try {
|
|
|
|
classes.add(Class.forName(className));
|
|
|
|
} catch (ClassNotFoundException e) {
|
2014-04-21 02:35:17 +02:00
|
|
|
logger.error("ClassNotFoundException loading " + className);
|
2014-11-28 16:50:04 +01:00
|
|
|
jarFile.close(); // Resource leak fix?
|
2014-03-04 14:35:35 +01:00
|
|
|
throw new RuntimeException("ClassNotFoundException loading " + className);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-11-28 16:50:04 +01:00
|
|
|
jarFile.close(); // Eclipse said not closing it would have a resource leak
|
2014-03-04 14:35:35 +01:00
|
|
|
} catch (IOException e) {
|
2014-04-05 20:52:25 +02:00
|
|
|
logger.error("Error while loading jar file:", e);
|
2014-03-04 14:35:35 +01:00
|
|
|
throw new RuntimeException(pkgname + " (" + directory + ") does not appear to be a valid package", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return classes;
|
|
|
|
}
|
2015-10-11 22:19:31 +02:00
|
|
|
|
2014-04-06 11:41:04 +02:00
|
|
|
public static final int SHORTENED_PATH_LENGTH = 12;
|
|
|
|
public static String shortenPath(String path) {
|
|
|
|
return shortenPath(new File(path));
|
|
|
|
}
|
|
|
|
public static String shortenPath(File file) {
|
|
|
|
String path = removeCWD(file);
|
|
|
|
if (path.length() < SHORTENED_PATH_LENGTH * 2) {
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
return path.substring(0, SHORTENED_PATH_LENGTH)
|
|
|
|
+ "..."
|
|
|
|
+ path.substring(path.length() - SHORTENED_PATH_LENGTH);
|
2014-04-05 10:39:10 +02:00
|
|
|
}
|
2015-10-11 22:19:31 +02:00
|
|
|
|
2014-04-12 07:35:46 +02:00
|
|
|
public static String filesystemSafe(String text) {
|
2014-04-25 18:42:54 +02:00
|
|
|
text = text.replaceAll("[^a-zA-Z0-9.-]", "_")
|
2014-04-12 07:35:46 +02:00
|
|
|
.replaceAll("__", "_")
|
|
|
|
.replaceAll("_+$", "");
|
2014-06-25 09:26:57 +02:00
|
|
|
if (text.length() > 100) {
|
|
|
|
text = text.substring(0, 99);
|
2014-04-25 18:42:54 +02:00
|
|
|
}
|
|
|
|
return text;
|
2014-04-12 07:35:46 +02:00
|
|
|
}
|
2015-10-11 22:19:31 +02:00
|
|
|
|
2014-04-20 07:41:11 +02:00
|
|
|
public static String bytesToHumanReadable(int bytes) {
|
|
|
|
float fbytes = (float) bytes;
|
|
|
|
String[] mags = new String[] {"", "k", "m", "g", "t"};
|
|
|
|
int magIndex = 0;
|
|
|
|
while (fbytes >= 1024) {
|
|
|
|
fbytes /= 1024;
|
|
|
|
magIndex++;
|
|
|
|
}
|
|
|
|
return String.format("%.2f%sb", fbytes, mags[magIndex]);
|
|
|
|
}
|
2014-04-27 19:09:52 +02:00
|
|
|
|
|
|
|
public static List<String> getListOfAlbumRippers() throws Exception {
|
|
|
|
List<String> list = new ArrayList<String>();
|
|
|
|
for (Constructor<?> ripper : AbstractRipper.getRipperConstructors("com.rarchives.ripme.ripper.rippers")) {
|
|
|
|
list.add(ripper.getName());
|
|
|
|
}
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
public static List<String> getListOfVideoRippers() throws Exception {
|
|
|
|
List<String> list = new ArrayList<String>();
|
|
|
|
for (Constructor<?> ripper : AbstractRipper.getRipperConstructors("com.rarchives.ripme.ripper.rippers.video")) {
|
|
|
|
list.add(ripper.getName());
|
|
|
|
}
|
|
|
|
return list;
|
|
|
|
}
|
2014-05-11 09:38:15 +02:00
|
|
|
|
|
|
|
public static void playSound(String filename) {
|
|
|
|
URL resource = ClassLoader.getSystemClassLoader().getResource(filename);
|
|
|
|
try {
|
|
|
|
final Clip clip = (Clip) AudioSystem.getLine(new Line.Info(Clip.class));
|
|
|
|
clip.addLineListener(new LineListener() {
|
|
|
|
@Override
|
|
|
|
public void update(LineEvent event) {
|
|
|
|
if (event.getType() == LineEvent.Type.STOP) {
|
|
|
|
clip.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
clip.open(AudioSystem.getAudioInputStream(resource));
|
|
|
|
clip.start();
|
|
|
|
} catch (Exception e) {
|
|
|
|
logger.error("Failed to play sound " + filename, e);
|
|
|
|
}
|
|
|
|
}
|
2014-06-12 07:21:09 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Configures root logger, either for FILE output or just console.
|
|
|
|
*/
|
|
|
|
public static void configureLogger() {
|
|
|
|
LogManager.shutdown();
|
|
|
|
String logFile;
|
|
|
|
if (getConfigBoolean("log.save", false)) {
|
|
|
|
logFile = "log4j.file.properties";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
logFile = "log4j.properties";
|
|
|
|
}
|
|
|
|
InputStream stream = Utils.class.getClassLoader().getResourceAsStream(logFile);
|
|
|
|
if (stream == null) {
|
|
|
|
PropertyConfigurator.configure("src/main/resources/" + logFile);
|
|
|
|
} else {
|
|
|
|
PropertyConfigurator.configure(stream);
|
|
|
|
}
|
|
|
|
logger.info("Loaded " + logFile);
|
2015-01-11 14:11:10 +01:00
|
|
|
try {
|
|
|
|
stream.close();
|
|
|
|
} catch (IOException e) { }
|
2014-06-12 07:21:09 +02:00
|
|
|
}
|
|
|
|
|
2014-06-26 08:01:07 +02:00
|
|
|
/**
|
|
|
|
* Gets list of strings between two strings.
|
|
|
|
* @param fullText Text to retrieve from.
|
|
|
|
* @param start String that precedes the desired text
|
|
|
|
* @param finish String that follows the desired text
|
|
|
|
* @return List of all strings that are between 'start' and 'finish'
|
|
|
|
*/
|
|
|
|
public static List<String> between(String fullText, String start, String finish) {
|
|
|
|
List<String> result = new ArrayList<String>();
|
|
|
|
int i, j;
|
|
|
|
i = fullText.indexOf(start);
|
|
|
|
while (i >= 0) {
|
|
|
|
i += start.length();
|
|
|
|
j = fullText.indexOf(finish, i);
|
|
|
|
if (j < 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
result.add(fullText.substring(i, j));
|
|
|
|
i = fullText.indexOf(start, j + finish.length());
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
2015-10-11 22:19:31 +02:00
|
|
|
}
|