diff --git a/.gitignore b/.gitignore
index 6143e53..e99d622 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,3 +20,18 @@
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
+
+.idea/workspace.xml
+.idea/**/gradle.xml
+.idea/**/libraries
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.xml
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/dictionaries
+.idea_modules/
diff --git a/.idea/artifacts/JDHttpApi_jar.xml b/.idea/artifacts/JDHttpApi_jar.xml
new file mode 100644
index 0000000..9f8f958
--- /dev/null
+++ b/.idea/artifacts/JDHttpApi_jar.xml
@@ -0,0 +1,14 @@
+
+
+ $PROJECT_DIR$/out/artifacts/JDHttpApi_jar
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..30b350b
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Core.xml b/.idea/libraries/Core.xml
new file mode 100644
index 0000000..26fb12d
--- /dev/null
+++ b/.idea/libraries/Core.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..5755a99
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..eaf9e53
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JDHttpApi.iml b/JDHttpApi.iml
new file mode 100644
index 0000000..2cc930b
--- /dev/null
+++ b/JDHttpApi.iml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index ad42820..b3f455d 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,127 @@
# JDHttpAPI
JDownloader2 plugin with a local HTTP API to add new files for download
+
+This plugin is loaded by JDownloader2, which then starts up an embedded Jetty
+HTTP server to receive
+
+From there, just about anything can send requests to queue up a new link. I
+like to use [Tampermonkey userscripts](https://tampermonkey.net/) to scrape
+links directly from web pages as I browse.
+
+Note: it binds to your IP address, therefore other PCs on the network can add
+links. Configure a password or update the code to bind to something else -
+there is not currently a way configure local-only access. This plugin also
+accepts all Origins over ajax.
+
+## Install
+
+1. Close JDownloader.
+2. Build or download the `JDHttpApi.jar` file.
+3. Place that file in `./extensions/` inside the JDownloader2 program folder.
+3. Open the file `./tmp/extensioncache/extensionInfos.json` in your JD program
+ folder and insert the following JSON as a new element in the array:
+
+```
+{
+ "settings" : true,
+ "configInterface" : "org.jdownloader.extensions.httpAPI.HttpAPIConfig",
+ "quickToggle" : false,
+ "headlessRunnable" : true,
+ "description" : "Http API.",
+ "lng" : "en_US",
+ "iconPath" : "folder_add",
+ "linuxRunnable" : true,
+ "macRunnable" : true,
+ "name" : "HTTP API",
+ "version" : -1,
+ "windowsRunnable" : true,
+ "classname" : "org.jdownloader.extensions.httpAPI.HttpAPIExtension",
+ "jarPath" : "/absolute/path/to/jd2/extensions/JDHttpApi.jar"
+}
+```
+
+4. Open the file `./update/versioninfo/JD/extensions.installed.json` inside the
+ JD program folder and insert the string `"jdhttpapi"` as the last element
+ in the JSON array.
+5. Start JDownloader2 and go to the settings page to enable the extension.
+
+Note: there is no official extension install process, so most of this is
+tricking JD into thinking the JAR is already installed. It's possible that
+an update will trigger a cache invalidation that boots out this extension. Just
+reapply the steps above and you should get it back.
+
+## Configure
+
+This plugin has four settings to configure through the JDownloader GUI. In order
+to make changes take effect, disable and then re-enable the extension.
+
+1. Use a password: require password authentication.
+2. Port: the port that the HTTP server listens on. Defaults to 8297.
+3. Password: If you've enabled the password feature, set it here.
+4. Allow Get: This disables HTTP GET access to the API. When enabled, you
+ must POST new links as JSON. This can help you reduce exposure to CSRF
+ vulnerabilities, especially when combined with a password.
+
+## Use
+
+There is currently only one URL: `/addLink`. You may submit via POST or GET.
+
+### GET Service
+
+There are three parameters, only `url` is required:
+
+* `url`: The URL to add.
+* `packageName`: If you want to configure a custom package name, send it here.
+* `forcePackageName`: Set this to `true` to set the package name. For whatever
+ reason, this is a separate field in JD's internals but if you don't force
+ it, the package name will not be changed. It's possible I am hooking in too
+ late in the process.
+
+The response has three possible values:
+
+On success: `{"success":true}`
+On malformed input: `{"errorMessage":"some error message"}`
+On authentication failure: `Login to access API` (this is not JSON)
+
+CURL Examples:
+
+```
+curl 'http://localhost:8297/addLink?url=https://i.imgur.com/muChjiN.jpg'
+curl 'http://localhost:8297/addLink?url=https://i.imgur.com/muChjiN.jpg&packageName=cutebunny&forcePackageName=true'
+```
+
+### POST Service
+
+Send a JSON object via POST with the same values as in the GET request:
+
+```
+curl -X POST 'http://localhost:8297/addLink' \
+ -d '{"url":"https://i.imgur.com/muChjiN.jpg"}'
+curl -X POST 'http://localhost:8297/addLink' \
+ -d '{"url":"https://i.imgur.com/muChjiN.jpg","packageName":"cutebunny","forcePackageName":true}'
+```
+
+### Authentication
+
+If you choose to use a password, send it as the password portion of HTTP Basic
+Authentication - leave the username blank.
+
+CURL Example:
+
+```
+curl -u ':mypassword' 'http://192.168.1.7:8297/addLink?url=https://i.imgur.com/muChjiN.jpg'
+curl -u ':mypassword' -X POST 'http://localhost:8297/addLink' \
+ -d '{"url":"https://i.imgur.com/muChjiN.jpg"}'
+```
+
+## Errata
+
+JDownloader2's extension system is surprisingly
+modular and easy to understand (aside from the install process). Feel free to
+use this project as an example for building other JD extensions as even the
+built-in ones are a bit more complex than this. Just make sure to have
+[the source code](https://svn.jdownloader.org/projects/jd) open up in
+another window for reference - there is virtually no documentation available
+and this project only uses the bare minimum of features.
+
+
diff --git a/lib/Core.jar b/lib/Core.jar
new file mode 100644
index 0000000..c8022fd
Binary files /dev/null and b/lib/Core.jar differ
diff --git a/lib/JDGUI.jar b/lib/JDGUI.jar
new file mode 100644
index 0000000..57a0f90
Binary files /dev/null and b/lib/JDGUI.jar differ
diff --git a/lib/JDownloader.jar b/lib/JDownloader.jar
new file mode 100644
index 0000000..9505d39
Binary files /dev/null and b/lib/JDownloader.jar differ
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..29db9b6
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,24 @@
+
+
+ 4.0.0
+
+ jdownloaderPlugins
+ JDownloaderPlugins
+ 1.0-SNAPSHOT
+
+
+
+ org.eclipse.jetty
+ jetty-server
+ 9.4.7.v20170914
+
+
+ com.google.code.gson
+ gson
+ 2.8.2
+
+
+
+
\ No newline at end of file
diff --git a/settings-screenshot.png b/settings-screenshot.png
new file mode 100644
index 0000000..a67b471
Binary files /dev/null and b/settings-screenshot.png differ
diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..f971d52
--- /dev/null
+++ b/src/main/java/META-INF/MANIFEST.MF
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+Class-Path: jetty-io-9.4.7.v20170914.jar jetty-server-9.4.7.v20170914.
+ jar Core.jar JDownloader.jar JDGUI.jar gson-2.8.2.jar jetty-http-9.4.
+ 7.v20170914.jar javax.servlet-api-3.1.0.jar jetty-util-9.4.7.v2017091
+ 4.jar
+
diff --git a/src/main/java/org/jdownloader/extensions/httpAPI/CFG_HTTPAPI.java b/src/main/java/org/jdownloader/extensions/httpAPI/CFG_HTTPAPI.java
new file mode 100644
index 0000000..ab175a0
--- /dev/null
+++ b/src/main/java/org/jdownloader/extensions/httpAPI/CFG_HTTPAPI.java
@@ -0,0 +1,29 @@
+package org.jdownloader.extensions.httpAPI;
+
+import org.appwork.storage.config.handler.BooleanKeyHandler;
+import org.appwork.storage.config.handler.IntegerKeyHandler;
+import org.appwork.storage.config.handler.StorageHandler;
+import org.appwork.storage.config.handler.StringKeyHandler;
+import org.appwork.utils.Application;
+import org.appwork.storage.config.ConfigUtils;
+import org.appwork.storage.config.JsonConfig;
+
+public class CFG_HTTPAPI {
+ public static void main(String[] args) {
+ ConfigUtils.printStaticMappings(HttpAPIConfig.class, "Application.getResource(\"cfg/\" + " + HttpAPIExtension.class.getSimpleName() + ".class.getName())");
+ }
+
+ public static final HttpAPIConfig CFG = JsonConfig.create(Application.getResource("cfg/" + HttpAPIExtension.class.getName()), HttpAPIConfig.class);
+
+ public static final StorageHandler SH = (StorageHandler) CFG._getStorageHandler();
+
+ public static final BooleanKeyHandler ENABLED = SH.getKeyHandler("Enabled", BooleanKeyHandler.class);
+
+ public static final IntegerKeyHandler PORT = SH.getKeyHandler("Port", IntegerKeyHandler.class);
+
+ public static final BooleanKeyHandler ALLOW_GET = SH.getKeyHandler("AllowGet", BooleanKeyHandler.class);
+
+ public static final BooleanKeyHandler USE_PASSWORD = SH.getKeyHandler("UsePassword", BooleanKeyHandler.class);
+
+ public static final StringKeyHandler PASSWORD = SH.getKeyHandler("Password", StringKeyHandler.class);
+}
diff --git a/src/main/java/org/jdownloader/extensions/httpAPI/HttpAPIConfig.java b/src/main/java/org/jdownloader/extensions/httpAPI/HttpAPIConfig.java
new file mode 100644
index 0000000..09e271b
--- /dev/null
+++ b/src/main/java/org/jdownloader/extensions/httpAPI/HttpAPIConfig.java
@@ -0,0 +1,28 @@
+package org.jdownloader.extensions.httpAPI;
+
+import jd.plugins.ExtensionConfigInterface;
+import org.appwork.storage.config.annotations.AboutConfig;
+import org.appwork.storage.config.annotations.DefaultBooleanValue;
+import org.appwork.storage.config.annotations.DefaultIntValue;
+
+public interface HttpAPIConfig extends ExtensionConfigInterface {
+
+ @AboutConfig
+ @DefaultIntValue(8297)
+ int getPort();
+ void setPort(int port);
+
+ @AboutConfig
+ @DefaultBooleanValue(false)
+ boolean getAllowGet();
+ void setAllowGet(boolean enabled);
+
+ @AboutConfig
+ @DefaultBooleanValue(false)
+ boolean getUsePassword();
+ void setUsePassword(boolean enabled);
+
+ @AboutConfig
+ String getPassword();
+ void setPassword(String password);
+}
diff --git a/src/main/java/org/jdownloader/extensions/httpAPI/HttpAPIConfigPanel.java b/src/main/java/org/jdownloader/extensions/httpAPI/HttpAPIConfigPanel.java
new file mode 100644
index 0000000..17e38a6
--- /dev/null
+++ b/src/main/java/org/jdownloader/extensions/httpAPI/HttpAPIConfigPanel.java
@@ -0,0 +1,31 @@
+package org.jdownloader.extensions.httpAPI;
+
+
+import org.jdownloader.extensions.ExtensionConfigPanel;
+
+import jd.gui.swing.jdgui.views.settings.panels.advanced.AdvancedConfigTableModel;
+import jd.gui.swing.jdgui.views.settings.panels.advanced.AdvancedTable;
+
+public class HttpAPIConfigPanel extends ExtensionConfigPanel {
+
+ private AdvancedConfigTableModel model;
+
+ public HttpAPIConfigPanel(HttpAPIExtension extension){
+ super(extension);
+
+ add(new AdvancedTable(model= new AdvancedConfigTableModel("HttpAPIConfigPanel"){
+ @Override
+ public void refresh(String filterText){ _fireTableStructureChanged(register(), true);}
+ }));
+ model.refresh("HttpAPIConfigPanel");
+ }
+
+ @Override
+ public void save() {
+ }
+
+ @Override
+ public void updateContents() {
+
+ }
+}
diff --git a/src/main/java/org/jdownloader/extensions/httpAPI/HttpAPIExtension.java b/src/main/java/org/jdownloader/extensions/httpAPI/HttpAPIExtension.java
new file mode 100644
index 0000000..b7dafb0
--- /dev/null
+++ b/src/main/java/org/jdownloader/extensions/httpAPI/HttpAPIExtension.java
@@ -0,0 +1,125 @@
+package org.jdownloader.extensions.httpAPI;
+
+import jd.controlling.linkcollector.LinkCollector;
+import org.appwork.storage.config.ValidationException;
+import org.appwork.utils.Application;
+import jd.plugins.AddonPanel;
+import org.appwork.storage.config.events.GenericConfigEventListener;
+import org.appwork.storage.config.handler.KeyHandler;
+import org.appwork.utils.logging2.LogSource;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.HandlerList;
+import org.jdownloader.extensions.AbstractExtension;
+import org.jdownloader.extensions.StartException;
+import org.jdownloader.extensions.StopException;
+import org.jdownloader.extensions.httpAPI.handlers.AjaxHandler;
+import org.jdownloader.extensions.httpAPI.handlers.AuthorizationHandler;
+import org.jdownloader.extensions.httpAPI.handlers.JDServerGETHandler;
+import org.jdownloader.extensions.httpAPI.handlers.JDServerPOSTHandler;
+import org.jdownloader.gui.IconKey;
+import org.jdownloader.logging.LogController;
+
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+
+public class HttpAPIExtension extends AbstractExtension implements Runnable, GenericConfigEventListener {
+ private LogSource logger;
+ private HttpAPIConfigPanel configPanel;
+ private Server server;
+
+ @Override
+ protected void initExtension() throws StartException {
+ logger = LogController.CL(HttpAPIExtension.class);
+ if (!Application.isHeadless()) {
+ configPanel = new HttpAPIConfigPanel(this);
+ }
+ }
+
+ @Override
+ protected void start() throws StartException {
+ CFG_HTTPAPI.PORT.getEventSender().addListener(this, true);
+ startServer();
+ }
+
+ protected void stop() throws StopException {
+ //ContainerPluginController.getInstance().remove(plugin.getAndSet(null));
+ stopServer();
+ }
+
+ @Override
+ public String getIconKey() {
+ return IconKey.ICON_FOLDER_ADD;
+ }
+
+
+ public void run() {
+ startServer();
+ }
+
+ @Override
+ public boolean isHeadlessRunnable() {
+ return true;
+ }
+
+ @Override
+ public boolean hasConfigPanel() {
+ return true;
+ }
+
+ @Override
+ public HttpAPIConfigPanel getConfigPanel() {
+ return configPanel;
+ }
+
+ @Override
+ public AddonPanel getGUI() {
+ return null;
+ }
+
+ @Override
+ public String getDescription() {
+ return T.description();
+ }
+
+ public void onConfigValidatorError(KeyHandler keyHandler, Integer invalidValue, ValidationException validateException) {
+ }
+
+ public synchronized void onConfigValueModified(KeyHandler keyHandler, Integer newValue) {
+ stopServer();
+ startServer();
+ }
+
+ private void startServer() {
+ HttpAPIConfig cfg = getSettings();
+ server = new Server(cfg.getPort());
+ HandlerList lst = new HandlerList();
+ LinkController ctr = new JDLinkController(LinkCollector.getInstance());
+ if(cfg.getUsePassword() && cfg.getPassword() != null && !cfg.getPassword().equals("")) {
+ lst.addHandler(new AuthorizationHandler(cfg.getPassword()));
+ }
+ lst.addHandler(new AjaxHandler(cfg.getAllowGet()));
+ if(cfg.getAllowGet()) {
+ lst.addHandler(new JDServerGETHandler(ctr));
+ }
+ lst.addHandler(new JDServerPOSTHandler(ctr));
+ server.setHandler(lst);
+ try {
+ server.start();
+ }
+ catch(Exception e) {
+ logger.log(new LogRecord(Level.SEVERE, e.getMessage()));
+ }
+ }
+
+ private void stopServer() {
+ if(server != null) {
+ try {
+ server.stop();
+ }
+ catch(Exception e) {
+ logger.log(new LogRecord(Level.SEVERE, e.getMessage()));
+ }
+ }
+ server = null;
+ }
+}
diff --git a/src/main/java/org/jdownloader/extensions/httpAPI/HttpAPITranslation.java b/src/main/java/org/jdownloader/extensions/httpAPI/HttpAPITranslation.java
new file mode 100644
index 0000000..7c8ff61
--- /dev/null
+++ b/src/main/java/org/jdownloader/extensions/httpAPI/HttpAPITranslation.java
@@ -0,0 +1,14 @@
+package org.jdownloader.extensions.httpAPI;
+
+import org.appwork.txtresource.Default;
+import org.appwork.txtresource.Defaults;
+import org.appwork.txtresource.TranslateInterface;
+
+@Defaults(lngs = { "en" })
+public interface HttpAPITranslation extends TranslateInterface {
+ @Default(lngs = { "en" }, values = { "HTTP API" })
+ String title();
+
+ @Default(lngs = { "en" }, values = { "Bundled HTTP server to add new files" })
+ String description();
+}
diff --git a/src/main/java/org/jdownloader/extensions/httpAPI/JDLinkController.java b/src/main/java/org/jdownloader/extensions/httpAPI/JDLinkController.java
new file mode 100644
index 0000000..cf20627
--- /dev/null
+++ b/src/main/java/org/jdownloader/extensions/httpAPI/JDLinkController.java
@@ -0,0 +1,28 @@
+package org.jdownloader.extensions.httpAPI;
+
+import jd.controlling.linkcollector.LinkCollectingJob;
+import jd.controlling.linkcollector.LinkCollector;
+import jd.controlling.linkcollector.LinkOrigin;
+import jd.controlling.linkcollector.LinkOriginDetails;
+import jd.controlling.linkcrawler.CrawledLink;
+import jd.controlling.linkcrawler.CrawledLinkModifier;
+import jd.controlling.linkcrawler.modifier.PackageNameModifier;
+
+public class JDLinkController implements LinkController {
+ private LinkCollector collector;
+
+ public JDLinkController(LinkCollector collector){
+ this.collector = collector;
+ }
+
+ public void AddLink(String url) {
+ LinkCollectingJob job = new LinkCollectingJob(LinkOriginDetails.getInstance(LinkOrigin.EXTENSION, "HTTPAPI"), url);
+ collector.addCrawlerJob(job);
+ }
+
+ public void AddLink(String url, String packageName, boolean forcePackageName) {
+ LinkCollectingJob job = new LinkCollectingJob(LinkOriginDetails.getInstance(LinkOrigin.EXTENSION, "HTTPAPI"), url);
+ job.addPostPackagizerModifier(new PackageNameModifier(packageName, forcePackageName));
+ collector.addCrawlerJob(job);
+ }
+}
diff --git a/src/main/java/org/jdownloader/extensions/httpAPI/LinkController.java b/src/main/java/org/jdownloader/extensions/httpAPI/LinkController.java
new file mode 100644
index 0000000..8039b04
--- /dev/null
+++ b/src/main/java/org/jdownloader/extensions/httpAPI/LinkController.java
@@ -0,0 +1,8 @@
+package org.jdownloader.extensions.httpAPI;
+
+public interface LinkController {
+
+ public void AddLink(String url);
+
+ public void AddLink(String url, String packageName, boolean forcePackageName);
+}
diff --git a/src/main/java/org/jdownloader/extensions/httpAPI/ParseException.java b/src/main/java/org/jdownloader/extensions/httpAPI/ParseException.java
new file mode 100644
index 0000000..189b8f0
--- /dev/null
+++ b/src/main/java/org/jdownloader/extensions/httpAPI/ParseException.java
@@ -0,0 +1,7 @@
+package org.jdownloader.extensions.httpAPI;
+
+public class ParseException extends Exception{
+ public ParseException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/org/jdownloader/extensions/httpAPI/handlers/AjaxHandler.java b/src/main/java/org/jdownloader/extensions/httpAPI/handlers/AjaxHandler.java
new file mode 100644
index 0000000..92b6387
--- /dev/null
+++ b/src/main/java/org/jdownloader/extensions/httpAPI/handlers/AjaxHandler.java
@@ -0,0 +1,39 @@
+package org.jdownloader.extensions.httpAPI.handlers;
+
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+public class AjaxHandler extends AbstractHandler {
+ private final boolean allowGet;
+
+ public AjaxHandler(boolean allowGet) {
+ this.allowGet = allowGet;
+ }
+
+ public void handle(String target,
+ Request baseRequest,
+ HttpServletRequest request,
+ HttpServletResponse response) throws IOException, ServletException {
+ if(baseRequest.getMethod().equals("OPTIONS")) {
+
+ response.setStatus(HttpServletResponse.SC_OK);
+ response.setHeader("Access-Control-Allow-Origin", "*");
+
+ String methods = "POST, OPTIONS";
+ if(allowGet) methods += ", GET";
+ response.setHeader("Access-Control-Allow-Methods", methods);
+ response.setHeader("Access-Control-Max-Age", "1000");
+ String req = request.getHeader("Access-Control-Request-Headers");
+ if(req != null) {
+ response.setHeader("Access-Control-Allow-Headers", req);
+ }
+
+ baseRequest.setHandled(true);
+ }
+ }
+}
diff --git a/src/main/java/org/jdownloader/extensions/httpAPI/handlers/AuthorizationHandler.java b/src/main/java/org/jdownloader/extensions/httpAPI/handlers/AuthorizationHandler.java
new file mode 100644
index 0000000..383dd57
--- /dev/null
+++ b/src/main/java/org/jdownloader/extensions/httpAPI/handlers/AuthorizationHandler.java
@@ -0,0 +1,38 @@
+package org.jdownloader.extensions.httpAPI.handlers;
+
+import org.appwork.utils.encoding.Base64;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+public class AuthorizationHandler extends AbstractHandler {
+ private final String password;
+ private final String authenticationHeader;
+
+ public AuthorizationHandler(String password) {
+ this.password = password;
+ authenticationHeader = "Basic " + Base64.encode(":" + password);
+ }
+
+ public void handle(String target,
+ Request baseRequest,
+ HttpServletRequest request,
+ HttpServletResponse response) throws IOException, ServletException {
+ String header = request.getHeader("Authorization");
+ if(header == null || !header.equals(authenticationHeader)) {
+ response.addHeader("WWW-Authenticate", "Basic");
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+
+ response.setContentType("text/plain; charset=utf-8");
+ PrintWriter out = response.getWriter();
+ out.println("Login to access API");
+
+ baseRequest.setHandled(true);
+ }
+ }
+}
diff --git a/src/main/java/org/jdownloader/extensions/httpAPI/handlers/BaseHandler.java b/src/main/java/org/jdownloader/extensions/httpAPI/handlers/BaseHandler.java
new file mode 100644
index 0000000..8005d6b
--- /dev/null
+++ b/src/main/java/org/jdownloader/extensions/httpAPI/handlers/BaseHandler.java
@@ -0,0 +1,89 @@
+package org.jdownloader.extensions.httpAPI.handlers;
+
+import com.google.gson.Gson;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.jdownloader.extensions.httpAPI.LinkController;
+import org.jdownloader.extensions.httpAPI.models.AddLinkRequest;
+import org.jdownloader.extensions.httpAPI.models.AddLinkResponse;
+import org.jdownloader.extensions.httpAPI.ParseException;
+import org.jdownloader.extensions.httpAPI.models.ErrorResponse;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+public abstract class BaseHandler extends AbstractHandler {
+
+ protected final Gson jparser = new Gson();
+
+ protected final LinkController controller;
+
+ protected BaseHandler(LinkController ctr) {
+ super();
+ controller = ctr;
+ }
+
+ protected abstract AddLinkRequest parseAddLinkParams(HttpServletRequest req) throws ParseException;
+
+ protected abstract String getAllowedMethod();
+
+ private void writeResponse(Request baseRequest, HttpServletResponse response, Object data) throws IOException{
+ response.setStatus(HttpServletResponse.SC_OK);
+ response.setContentType("application/json; charset=utf-8");
+
+ String origin = baseRequest.getHeader("Origin");
+ if(origin != null) {
+ response.setHeader("Access-Control-Allow-Origin", origin);
+ }
+
+ PrintWriter out = response.getWriter();
+ out.println(jparser.toJson(data));
+ baseRequest.setHandled(true);
+ }
+
+ private void writeError(Request baseRequest, HttpServletResponse response, String message) throws IOException{
+ response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ response.setContentType("application/json; charset=utf-8");
+ ErrorResponse resp = new ErrorResponse();
+ resp.errorMessage = message;
+ PrintWriter out = response.getWriter();
+ out.println(jparser.toJson(resp));
+ baseRequest.setHandled(true);
+ }
+
+ public void handle(String target,
+ Request baseRequest,
+ HttpServletRequest request,
+ HttpServletResponse response) throws IOException, ServletException {
+ if(!baseRequest.getMethod().equals(getAllowedMethod())) {
+ return;
+ }
+
+ String path = request.getPathInfo();
+
+ if(path.equals("/addLink")) {
+ AddLinkRequest data;
+ try {
+ data = parseAddLinkParams(request);
+ }
+ catch (ParseException e) {
+ writeError(baseRequest, response, e.getMessage());
+ return;
+ }
+
+ if(data.packageName != null && !data.packageName.equals("")) {
+ controller.AddLink(data.url.toString(), data.packageName, data.forcePackageName);
+ }
+ else {
+ controller.AddLink(data.url.toString());
+ }
+
+ AddLinkResponse resp = new AddLinkResponse();
+ resp.success = true;
+ writeResponse(baseRequest, response, resp);
+ }
+ }
+}
diff --git a/src/main/java/org/jdownloader/extensions/httpAPI/handlers/JDServerGETHandler.java b/src/main/java/org/jdownloader/extensions/httpAPI/handlers/JDServerGETHandler.java
new file mode 100644
index 0000000..069a08f
--- /dev/null
+++ b/src/main/java/org/jdownloader/extensions/httpAPI/handlers/JDServerGETHandler.java
@@ -0,0 +1,49 @@
+package org.jdownloader.extensions.httpAPI.handlers;
+
+
+import org.jdownloader.extensions.httpAPI.LinkController;
+import org.jdownloader.extensions.httpAPI.models.AddLinkRequest;
+import org.jdownloader.extensions.httpAPI.ParseException;
+
+import javax.servlet.http.HttpServletRequest;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+
+public class JDServerGETHandler extends BaseHandler {
+
+ public JDServerGETHandler(LinkController ctr) {
+ super(ctr);
+ }
+
+ protected AddLinkRequest parseAddLinkParams(HttpServletRequest req) throws ParseException{
+ AddLinkRequest data = new AddLinkRequest();
+
+ try {
+ URL url = new URL(req.getParameter("url"));
+ if (url == null || url.equals("")) {
+ throw new ParseException("Missing parameter 'url'");
+ }
+ data.url = url;
+ }
+ catch(MalformedURLException e) {
+ throw new ParseException("Parameter 'url' is malformed");
+ }
+
+ String pkg = req.getParameter("packageName");
+ if(pkg != null && !pkg.equals("")) {
+ data.packageName = pkg;
+ }
+
+ String force = req.getParameter("forcePackageName");
+ if(force != null && force.equals("true")) {
+ data.forcePackageName = true;
+ }
+
+ return data;
+ }
+
+ protected String getAllowedMethod() {
+ return "GET";
+ }
+}
diff --git a/src/main/java/org/jdownloader/extensions/httpAPI/handlers/JDServerPOSTHandler.java b/src/main/java/org/jdownloader/extensions/httpAPI/handlers/JDServerPOSTHandler.java
new file mode 100644
index 0000000..4f143ad
--- /dev/null
+++ b/src/main/java/org/jdownloader/extensions/httpAPI/handlers/JDServerPOSTHandler.java
@@ -0,0 +1,39 @@
+package org.jdownloader.extensions.httpAPI.handlers;
+
+
+import com.google.gson.JsonSyntaxException;
+import org.jdownloader.extensions.httpAPI.LinkController;
+import org.jdownloader.extensions.httpAPI.ParseException;
+import org.jdownloader.extensions.httpAPI.models.AddLinkRequest;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+
+public class JDServerPOSTHandler extends BaseHandler {
+
+ public JDServerPOSTHandler(LinkController ctr) {
+ super(ctr);
+ }
+
+ protected AddLinkRequest parseAddLinkParams(HttpServletRequest req) throws ParseException{
+ try {
+ AddLinkRequest data = jparser.fromJson(req.getReader(), AddLinkRequest.class);
+
+ if (data.url == null || data.url.equals("")) {
+ throw new ParseException("Missing parameter 'url'");
+ }
+
+ return data;
+ }
+ catch(IOException e) {
+ throw new ParseException(e.getMessage());
+ }
+ catch(JsonSyntaxException e) {
+ throw new ParseException(e.getMessage());
+ }
+ }
+
+ protected String getAllowedMethod() {
+ return "POST";
+ }
+}
diff --git a/src/main/java/org/jdownloader/extensions/httpAPI/models/AddLinkRequest.java b/src/main/java/org/jdownloader/extensions/httpAPI/models/AddLinkRequest.java
new file mode 100644
index 0000000..290c3b5
--- /dev/null
+++ b/src/main/java/org/jdownloader/extensions/httpAPI/models/AddLinkRequest.java
@@ -0,0 +1,12 @@
+package org.jdownloader.extensions.httpAPI.models;
+
+import java.net.URL;
+
+public class AddLinkRequest {
+
+ public URL url;
+
+ public String packageName = null;
+
+ public boolean forcePackageName = false;
+}
diff --git a/src/main/java/org/jdownloader/extensions/httpAPI/models/AddLinkResponse.java b/src/main/java/org/jdownloader/extensions/httpAPI/models/AddLinkResponse.java
new file mode 100644
index 0000000..4c6afa2
--- /dev/null
+++ b/src/main/java/org/jdownloader/extensions/httpAPI/models/AddLinkResponse.java
@@ -0,0 +1,7 @@
+package org.jdownloader.extensions.httpAPI.models;
+
+public class AddLinkResponse {
+ public boolean success;
+
+ public String errorMessage;
+}
diff --git a/src/main/java/org/jdownloader/extensions/httpAPI/models/ErrorResponse.java b/src/main/java/org/jdownloader/extensions/httpAPI/models/ErrorResponse.java
new file mode 100644
index 0000000..cdbf80d
--- /dev/null
+++ b/src/main/java/org/jdownloader/extensions/httpAPI/models/ErrorResponse.java
@@ -0,0 +1,5 @@
+package org.jdownloader.extensions.httpAPI.models;
+
+public class ErrorResponse {
+ public String errorMessage;
+}
diff --git a/src/main/java/org/jdownloader/sample/Program.java b/src/main/java/org/jdownloader/sample/Program.java
new file mode 100644
index 0000000..7b3ba84
--- /dev/null
+++ b/src/main/java/org/jdownloader/sample/Program.java
@@ -0,0 +1,36 @@
+package org.jdownloader.sample;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.HandlerList;
+import org.jdownloader.extensions.httpAPI.LinkController;
+import org.jdownloader.extensions.httpAPI.handlers.AjaxHandler;
+import org.jdownloader.extensions.httpAPI.handlers.AuthorizationHandler;
+import org.jdownloader.extensions.httpAPI.handlers.JDServerGETHandler;
+import org.jdownloader.extensions.httpAPI.handlers.JDServerPOSTHandler;
+
+
+public class Program {
+ public static void main(String[] args) {
+ int port = 8297;
+ HandlerList lst = new HandlerList();
+
+ String password = null;//"pass";
+ Server server = new Server(port);
+ JDServerPOSTHandler hnd;
+ LinkController ctr = new SampleLinkController();
+ if(password != null) {
+ lst.addHandler(new AuthorizationHandler(password));
+ }
+ lst.addHandler(new AjaxHandler(true));
+ lst.addHandler(new JDServerGETHandler(ctr));
+ lst.addHandler(new JDServerPOSTHandler(ctr));
+ server.setHandler(lst);
+ try {
+ server.start();
+ server.join();
+ }
+ catch(Exception e) {
+ System.out.println(e);
+ }
+ }
+}
diff --git a/src/main/java/org/jdownloader/sample/SampleLinkController.java b/src/main/java/org/jdownloader/sample/SampleLinkController.java
new file mode 100644
index 0000000..3e6fff3
--- /dev/null
+++ b/src/main/java/org/jdownloader/sample/SampleLinkController.java
@@ -0,0 +1,18 @@
+package org.jdownloader.sample;
+
+import org.jdownloader.extensions.httpAPI.LinkController;
+
+public class SampleLinkController implements LinkController {
+ public void AddLink(String url) {
+ System.out.println("Adding URL " + url);
+ }
+
+ public void AddLink(String url, String packageName, boolean forcePackageName) {
+ if(forcePackageName) {
+ System.out.println("Adding URL " + url + " with forced package " + packageName);
+ }
+ else {
+ System.out.println("Adding URL " + url + " in package " + packageName);
+ }
+ }
+}