Refactoring and cleaning

1.6
This commit is contained in:
tonikelope 2016-10-02 17:46:32 +02:00
parent c8ae3bc4be
commit f39da85605
12 changed files with 496 additions and 560 deletions

View File

@ -166,7 +166,7 @@ public final class AboutDialog extends javax.swing.JDialog {
swingReflectionInvoke("setEnabled", check_version_button, false);
final AboutDialog main = this;
final AboutDialog tthis = this;
THREAD_POOL.execute(new Runnable(){
@Override
@ -186,7 +186,7 @@ public final class AboutDialog extends javax.swing.JDialog {
if(((String)current_node.get("name")).contains("_"+VERSION.replaceAll(" *beta *", "")+".")) {
JOptionPane.showMessageDialog(main, "You have the latest version ;)");
JOptionPane.showMessageDialog(tthis, "You have the latest version ;)");
new_version = false;
@ -196,14 +196,14 @@ public final class AboutDialog extends javax.swing.JDialog {
if(new_version) {
JOptionPane.showMessageDialog(main, "NEW VERSION IS AVAILABLE!");
JOptionPane.showMessageDialog(tthis, "NEW VERSION IS AVAILABLE!");
}
} catch (Exception ex) {
getLogger(AboutDialog.class.getName()).log(Level.SEVERE, null, ex);
}
swingReflectionInvoke("setEnabled", main.check_version_button, true);
swingReflectionInvoke("setEnabled", check_version_button, true);
}});

View File

@ -14,8 +14,6 @@ import static java.lang.Long.valueOf;
import static java.lang.Math.ceil;
import static java.lang.System.out;
import static java.lang.Thread.sleep;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.FileChannel;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
@ -36,11 +34,10 @@ import static megabasterd.CryptTools.genCrypter;
import static megabasterd.DBTools.deleteDownload;
import static megabasterd.DBTools.insertDownload;
import static megabasterd.DBTools.selectSettingValueFromDB;
import static megabasterd.MainPanel.CONNECTION_TIMEOUT;
import static megabasterd.MainPanel.THREAD_POOL;
import static megabasterd.MainPanel.USER_AGENT;
import static megabasterd.MiscTools.UrlBASE642Bin;
import static megabasterd.MiscTools.bin2i32a;
import static megabasterd.MiscTools.checkMegaDownloadUrl;
import static megabasterd.MiscTools.findFirstRegex;
import static megabasterd.MiscTools.formatBytes;
import static megabasterd.MiscTools.getWaitTimeExpBackOff;
@ -855,30 +852,11 @@ public final class Download implements Transference, Runnable, SecureNotifiable
}
public boolean checkDownloadUrl(String string_url)
{
try {
URL url = new URL(string_url+"/0-0");
URLConnection connection = url.openConnection();
connection.setConnectTimeout(CONNECTION_TIMEOUT);
connection.setRequestProperty("User-Agent", USER_AGENT);
try (InputStream is = connection.getInputStream()) {
while(is.read()!=-1);
}
return true;
}catch (Exception ex) {
return false;
}
}
/* OJO!! -> ESTO ESTÁ CAMBIADO Y NO COMPROBADO!! */
public synchronized String getDownloadUrlForWorker() throws IOException
{
if(_last_download_url != null && checkDownloadUrl(_last_download_url)) {
if(_last_download_url != null && checkMegaDownloadUrl(_last_download_url)) {
return _last_download_url;
}
@ -905,7 +883,7 @@ public final class Download implements Transference, Runnable, SecureNotifiable
download_url = MegaCrypterAPI.getMegaFileDownloadUrl(_url, _file_pass, _file_noexpire);
}
if(checkDownloadUrl(download_url)) {
if(checkMegaDownloadUrl(download_url)) {
_last_download_url = download_url;

View File

@ -45,7 +45,7 @@ public final class DownloadManager extends TransferenceManager {
try {
this._provision((Download)download, false);
_provision((Download)download, false);
secureNotify();
@ -53,15 +53,13 @@ public final class DownloadManager extends TransferenceManager {
System.out.println("Provision failed! Retrying in separated thread...");
final DownloadManager tthis = this;
THREAD_POOL.execute(new Runnable(){
@Override
public void run(){
try {
tthis._provision((Download)download, true);
_provision((Download)download, true);
} catch (MegaAPIException | MegaCrypterAPIException ex1) {

View File

@ -269,23 +269,23 @@ public final class FolderLinkDialog extends javax.swing.JDialog {
swingReflectionInvoke("setEnabled", file_tree, false);
final FolderLinkDialog main = this;
THREAD_POOL.execute(new Runnable(){
@Override
public void run() {
main._loadMegaDirTree();
_loadMegaDirTree();
main._genDownloadLiks();
_genDownloadLiks();
swingReflectionInvoke("setEnabled", main.restore_button, true);
swingReflectionInvoke("setEnabled", restore_button, true);
swingReflectionInvoke("setVisible", main.restore_button, false);
swingReflectionInvoke("setVisible", restore_button, false);
swingReflectionInvoke("setEnabled", main.dance_button, true);
swingReflectionInvoke("setEnabled", dance_button, true);
swingReflectionInvoke("setEnabled", main.file_tree, true);
swingReflectionInvoke("setEnabled", file_tree, true);
}});
}//GEN-LAST:event_restore_buttonActionPerformed

View File

@ -1,124 +1,210 @@
package megabasterd;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import java.awt.Color;
import static java.awt.Frame.NORMAL;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import static java.util.logging.Level.SEVERE;
import java.util.logging.Logger;
import static java.util.logging.Logger.getLogger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.crypto.CipherInputStream;
import static megabasterd.MainPanel.STREAMER_PORT;
import static megabasterd.MainPanel.THREAD_POOL;
import static megabasterd.MiscTools.checkMegaDownloadUrl;
import static megabasterd.MiscTools.findFirstRegex;
import static megabasterd.MiscTools.getWaitTimeExpBackOff;
import static megabasterd.MiscTools.swingReflectionInvoke;
public final class KissVideoStreamServer {
public final class KissVideoStreamServer implements HttpHandler, SecureNotifiable {
public static final int WORKER_STATUS_FILE_INFO=0x01;
public static final int WORKER_STATUS_CONNECT=0x02;
public static final int WORKER_STATUS_STREAM=0x03;
public static final int WORKER_STATUS_RETRY=0x04;
public static final int WORKER_STATUS_EXIT=0x05;
public static final int TIMEOUT=30000;
public static final int EXP_BACKOFF_BASE=2;
public static final int EXP_BACKOFF_SECS_RETRY=1;
public static final int EXP_BACKOFF_MAX_WAIT_TIME=128;
private HttpServer _httpserver;
private final MainPanelView _main_panel;
private final MainPanel _main_panel;
private final ConcurrentHashMap<String, String[]> _link_cache;
private final ConcurrentHashMap<Thread, Boolean> _working;
private final ConcurrentHashMap<Thread, Integer> _working_threads;
private final ContentType _ctype;
private KissVideoStreamServerHandler _http_handler;
public KissVideoStreamServer(MainPanelView panel) {
private boolean _notified;
private final Object _secure_notify_lock;
public KissVideoStreamServer(MainPanel panel) {
_main_panel = panel;
_link_cache = new ConcurrentHashMap();
_working = new ConcurrentHashMap();
_working_threads = new ConcurrentHashMap();
_ctype = new ContentType();
_notified=false;
_secure_notify_lock = new Object();
}
public KissVideoStreamServerHandler getHandler()
{
return _http_handler;
}
public MainPanelView getPanel()
{
public MainPanel getMain_panel() {
return _main_panel;
}
public ContentType getCtype()
{
public ConcurrentHashMap<String, String[]> getLink_cache() {
return _link_cache;
}
public ConcurrentHashMap<Thread, Integer> getWorking_threads() {
return _working_threads;
}
public ContentType getCtype() {
return _ctype;
}
public ConcurrentHashMap getStreaming()
@Override
public void secureNotify()
{
return _working;
synchronized(_secure_notify_lock) {
_notified = true;
_secure_notify_lock.notify();
}
}
public boolean isWorking()
@Override
public void secureWait() {
synchronized(_secure_notify_lock)
{
return !_working.isEmpty();
while(!_notified) {
try {
_secure_notify_lock.wait();
} catch (InterruptedException ex) {
getLogger(Download.class.getName()).log(SEVERE, null, ex);
}
}
_notified = false;
}
}
@Override
public void secureNotifyAll() {
synchronized(_secure_notify_lock) {
_notified = true;
_secure_notify_lock.notifyAll();
}
}
public void start(int port, String context) throws IOException
{
swingReflectionInvoke("setForeground", _main_panel.getView().getKiss_server_status(), new Color(0,128,0));
swingReflectionInvoke("setText", _main_panel.getView().getKiss_server_status(), "Kissvideostreamer on localhost:"+STREAMER_PORT+" (Waiting for request...)");
_httpserver = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), port), 0);
printStatusOK("Kissvideostreamer on localhost:"+STREAMER_PORT+" (Waiting for request...)");
_httpserver.createContext(context, (_http_handler = new KissVideoStreamServerHandler(this, _main_panel)));
_httpserver.setExecutor(Executors.newCachedThreadPool());
_httpserver.createContext(context, this);
_httpserver.setExecutor(THREAD_POOL);
_httpserver.start();
THREAD_POOL.execute(new Runnable() {
@Override
public void run() {
while(true) {
secureWait();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(KissVideoStreamServer.class.getName()).log(Level.SEVERE, null, ex);
}
public void stop()
if(_working_threads.isEmpty()) {
swingReflectionInvoke("setExtendedState", _main_panel.getView(), NORMAL);
swingReflectionInvoke("setVisible", _main_panel.getView(), true);
}
}
}
});
}
private void updateStatus(Integer new_status) {
if(new_status != WORKER_STATUS_EXIT) {
getWorking_threads().put(Thread.currentThread(), new_status);
} else {
getWorking_threads().remove(Thread.currentThread());
}
int conta_info=0, conta_connect=0, conta_stream=0, conta_retry=0;
for(Integer thread_status:getWorking_threads().values()) {
switch(thread_status) {
case WORKER_STATUS_FILE_INFO:
conta_info++;
break;
case WORKER_STATUS_CONNECT:
conta_connect++;
break;
case WORKER_STATUS_STREAM:
conta_stream++;
break;
case WORKER_STATUS_RETRY:
conta_retry++;
break;
}
}
String status="Kissvideostreamer on localhost:"+STREAMER_PORT+" Info: "+conta_info+" / Conn: "+conta_connect+" / Stream: "+conta_stream+" / Retry: "+conta_retry;
swingReflectionInvoke("setText", _main_panel.getView().getKiss_server_status(), status);
}
private String[] getMegaFileMetadata(String link, MainPanelView panel) throws IOException, InterruptedException
{
_httpserver.stop(0);
}
public void printStatusError(String message)
{
swingReflectionInvoke("setForeground", _main_panel.getKiss_server_status(), Color.red);
swingReflectionInvoke("setText", _main_panel.getKiss_server_status(), message);
}
public void printStatusOK(String message)
{
swingReflectionInvoke("setForeground", _main_panel.getKiss_server_status(), new Color(0,128,0));
swingReflectionInvoke("setText", _main_panel.getKiss_server_status(), message);
}
public String[] getFromLinkCache(String link)
{
return _link_cache.containsKey(link)?_link_cache.get(link):null;
}
public void updateLinkCache(String link, String[] info) {
_link_cache.put(link, info);
}
public void removeFromLinkCache(String link) {
_link_cache.remove(link);
}
public String[] getMegaFileMetadata(String link, MainPanelView panel) throws IOException, InterruptedException
{
String[] file_info=null;
int retry=0, error_code=0;
int retry=0;
boolean error;
do
{
updateStatus(WORKER_STATUS_FILE_INFO);
error=false;
try
{
if( findFirstRegex("://mega(\\.co)?\\.nz/", link, 0) != null)
{
MegaAPI ma = new MegaAPI();
@ -130,15 +216,12 @@ public final class KissVideoStreamServer {
file_info = MegaCrypterAPI.getMegaFileMetadata(link, panel);
}
}
catch(MegaAPIException | MegaCrypterAPIException e)
{
error=true;
error_code = Integer.parseInt(e.getMessage());
switch(error_code)
switch(Integer.parseInt(e.getMessage()))
{
case -2:
throw new IOException("Mega link is not valid!");
@ -157,22 +240,16 @@ public final class KissVideoStreamServer {
default:
updateStatus(WORKER_STATUS_RETRY);
for(long i=getWaitTimeExpBackOff(retry++); i>0; i--)
{
if(error_code == -18)
{
printStatusError("File temporarily unavailable! (Retrying in "+i+" secs...)");
}
else
{
printStatusError("Mega/MC APIException error "+e.getMessage()+" (Retrying in "+i+" secs...)");
}
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {}
}
}
} catch(Exception ex) {
}
@ -183,23 +260,20 @@ public final class KissVideoStreamServer {
return file_info;
}
public String getMegaFileDownloadUrl(String link, String pass_hash, String noexpire_token) throws IOException, InterruptedException
private String getMegaFileDownloadUrl(String link, String pass_hash, String noexpire_token) throws IOException, InterruptedException
{
String dl_url=null;
int retry=0, error_code;
int retry=0;
boolean error;
do
{
updateStatus(WORKER_STATUS_FILE_INFO);
error=false;
try
{
if( findFirstRegex("://mega(\\.co)?\\.nz/", link, 0) != null)
{
MegaAPI ma = new MegaAPI();
@ -210,38 +284,12 @@ public final class KissVideoStreamServer {
{
dl_url = MegaCrypterAPI.getMegaFileDownloadUrl(link,pass_hash,noexpire_token);
}
}
catch(MegaAPIException e)
catch(MegaAPIException | MegaCrypterAPIException e)
{
error=true;
error_code = Integer.parseInt(e.getMessage());
for(long i=getWaitTimeExpBackOff(retry++); i>0; i--)
{
if(error_code == -18)
{
printStatusError("File temporarily unavailable! (Retrying in "+i+" secs...)");
}
else
{
printStatusError("MegaAPIException error "+e.getMessage()+" (Retrying in "+i+" secs...)");
}
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {}
}
}
catch(MegaCrypterAPIException e)
{
error=true;
error_code = Integer.parseInt(e.getMessage());
switch(error_code)
switch(Integer.parseInt(e.getMessage()))
{
case 22:
throw new IOException("MegaCrypter link is not valid!");
@ -253,17 +301,11 @@ public final class KissVideoStreamServer {
throw new IOException("MegaCrypter link has expired!");
default:
updateStatus(WORKER_STATUS_RETRY);
for(long i=getWaitTimeExpBackOff(retry++); i>0; i--)
{
if(error_code == -18)
{
printStatusError("File temporarily unavailable! (Retrying in "+i+" secs...)");
}
else
{
printStatusError("MegaCrypterAPIException error "+e.getMessage()+" (Retrying in "+i+" secs...)");
}
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {}
@ -276,27 +318,7 @@ public final class KissVideoStreamServer {
return dl_url;
}
public boolean checkDownloadUrl(String string_url)
{
try {
URL url = new URL(string_url+"/0-0");
URLConnection connection = url.openConnection();
connection.setConnectTimeout(TIMEOUT);
connection.setRequestProperty("User-Agent", MainPanel.USER_AGENT);
connection.setRequestProperty("Connection", "close");
try (InputStream is = connection.getInputStream()) {
while(is.read()!=-1);
}
return true;
}catch (Exception ex) {
return false;
}
}
public long[] parseRangeHeader(String header)
private long[] parseRangeHeader(String header)
{
Pattern pattern = Pattern.compile("bytes\\=([0-9]+)\\-([0-9]+)?");
@ -319,15 +341,237 @@ public final class KissVideoStreamServer {
return ranges;
}
public String cookRangeUrl(String url, long[] ranges, int sync_bytes)
private String cookRangeUrl(String url, long[] ranges, int sync_bytes)
{
return url+"/"+String.valueOf(ranges[0]-sync_bytes)+(ranges[1]>=0?"-"+String.valueOf(ranges[1]):"");
}
public void restoreMainWindow() {
@Override
public void handle(HttpExchange xchg) throws IOException {
_main_panel.setExtendedState(javax.swing.JFrame.NORMAL);
swingReflectionInvoke("setVisible", _main_panel, true);
long clength;
OutputStream os;
CipherInputStream cis = null;
String httpmethod = xchg.getRequestMethod();
try{
Headers reqheaders=xchg.getRequestHeaders();
Headers resheaders = xchg.getResponseHeaders();
String url_path = xchg.getRequestURI().getPath();
String link = url_path.substring(url_path.indexOf("/video/")+7);
if(link.indexOf("mega/") == 0)
{
link = link.replaceAll("mega/", "https://mega.co.nz/#");
}
else
{
String mc_host = findFirstRegex("^[^/]+/", link, 0);
link = "http://" + mc_host + link;
}
String[] cache_info, file_info;
cache_info = getLink_cache().get(link);
if(cache_info!=null) {
file_info = new String[6];
System.arraycopy( cache_info, 0, file_info, 0, cache_info.length );
} else {
file_info = getMegaFileMetadata(link, _main_panel.getView());
cache_info = new String[6];
System.arraycopy( file_info, 0, cache_info, 0, file_info.length );
cache_info[5]=null;
}
String file_name = file_info[0];
long file_size = Long.parseLong(file_info[1]);
String file_key = file_info[2];
String pass_hash, noexpire_token;
if(file_info.length >= 5)
{
pass_hash = file_info[3];
noexpire_token = file_info[4];
} else {
pass_hash = null;
noexpire_token = null;
}
String file_ext = file_name.substring(file_name.lastIndexOf('.')+1).toLowerCase();
URLConnection urlConn;
if(httpmethod.equals("HEAD")) {
resheaders.add("Accept-Ranges", "bytes");
resheaders.add("transferMode.dlna.org", "Streaming");
resheaders.add("contentFeatures.dlna.org", "DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000");
resheaders.add("Content-Type", getCtype().getMIME(file_ext));
resheaders.add("Content-Length", String.valueOf(file_size));
resheaders.add("Connection", "close");
xchg.sendResponseHeaders(HttpURLConnection.HTTP_OK, 0);
} else if(httpmethod.equals("GET")) {
resheaders.add("Accept-Ranges", "bytes");
resheaders.add("transferMode.dlna.org", "Streaming");
resheaders.add("contentFeatures.dlna.org", "DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000");
resheaders.add("Content-Type", getCtype().getMIME(file_ext));
resheaders.add("Connection", "close");
byte[] buffer = new byte[16*1024];
int reads;
String temp_url;
if(cache_info[5]!=null) {
temp_url = cache_info[5];
if(!checkMegaDownloadUrl(temp_url)) {
temp_url = getMegaFileDownloadUrl(link,pass_hash,noexpire_token);
cache_info[5] = temp_url;
getLink_cache().put(link, file_info);
}
} else {
temp_url = getMegaFileDownloadUrl(link,pass_hash,noexpire_token);
cache_info[5] = temp_url;
getLink_cache().put(link, cache_info);
}
long[] ranges=new long[2];
int sync_bytes=0;
String header_range=null;
InputStream is;
URL url;
if(reqheaders.containsKey("Range"))
{
header_range = "Range";
} else if(reqheaders.containsKey("range")) {
header_range = "range";
}
if(header_range != null)
{
List<String> ranges_raw = reqheaders.get(header_range);
String range_header=ranges_raw.get(0);
ranges = parseRangeHeader(range_header);
sync_bytes = (int)ranges[0] % 16;
if(ranges[1]>=0 && ranges[1]>=ranges[0]) {
clength = ranges[1]-ranges[0]+1;
} else {
clength = file_size - ranges[0];
}
resheaders.add("Content-Range", "bytes "+ranges[0]+"-"+(ranges[1]>=0?ranges[1]:(file_size-1))+"/"+file_size);
xchg.sendResponseHeaders(HttpURLConnection.HTTP_PARTIAL, clength);
url = new URL(cookRangeUrl(temp_url, ranges, sync_bytes));
} else {
xchg.sendResponseHeaders(HttpURLConnection.HTTP_OK, file_size);
url = new URL(temp_url);
}
updateStatus(WORKER_STATUS_CONNECT);
urlConn = url.openConnection();
urlConn.setConnectTimeout(MainPanel.CONNECTION_TIMEOUT);
urlConn.setRequestProperty("User-Agent", MainPanel.USER_AGENT);
urlConn.setRequestProperty("Connection", "close");
is = urlConn.getInputStream();
byte[] iv = CryptTools.initMEGALinkKeyIV(file_key);
cis = new CipherInputStream(is, CryptTools.genDecrypter("AES", "AES/CTR/NoPadding", CryptTools.initMEGALinkKey(file_key), (header_range!=null && (ranges[0]-sync_bytes)>0)?CryptTools.forwardMEGALinkKeyIV(iv, ranges[0]-sync_bytes):iv));
os = xchg.getResponseBody();
cis.skip(sync_bytes);
updateStatus(WORKER_STATUS_STREAM);
while((reads=cis.read(buffer))!=-1) {
os.write(buffer, 0, reads);
}
}
}
catch(Exception ex){ }
finally
{
if(cis!=null) {
cis.close();
}
xchg.close();
updateStatus(WORKER_STATUS_EXIT);
secureNotify();
}
}
}

View File

@ -1,301 +0,0 @@
package megabasterd;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.logging.Level;
import static java.util.logging.Logger.getLogger;
import javax.crypto.CipherInputStream;
import javax.crypto.NoSuchPaddingException;
import static megabasterd.MainPanel.STREAMER_PORT;
import static megabasterd.MiscTools.findFirstRegex;
public final class KissVideoStreamServerHandler implements HttpHandler {
private final KissVideoStreamServer _httpserver;
private final MainPanelView _view;
private String _file_name;
private long _file_size;
private String _file_key;
private String _pass_hash;
private String _noexpire_token;
public KissVideoStreamServerHandler(KissVideoStreamServer server, MainPanelView view) {
_httpserver = server;
_view = view;
}
@Override
public void handle(HttpExchange xchg) throws IOException {
_httpserver.getStreaming().put(Thread.currentThread(), true);
long clength;
OutputStream os;
CipherInputStream cis = null;
String httpmethod = xchg.getRequestMethod();
_httpserver.printStatusOK("Kissvideostreamer (Request received! Dispatching it...)");
Headers reqheaders=xchg.getRequestHeaders();
Headers resheaders = xchg.getResponseHeaders();
String url_path = xchg.getRequestURI().getPath();
String link = url_path.substring(url_path.indexOf("/video/")+7);
if(link.indexOf("mega/") == 0)
{
link = link.replaceAll("mega/", "https://mega.co.nz/#");
}
else
{
String mc_host = findFirstRegex("^[^/]+/", link, 0);
link = "http://" + mc_host + link;
}
_httpserver.printStatusOK("Kissvideostreamer (Retrieving file metadata...)");
String[] cache_info, file_info=null;
cache_info = _httpserver.getFromLinkCache(link);
if(cache_info!=null) {
file_info = new String[6];
System.arraycopy( cache_info, 0, file_info, 0, cache_info.length );
} else {
try {
file_info = _httpserver.getMegaFileMetadata(link, _view);
} catch (InterruptedException ex) {
getLogger(KissVideoStreamServerHandler.class.getName()).log(Level.SEVERE, null, ex);
}
cache_info = new String[6];
System.arraycopy( file_info, 0, cache_info, 0, file_info.length );
cache_info[5]=null;
}
_file_name = file_info[0];
_file_size = Long.parseLong(file_info[1]);
_file_key = file_info[2];
if(file_info.length >= 5)
{
_pass_hash = file_info[3];
_noexpire_token = file_info[4];
} else {
_pass_hash = null;
_noexpire_token = null;
}
String file_ext = _file_name.substring(_file_name.lastIndexOf('.')+1).toLowerCase();
URLConnection urlConn;
try{
if(httpmethod.equals("HEAD")) {
resheaders.add("Accept-Ranges", "bytes");
resheaders.add("transferMode.dlna.org", "Streaming");
resheaders.add("contentFeatures.dlna.org", "DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000");
resheaders.add("Content-Type", _httpserver.getCtype().getMIME(file_ext));
resheaders.add("Content-Length", String.valueOf(_file_size));
resheaders.add("Connection", "close");
xchg.sendResponseHeaders(HttpURLConnection.HTTP_OK, 0);
} else if(httpmethod.equals("GET")) {
resheaders.add("Accept-Ranges", "bytes");
resheaders.add("transferMode.dlna.org", "Streaming");
resheaders.add("contentFeatures.dlna.org", "DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000");
resheaders.add("Content-Type", _httpserver.getCtype().getMIME(file_ext));
resheaders.add("Connection", "close");
byte[] buffer = new byte[16*1024];
int reads;
_httpserver.printStatusOK("Kissvideostreamer (Retrieving mega temp url...)");
String temp_url;
if(cache_info[5]!=null) {
temp_url = cache_info[5];
if(!_httpserver.checkDownloadUrl(temp_url)) {
temp_url = _httpserver.getMegaFileDownloadUrl(link,_pass_hash,_noexpire_token);
cache_info[5] = temp_url;
_httpserver.updateLinkCache(link, cache_info);
}
} else {
temp_url = _httpserver.getMegaFileDownloadUrl(link,_pass_hash,_noexpire_token);
cache_info[5] = temp_url;
_httpserver.updateLinkCache(link, cache_info);
}
_httpserver.printStatusOK("Kissvideostreamer (Connecting...)");
long[] ranges=new long[2];
int sync_bytes=0;
String header_range=null;
InputStream is;
URL url;
if(reqheaders.containsKey("Range"))
{
header_range = "Range";
} else if(reqheaders.containsKey("range")) {
header_range = "range";
}
if(header_range != null)
{
List<String> ranges_raw = reqheaders.get(header_range);
String range_header=ranges_raw.get(0);
ranges = _httpserver.parseRangeHeader(range_header);
sync_bytes = (int)ranges[0] % 16;
if(ranges[1]>=0 && ranges[1]>=ranges[0]) {
clength = ranges[1]-ranges[0]+1;
} else {
clength = _file_size - ranges[0];
}
resheaders.add("Content-Range", "bytes "+ranges[0]+"-"+(ranges[1]>=0?ranges[1]:(_file_size-1))+"/"+_file_size);
xchg.sendResponseHeaders(HttpURLConnection.HTTP_PARTIAL, clength);
url = new URL(_httpserver.cookRangeUrl(temp_url, ranges, sync_bytes));
} else {
xchg.sendResponseHeaders(HttpURLConnection.HTTP_OK, _file_size);
url = new URL(temp_url);
}
urlConn = url.openConnection();
urlConn.setConnectTimeout(KissVideoStreamServer.TIMEOUT);
urlConn.setRequestProperty("User-Agent", MainPanel.USER_AGENT);
urlConn.setRequestProperty("Connection", "close");
is = urlConn.getInputStream();
byte[] iv = CryptTools.initMEGALinkKeyIV(_file_key);
try {
cis = new CipherInputStream(is, CryptTools.genDecrypter("AES", "AES/CTR/NoPadding", CryptTools.initMEGALinkKey(_file_key), (header_range!=null && (ranges[0]-sync_bytes)>0)?CryptTools.forwardMEGALinkKeyIV(iv, ranges[0]-sync_bytes):iv));
} catch ( NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException ex) {
getLogger(KissVideoStreamServerHandler.class.getName()).log(Level.SEVERE, null, ex);
}
os = xchg.getResponseBody();
_httpserver.printStatusOK("Kissvideostreamer (Streaming file "+_file_name+" ...)");
//Skip sync bytes
cis.skip(sync_bytes);
while((reads=cis.read(buffer))!=-1) {
os.write(buffer, 0, reads);
}
}
}
catch(Exception ex)
{
}
finally
{
if(cis!=null) {
cis.close();
}
xchg.close();
_httpserver.printStatusOK("Kissvideostreamer on localhost:"+STREAMER_PORT+" (Waiting for request...)");
_httpserver.getStreaming().remove(Thread.currentThread());
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
getLogger(KissVideoStreamServerHandler.class.getName()).log(Level.SEVERE, null, ex);
}
if(!_httpserver.isWorking()) {
_httpserver.restoreMainWindow();
}
}
}
}

View File

@ -57,7 +57,7 @@ import static megabasterd.Transference.MAX_TRANSFERENCE_SPEED_DEFAULT;
*/
public final class MainPanel {
public static final String VERSION="1.5";
public static final String VERSION="1.6";
public static final String USER_AGENT="Mozilla/5.0 (X11; Linux x8664; rv:48.0) Gecko/20100101 Firefox/48.0";
public static final int CONNECTION_TIMEOUT = 30000;
public static final int THROTTLE_SLICE_SIZE=16*1024;
@ -138,7 +138,7 @@ public final class MainPanel {
resumeUploads();
_streamserver = new KissVideoStreamServer(getView());
_streamserver = new KissVideoStreamServer(this);
try {
_streamserver.start(STREAMER_PORT, "/video");
@ -341,7 +341,7 @@ public final class MainPanel {
public void _byebye() {
if(_streamserver.isWorking()) {
if(!_streamserver.getWorking_threads().isEmpty()) {
Object[] options = {"No",
"Yes"};
@ -437,7 +437,7 @@ public final class MainPanel {
swingReflectionInvoke("setText", getView().getStatus_down_label(), "Resuming previous downloads, please wait...");
final MainPanel main =this;
final MainPanel tthis =this;
THREAD_POOL.execute(new Runnable(){
@ -452,9 +452,9 @@ public final class MainPanel {
for(HashMap<String,Object> o:res) {
Download download = new Download(main, (String)o.get("url"), (String)o.get("path"), (String)o.get("filename"), (String)o.get("filekey"), (Long)o.get("filesize"), (String)o.get("filepass"), (String)o.get("filenoexpire"), main._use_slots_down, main._default_slots_down, false);
Download download = new Download(tthis, (String)o.get("url"), (String)o.get("path"), (String)o.get("filename"), (String)o.get("filekey"), (Long)o.get("filesize"), (String)o.get("filepass"), (String)o.get("filenoexpire"), _use_slots_down, _default_slots_down, false);
main.getDownload_manager().getTransference_provision_queue().add(download);
getDownload_manager().getTransference_provision_queue().add(download);
conta_downloads++;
}
@ -466,15 +466,15 @@ public final class MainPanel {
if(conta_downloads>0) {
swingReflectionInvoke("setText", main.getView().getStatus_down_label(), "Starting downloads provisioning, please wait...");
swingReflectionInvoke("setText", getView().getStatus_down_label(), "Starting downloads provisioning, please wait...");
main.getDownload_manager().secureNotify();
getDownload_manager().secureNotify();
main.getView().getjTabbedPane1().setSelectedIndex(0);
getView().getjTabbedPane1().setSelectedIndex(0);
}
swingReflectionInvoke("setText", main.getView().getStatus_down_label(), "");
swingReflectionInvoke("setText", getView().getStatus_down_label(), "");
}});
@ -517,12 +517,11 @@ public final class MainPanel {
MenuItem closeItem = new MenuItem("EXIT");
final MainPanel main=this;
closeItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
main._byebye();
_byebye();
}
});
@ -565,7 +564,7 @@ public final class MainPanel {
swingReflectionInvoke("setText", getView().getStatus_up_label(), "Resuming previous uploads, please wait...");
final MainPanel main =this;
final MainPanel tthis =this;
THREAD_POOL.execute(new Runnable(){
@Override
@ -585,11 +584,11 @@ public final class MainPanel {
MegaAPI ma;
if(main._mega_accounts.get(email) != null) {
if(_mega_accounts.get(email) != null) {
final HashMap<String,Object> account_info = (HashMap)main._mega_accounts.get(email);
final HashMap<String,Object> account_info = (HashMap)_mega_accounts.get(email);
ma = main._mega_active_accounts.get(email);
ma = _mega_active_accounts.get(email);
if(ma == null) {
@ -599,16 +598,16 @@ public final class MainPanel {
ma.login(email, bin2i32a(BASE642Bin((String)account_info.get("password_aes"))), (String)account_info.get("user_hash"));
main._mega_active_accounts.put(email, ma);
_mega_active_accounts.put(email, ma);
} catch (Exception ex) {
getLogger(MainPanelView.class.getName()).log(SEVERE, null, ex);
}
}
Upload upload = new Upload(main, ma, (String)o.get("filename"), (String)o.get("parent_node"), (String)o.get("ul_key")!=null?bin2i32a(BASE642Bin((String)o.get("ul_key"))):null, (String)o.get("url"), (String)o.get("root_node"), BASE642Bin((String)o.get("share_key")), (String)o.get("folder_link"), main._use_slots_up, main._default_slots_up, false);
Upload upload = new Upload(tthis, ma, (String)o.get("filename"), (String)o.get("parent_node"), (String)o.get("ul_key")!=null?bin2i32a(BASE642Bin((String)o.get("ul_key"))):null, (String)o.get("url"), (String)o.get("root_node"), BASE642Bin((String)o.get("share_key")), (String)o.get("folder_link"), _use_slots_up, _default_slots_up, false);
main.getUpload_manager().getTransference_provision_queue().add(upload);
getUpload_manager().getTransference_provision_queue().add(upload);
conta_uploads++;
@ -620,15 +619,15 @@ public final class MainPanel {
if(conta_uploads>0) {
swingReflectionInvoke("setText", main.getView().getStatus_up_label(), "Starting uploads provisioning, please wait...");
swingReflectionInvoke("setText", getView().getStatus_up_label(), "Starting uploads provisioning, please wait...");
main.getUpload_manager().secureNotify();
getUpload_manager().secureNotify();
main.getView().getjTabbedPane1().setSelectedIndex(1);
getView().getjTabbedPane1().setSelectedIndex(1);
}
swingReflectionInvoke("setText", main.getView().getStatus_up_label(), "");
swingReflectionInvoke("setText", getView().getStatus_up_label(), "");
} catch (Exception ex) {
getLogger(MainPanel.class.getName()).log(SEVERE, null, ex);

View File

@ -510,7 +510,7 @@ public final class MainPanelView extends javax.swing.JFrame {
@Override
public void run() {
swingReflectionInvoke("setText", tthis.status_down_label, "Pre-processing downloads, please wait...");
swingReflectionInvoke("setText", status_down_label, "Pre-processing downloads, please wait...");
Set<String> urls = new HashSet(findAllRegex("(?:https?|mega)://[^/]*/(#.*?)?!.+![^\r\n]+", dialog.getLinks_textarea().getText(), 0));
@ -555,9 +555,9 @@ public final class MainPanelView extends javax.swing.JFrame {
for(HashMap folder_link:folder_links) {
download = new Download(tthis.getMain_panel(), (String)folder_link.get("url"), dl_path, (String)folder_link.get("filename"), (String)folder_link.get("filekey"), (long)folder_link.get("filesize"), null, null, tthis.getMain_panel().isUse_slots_down(), tthis.getMain_panel().getDefault_slots_down(), true);
download = new Download(getMain_panel(), (String)folder_link.get("url"), dl_path, (String)folder_link.get("filename"), (String)folder_link.get("filekey"), (long)folder_link.get("filesize"), null, null, getMain_panel().isUse_slots_down(), getMain_panel().getDefault_slots_down(), true);
tthis.getMain_panel().getDownload_manager().getTransference_provision_queue().add(download);
getMain_panel().getDownload_manager().getTransference_provision_queue().add(download);
conta_downloads++;
}
@ -570,9 +570,9 @@ public final class MainPanelView extends javax.swing.JFrame {
} else {
download = new Download(tthis.getMain_panel(), url, dl_path, null, null, null, null, null, tthis.getMain_panel().isUse_slots_down(), tthis.getMain_panel().getDefault_slots_down(), false);
download = new Download(getMain_panel(), url, dl_path, null, null, null, null, null, getMain_panel().isUse_slots_down(), getMain_panel().getDefault_slots_down(), false);
tthis.getMain_panel().getDownload_manager().getTransference_provision_queue().add(download);
getMain_panel().getDownload_manager().getTransference_provision_queue().add(download);
conta_downloads++;
}
@ -580,18 +580,18 @@ public final class MainPanelView extends javax.swing.JFrame {
if(conta_downloads > 0) {
swingReflectionInvoke("setText", tthis.status_down_label, "Starting downloads provisioning, please wait...");
swingReflectionInvoke("setText", status_down_label, "Starting downloads provisioning, please wait...");
tthis.getMain_panel().getDownload_manager().secureNotify();
getMain_panel().getDownload_manager().secureNotify();
}
}
swingReflectionInvoke("setText", tthis.status_down_label, "");
swingReflectionInvoke("setText", status_down_label, "");
swingReflectionInvoke("setEnabled", new_download_menu, true);
tthis.getMain_panel().getDownload_manager().setPreprocessing_transferences(false);
getMain_panel().getDownload_manager().setPreprocessing_transferences(false);
}});
} else {
@ -742,21 +742,19 @@ public final class MainPanelView extends javax.swing.JFrame {
final ArrayList<File> files = dialog.getFiles();
final MainPanelView main = this;
jTabbedPane1.setSelectedIndex(1);
THREAD_POOL.execute(new Runnable(){
@Override
public void run() {
MegaAPI ma=main.getMain_panel().getMega_active_accounts().get(mega_account)!=null?main.getMain_panel().getMega_active_accounts().get(mega_account):new MegaAPI();
MegaAPI ma=getMain_panel().getMega_active_accounts().get(mega_account)!=null?getMain_panel().getMega_active_accounts().get(mega_account):new MegaAPI();
try {
ma.login(mega_account, mega_aes_pass, mega_user_hash);
main.getMain_panel().getMega_active_accounts().put(mega_account, ma);
getMain_panel().getMega_active_accounts().put(mega_account, ma);
byte[] parent_key = ma.genFolderKey();
@ -778,7 +776,7 @@ public final class MainPanelView extends javax.swing.JFrame {
for(File f:files) {
swingReflectionInvoke("setText", main.status_up_label, "Pre-processing ("+(conta++)+"/"+files.size()+") uploads, please wait...");
swingReflectionInvoke("setText", status_up_label, "Pre-processing ("+(conta++)+"/"+files.size()+") uploads, please wait...");
String file_path = f.getParentFile().getAbsolutePath().replace(base_path, "");
@ -813,15 +811,15 @@ public final class MainPanelView extends javax.swing.JFrame {
}
}
Upload upload = new Upload(main.getMain_panel(), ma, f.getAbsolutePath(), file_parent, null, null, parent_node, share_key, folder_link, main.getMain_panel().isUse_slots_up(), main.getMain_panel().getDefault_slots_up(), false);
Upload upload = new Upload(getMain_panel(), ma, f.getAbsolutePath(), file_parent, null, null, parent_node, share_key, folder_link, getMain_panel().isUse_slots_up(), getMain_panel().getDefault_slots_up(), false);
main.getMain_panel().getUpload_manager().getTransference_provision_queue().add(upload);
getMain_panel().getUpload_manager().getTransference_provision_queue().add(upload);
}
swingReflectionInvoke("setText", main.status_up_label, "Starting uploads provisioning, please wait...");
swingReflectionInvoke("setText", status_up_label, "Starting uploads provisioning, please wait...");
main.getMain_panel().getUpload_manager().secureNotify();
getMain_panel().getUpload_manager().secureNotify();
} catch (Exception ex) {
@ -830,7 +828,7 @@ public final class MainPanelView extends javax.swing.JFrame {
swingReflectionInvoke("setEnabled", new_upload_menu, true);
main.getMain_panel().getUpload_manager().setPreprocessing_transferences(false);
getMain_panel().getUpload_manager().setPreprocessing_transferences(false);
}
});

View File

@ -58,12 +58,10 @@ public final class MegaAPI {
private String _root_id;
private String _inbox_id;
private String _email;
private String _trashbin_id;
private String _req_id;

View File

@ -50,6 +50,8 @@ import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.xml.bind.DatatypeConverter;
import static megabasterd.MainPanel.CONNECTION_TIMEOUT;
import static megabasterd.MainPanel.USER_AGENT;
public final class MiscTools {
@ -813,6 +815,29 @@ public final class MiscTools {
return res;
}
public static boolean checkMegaDownloadUrl(String string_url) {
boolean url_ok=false;
try {
URL url = new URL(string_url+"/0-0");
URLConnection connection = url.openConnection();
connection.setConnectTimeout(CONNECTION_TIMEOUT);
connection.setRequestProperty("User-Agent", USER_AGENT);
try (InputStream is = connection.getInputStream()) {
while(is.read()!=-1);
}
url_ok=true;
}catch (Exception ex) {}
return url_ok;
}
private MiscTools() {
}

View File

@ -179,9 +179,9 @@ public final class StreamerDialog extends javax.swing.JDialog implements Clipboa
JOptionPane.showMessageDialog(tthis, "Streaming link was copied to clipboard!\n(Remember to keep MegaBasterd running in background while playing)");
tthis.dispose();
dispose();
tthis.getParent().dispatchEvent(new WindowEvent(tthis, WINDOW_CLOSING));
getParent().dispatchEvent(new WindowEvent(tthis, WINDOW_CLOSING));
} catch (IOException ex) {
Logger.getLogger(StreamerDialog.class.getName()).log(Level.SEVERE, null, ex);

View File

@ -271,8 +271,6 @@ abstract public class TransferenceManager implements Runnable, SecureNotifiable
@Override
public void run() {
final TransferenceManager tthis = this;
while(true)
{
if(!isProvisioning_transferences() && !getTransference_provision_queue().isEmpty())
@ -283,7 +281,6 @@ abstract public class TransferenceManager implements Runnable, SecureNotifiable
@Override
public void run(){
while(!getTransference_provision_queue().isEmpty())
{
final Transference transference = getTransference_provision_queue().poll();
@ -295,9 +292,9 @@ abstract public class TransferenceManager implements Runnable, SecureNotifiable
}
}
tthis.setProvisioning_transferences(false);
setProvisioning_transferences(false);
tthis.secureNotify();
secureNotify();
}});
@ -321,9 +318,9 @@ abstract public class TransferenceManager implements Runnable, SecureNotifiable
}
}
tthis.setRemoving_transferences(false);
setRemoving_transferences(false);
tthis.secureNotify();
secureNotify();
}});
}
@ -346,9 +343,9 @@ abstract public class TransferenceManager implements Runnable, SecureNotifiable
}
}
tthis.setStarting_transferences(false);
setStarting_transferences(false);
tthis.secureNotify();
secureNotify();
}});
}