Java tutorial
/* * Copyright 2013 Sigurd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.digiway.rapidbreeze.client.infrastructure.cnl; import com.sun.jersey.core.util.Base64; import de.digiway.rapidbreeze.client.infrastructure.BusEvents; import de.digiway.rapidbreeze.client.model.collector.LinkBundle; import java.io.IOException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.net.URL; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; import java.util.Map; import javafx.application.Platform; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Response; import org.eclipse.jetty.server.handler.AbstractHandler; import org.mozilla.javascript.Context; import org.mozilla.javascript.ContextFactory; import org.mozilla.javascript.Scriptable; import org.rribbit.RRB; /** * * @author Sigurd */ public class ClickAndLoadHandler extends AbstractHandler { private static final String POST_METHOD = "POST"; private static final String GET_METHOD = "GET"; private static final String STARTED_URI = "/flash/"; private static final String STARTED_RESPONSE = "JDownloader"; private static final String SCRIPT = "/jdcheck.js"; private static final String SCRIPT_RESPONSE = "jdownloader=true;\nvar version='9.581';"; private static final String ADD_LINKS_URI = "/flash/addcrypted2"; @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { switch (request.getMethod().toUpperCase()) { case GET_METHOD: handleGet(request, response); break; case POST_METHOD: handlePost(request, response); break; } } private void handleGet(HttpServletRequest request, HttpServletResponse response) throws IOException { String requestURI = request.getRequestURI(); try (PrintWriter writer = response.getWriter()) { switch (requestURI) { case STARTED_URI: writer.write(STARTED_RESPONSE); break; case SCRIPT: writer.write(SCRIPT_RESPONSE); break; default: response.sendError(Response.SC_NOT_FOUND); break; } } } private void handlePost(HttpServletRequest request, HttpServletResponse response) throws IOException { String requestURI = request.getRequestURI(); switch (requestURI) { case ADD_LINKS_URI: if (addLinks(request)) { try (PrintWriter writer = response.getWriter()) { writer.write("success"); } } break; default: response.sendError(Response.SC_NOT_FOUND); break; } } private boolean addLinks(HttpServletRequest request) throws IOException { String passwords = null; String source = null; String jk = null; String crypted = null; for (Map.Entry<String, String[]> entry : request.getParameterMap().entrySet()) { String value = entry.getValue()[0]; switch (entry.getKey().toLowerCase()) { case "passwords": passwords = value; break; case "source": source = value; break; case "jk": jk = value; break; case "crypted": crypted = value; break; } } if (jk != null) { Context cx = null; try { cx = ContextFactory.getGlobal().enterContext(); Scriptable scope = cx.initStandardObjects(); String fun = jk + " f()"; Object result = cx.evaluateString(scope, fun, "<cmd>", 1, null); byte[] key = hexStringToByteArray(Context.toString(result)); byte[] decoded = Base64.decode(crypted); String decryptedUrls = decrypt(decoded, key); String[] split = StringUtils.split(decryptedUrls, "\n"); if (split.length > 0) { List<URL> urls = new ArrayList<>(); for (String url : split) { String trimmed = url.trim(); if (!trimmed.isEmpty()) { urls.add(new URL(url)); } } LinkBundle lb = new LinkBundle(urls); RRB.get().send(BusEvents.ADD_LINK_BUNDLE, lb); Platform.runLater(new Runnable() { @Override public void run() { RRB.get().send(BusEvents.OPEN_DOWNLOAD_COLLECTOR_WINDOW); } }); return true; } } finally { if (cx != null) { Context.exit(); } } } return false; } private String decrypt(final byte[] b, final byte[] key) { try { final Cipher cipher; final IvParameterSpec ivSpec = new IvParameterSpec(key); final SecretKeySpec skeySpec = new SecretKeySpec(key, "AES"); cipher = Cipher.getInstance("AES/CBC/NoPadding"); cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivSpec); return new String(cipher.doFinal(b), "UTF-8"); } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException | UnsupportedEncodingException ex) { throw new IllegalStateException("Error occured during decryption.", ex); } } private byte[] hexStringToByteArray(String s) { int len = s.length(); byte[] data = new byte[len / 2]; for (int i = 0; i < len; i += 2) { data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16)); } return data; } }