Compare commits

...

12 Commits

Author SHA1 Message Date
tonikelope
fda0fac577 Revert "Added Remote Rest API Support for Downloads (#704)"
This reverts commit fed9f142d08d641d101cdc8e4bce942bc23908d2.
2025-03-20 11:51:51 +01:00
Evan Trowbridge
fed9f142d0
Added Remote Rest API Support for Downloads (#704)
* added remote api for automated management of downloads

* api updates

* api updates

T-H-A-N-K Y-O-U
2025-03-20 11:38:21 +01:00
Antonio L. Vivar
fadb7ea2cc
Update README.md 2024-11-19 12:23:56 +01:00
Antonio L. Vivar
762d3692e9
Add files via upload 2024-11-19 12:22:16 +01:00
Antonio L. Vivar
5378954bb5
Update README.md 2024-11-19 12:21:36 +01:00
tonikelope
d16baf4866 8.22
https://github.com/tonikelope/megabasterd/issues/647

https://github.com/tonikelope/megabasterd/issues/643
2024-08-06 16:09:38 +02:00
tonikelope
5353110c3e https://github.com/tonikelope/megabasterd/issues/643
JOIN CHUNKS LOCK (one file at time)
2024-08-06 16:08:25 +02:00
tonikelope
91dafbce45 Merge origin/master 2024-08-05 19:14:37 +02:00
tonikelope
53c65de717 https://github.com/tonikelope/megabasterd/issues/647 FIX
File split/merge sha1 removed
2024-08-05 19:14:09 +02:00
tonikelope
ba8336e60d test key 2024-08-05 16:07:54 +02:00
tonikelope
fc03de1d3b 8.21
https://github.com/tonikelope/megabasterd/issues/633
https://github.com/tonikelope/megabasterd/issues/634
https://github.com/tonikelope/megabasterd/issues/632
2023-12-13 15:06:05 +01:00
tonikelope
7f8ba83209 8.20
Trying to mitigate https://github.com/tonikelope/megabasterd/issues/623
2023-12-09 12:50:42 +01:00
9 changed files with 107 additions and 104 deletions

View File

@ -14,8 +14,11 @@
<p align="center"><a href="https://youtu.be/5TkBXT7osQI"><b>MegaBasterd DEMO</b></a></p> <p align="center"><a href="https://youtu.be/5TkBXT7osQI"><b>MegaBasterd DEMO</b></a></p>
<p align="center"><img src="https://raw.githubusercontent.com/tonikelope/megabasterd/master/src/main/resources/images/ethereum_toni.png"></p> <p align="center"><img src="https://raw.githubusercontent.com/tonikelope/megabasterd/master/coffee.png"><br><img src="https://raw.githubusercontent.com/tonikelope/megabasterd/master/src/main/resources/images/ethereum_toni.png"></p>
<p align="center"><a href="https://github.com/tonikelope/megabasterd/issues/385#issuecomment-1019215670">BONUS: Why the f*ck has MegaBasterd stopped downloading?</a></p> <p align="center"><a href="https://github.com/tonikelope/megabasterd/issues/385#issuecomment-1019215670">BONUS: Why the f*ck has MegaBasterd stopped downloading?</a></p>
<p align="center"><b>IMPORTANT:</b> You are not authorized to use MegaBasterd in any way that violates <a href="https://mega.io/es/terms"><b>MEGA's terms of use</b></a>.</p>

BIN
coffee.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.tonikelope</groupId> <groupId>com.tonikelope</groupId>
<artifactId>MegaBasterd</artifactId> <artifactId>MegaBasterd</artifactId>
<version>8.19</version> <version>8.22</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<repositories> <repositories>
<repository> <repository>

View File

@ -19,6 +19,7 @@ import java.nio.file.Paths;
import java.security.InvalidAlgorithmParameterException; import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.crypto.CipherInputStream; import javax.crypto.CipherInputStream;
@ -32,6 +33,8 @@ public class ChunkWriterManager implements Runnable, SecureSingleThreadNotifiabl
private static final Logger LOG = Logger.getLogger(ChunkWriterManager.class.getName()); private static final Logger LOG = Logger.getLogger(ChunkWriterManager.class.getName());
private static final ReentrantLock JOIN_CHUNKS_LOCK = new ReentrantLock();
public static long calculateChunkOffset(long chunk_id, int size_multi) { public static long calculateChunkOffset(long chunk_id, int size_multi) {
long[] offs = {0, 128, 384, 768, 1280, 1920, 2688}; long[] offs = {0, 128, 384, 768, 1280, 1920, 2688};
@ -179,71 +182,89 @@ public class ChunkWriterManager implements Runnable, SecureSingleThreadNotifiabl
LOG.log(Level.INFO, "{0} ChunkWriterManager LAST CHUNK WRITTEN -> [{1}] {2} {3}...", new Object[]{Thread.currentThread().getName(), _last_chunk_id_written, _bytes_written, _download.getFile_name()}); LOG.log(Level.INFO, "{0} ChunkWriterManager LAST CHUNK WRITTEN -> [{1}] {2} {3}...", new Object[]{Thread.currentThread().getName(), _last_chunk_id_written, _bytes_written, _download.getFile_name()});
boolean download_finished = false; boolean download_finished = false;
if (_file_size > 0) { if (_file_size > 0) {
while (!_exit && (!_download.isStopped() || !_download.getChunkworkers().isEmpty()) && _bytes_written < _file_size) {
if (!download_finished && _download.getProgress() == _file_size) { try {
finishDownload(); while (!_exit && (!_download.isStopped() || !_download.getChunkworkers().isEmpty()) && _bytes_written < _file_size) {
download_finished = true;
}
boolean chunk_io_error; if (!JOIN_CHUNKS_LOCK.isHeldByCurrentThread()) {
LOG.log(Level.INFO, "{0} ChunkWriterManager: JOIN LOCK LOCKED FOR {1}", new Object[]{Thread.currentThread().getName(), _download.getFile_name()});
do { JOIN_CHUNKS_LOCK.lock();
chunk_io_error = false;
try {
File chunk_file = new File(getChunks_dir() + "/" + MiscTools.HashString("sha1", _download.getUrl()) + ".chunk" + String.valueOf(_last_chunk_id_written + 1));
while (chunk_file.exists() && chunk_file.canRead() && chunk_file.canWrite() && chunk_file.length() > 0) {
if (!download_finished && _download.getProgress() == _file_size) {
finishDownload();
download_finished = true;
}
byte[] buffer = new byte[MainPanel.DEFAULT_BYTE_BUFFER_SIZE];
int reads;
try (CipherInputStream cis = new CipherInputStream(new BufferedInputStream(new FileInputStream(chunk_file)), genDecrypter("AES", "AES/CTR/NoPadding", _byte_file_key, forwardMEGALinkKeyIV(_byte_iv, _bytes_written)))) {
while ((reads = cis.read(buffer)) != -1) {
_download.getOutput_stream().write(buffer, 0, reads);
}
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException ex) {
LOG.log(Level.SEVERE, ex.getMessage());
}
_bytes_written += chunk_file.length();
_last_chunk_id_written++;
LOG.log(Level.INFO, "{0} ChunkWriterManager has written to disk chunk [{1}] {2} {3} {4}...", new Object[]{Thread.currentThread().getName(), _last_chunk_id_written, _bytes_written, _download.calculateLastWrittenChunk(_bytes_written), _download.getFile_name()});
chunk_file.delete();
chunk_file = new File(getChunks_dir() + "/" + MiscTools.HashString("sha1", _download.getUrl()) + ".chunk" + String.valueOf(_last_chunk_id_written + 1));
}
} catch (IOException ex) {
chunk_io_error = true;
LOG.log(Level.WARNING, ex.getMessage());
MiscTools.pausar(1000);
} }
} while (chunk_io_error); if (!download_finished && _download.getProgress() == _file_size) {
if (!_exit && (!_download.isStopped() || !_download.getChunkworkers().isEmpty()) && _bytes_written < _file_size) { finishDownload();
download_finished = true;
}
LOG.log(Level.INFO, "{0} ChunkWriterManager waiting for chunk [{1}] {2}...", new Object[]{Thread.currentThread().getName(), _last_chunk_id_written + 1, _download.getFile_name()}); boolean chunk_io_error;
secureWait(); do {
chunk_io_error = false;
try {
File chunk_file = new File(getChunks_dir() + "/" + MiscTools.HashString("sha1", _download.getUrl()) + ".chunk" + String.valueOf(_last_chunk_id_written + 1));
while (chunk_file.exists() && chunk_file.canRead() && chunk_file.canWrite() && chunk_file.length() > 0) {
if (!download_finished && _download.getProgress() == _file_size) {
finishDownload();
download_finished = true;
}
byte[] buffer = new byte[MainPanel.DEFAULT_BYTE_BUFFER_SIZE];
int reads;
try (CipherInputStream cis = new CipherInputStream(new BufferedInputStream(new FileInputStream(chunk_file)), genDecrypter("AES", "AES/CTR/NoPadding", _byte_file_key, forwardMEGALinkKeyIV(_byte_iv, _bytes_written)))) {
while ((reads = cis.read(buffer)) != -1) {
_download.getOutput_stream().write(buffer, 0, reads);
}
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException ex) {
LOG.log(Level.SEVERE, ex.getMessage());
}
_bytes_written += chunk_file.length();
_last_chunk_id_written++;
LOG.log(Level.INFO, "{0} ChunkWriterManager has written to disk chunk [{1}] {2} {3} {4}...", new Object[]{Thread.currentThread().getName(), _last_chunk_id_written, _bytes_written, _download.calculateLastWrittenChunk(_bytes_written), _download.getFile_name()});
chunk_file.delete();
chunk_file = new File(getChunks_dir() + "/" + MiscTools.HashString("sha1", _download.getUrl()) + ".chunk" + String.valueOf(_last_chunk_id_written + 1));
}
} catch (IOException ex) {
chunk_io_error = true;
LOG.log(Level.WARNING, ex.getMessage());
MiscTools.pausar(1000);
}
} while (chunk_io_error);
if (!_exit && (!_download.isStopped() || !_download.getChunkworkers().isEmpty()) && _bytes_written < _file_size) {
LOG.log(Level.INFO, "{0} ChunkWriterManager waiting for chunk [{1}] {2}...", new Object[]{Thread.currentThread().getName(), _last_chunk_id_written + 1, _download.getFile_name()});
if (JOIN_CHUNKS_LOCK.isHeldByCurrentThread() && JOIN_CHUNKS_LOCK.isLocked()) {
LOG.log(Level.INFO, "{0} ChunkWriterManager: JOIN LOCK RELEASED FOR {1}", new Object[]{Thread.currentThread().getName(), _download.getFile_name()});
JOIN_CHUNKS_LOCK.unlock();
}
secureWait();
}
} }
} finally {
if (JOIN_CHUNKS_LOCK.isHeldByCurrentThread() && JOIN_CHUNKS_LOCK.isLocked()) {
LOG.log(Level.INFO, "{0} ChunkWriterManager: JOIN LOCK RELEASED FOR {1}", new Object[]{Thread.currentThread().getName(), _download.getFile_name()});
JOIN_CHUNKS_LOCK.unlock();
}
} }
if (_bytes_written == _file_size && MiscTools.isDirEmpty(Paths.get(getChunks_dir()))) { if (_bytes_written == _file_size && MiscTools.isDirEmpty(Paths.get(getChunks_dir()))) {

View File

@ -41,7 +41,6 @@ public class FileSplitterDialog extends javax.swing.JDialog {
private final MainPanel _main_panel; private final MainPanel _main_panel;
private File[] _files = null; private File[] _files = null;
private File _output_dir = null; private File _output_dir = null;
private volatile String _sha1 = null;
private volatile long _progress = 0L; private volatile long _progress = 0L;
private volatile Path _current_part = null; private volatile Path _current_part = null;
private volatile int _current_file = 0; private volatile int _current_file = 0;
@ -86,17 +85,6 @@ public class FileSplitterDialog extends javax.swing.JDialog {
private boolean _splitFile(int i) throws IOException { private boolean _splitFile(int i) throws IOException {
_sha1 = "";
THREAD_POOL.execute(() -> {
try {
_sha1 = MiscTools.computeFileSHA1(new File(_files[i].getAbsolutePath()));
} catch (IOException ex) {
Logger.getLogger(FileSplitterDialog.class.getName()).log(Level.SEVERE, null, ex);
}
});
this._progress = 0L; this._progress = 0L;
int mBperSplit = Integer.parseInt(this.split_size_text.getText()); int mBperSplit = Integer.parseInt(this.split_size_text.getText());
@ -135,20 +123,6 @@ public class FileSplitterDialog extends javax.swing.JDialog {
} }
} }
while ("".equals(_sha1)) {
MiscTools.GUIRunAndWait(() -> {
split_button.setText(LabelTranslatorSingleton.getInstance().translate("GENERATING SHA1, please wait..."));
});
MiscTools.pausar(1000);
}
if (_sha1 != null) {
Files.writeString(Paths.get(this._files[i].getAbsolutePath() + ".sha1"), _sha1);
}
return true; return true;
} }
@ -195,9 +169,13 @@ public class FileSplitterDialog extends javax.swing.JDialog {
monitorProgress(f, byteSize); monitorProgress(f, byteSize);
if (!_exit) { if (!_exit) {
long dest_bytes_copied = Files.exists(fileName) ? Files.size(fileName) : 0;
try (RandomAccessFile toFile = new RandomAccessFile(fileName.toFile(), "rw"); FileChannel toChannel = toFile.getChannel()) { try (RandomAccessFile toFile = new RandomAccessFile(fileName.toFile(), "rw"); FileChannel toChannel = toFile.getChannel()) {
sourceChannel.position(position); while (dest_bytes_copied < byteSize) {
toChannel.transferFrom(sourceChannel, 0, byteSize); sourceChannel.position(position + dest_bytes_copied);
dest_bytes_copied += toChannel.transferFrom(sourceChannel, dest_bytes_copied, byteSize - dest_bytes_copied);
}
} }
} }

View File

@ -69,7 +69,7 @@ import javax.swing.UIManager;
*/ */
public final class MainPanel { public final class MainPanel {
public static final String VERSION = "8.19"; public static final String VERSION = "8.22";
public static final boolean FORCE_SMART_PROXY = false; //TRUE FOR DEBUGING SMART PROXY public static final boolean FORCE_SMART_PROXY = false; //TRUE FOR DEBUGING SMART PROXY
public static final int THROTTLE_SLICE_SIZE = 16 * 1024; public static final int THROTTLE_SLICE_SIZE = 16 * 1024;
public static final int DEFAULT_BYTE_BUFFER_SIZE = 16 * 1024; public static final int DEFAULT_BYTE_BUFFER_SIZE = 16 * 1024;
@ -106,15 +106,6 @@ public final class MainPanel {
public static void main(String args[]) { public static void main(String args[]) {
boolean dark = false;
try {
dark = "yes".equals(DBTools.selectSettingValue("dark_mode"));
} catch (Exception ex) {
}
setNimbusLookAndFeel(dark);
if (args.length > 0) { if (args.length > 0) {
if (args.length > 1) { if (args.length > 1) {
@ -139,6 +130,20 @@ public final class MainPanel {
MEGABASTERD_HOME_DIR = f.getParentFile().getAbsolutePath(); MEGABASTERD_HOME_DIR = f.getParentFile().getAbsolutePath();
} }
try {
setupSqliteTables();
} catch (SQLException ex) {
Logger.getLogger(MainPanel.class.getName()).log(SEVERE, null, ex);
}
setNimbusLookAndFeel("yes".equals(DBTools.selectSettingValue("dark_mode")));
if ("yes".equals(DBTools.selectSettingValue("upload_log"))) {
MiscTools.createUploadLogDir();
}
final MainPanel main_panel = new MainPanel(); final MainPanel main_panel = new MainPanel();
invokeLater(() -> { invokeLater(() -> {
@ -259,16 +264,6 @@ public final class MainPanel {
_resume_downloads = false; _resume_downloads = false;
MiscTools.createUploadLogDir();
try {
setupSqliteTables();
} catch (SQLException ex) {
Logger.getLogger(MainPanel.class.getName()).log(SEVERE, null, ex);
}
loadUserSettings(); loadUserSettings();
if (_debug_file) { if (_debug_file) {

View File

@ -276,6 +276,8 @@ public final class MainPanelView extends javax.swing.JFrame {
if (dialog.getUpload_log_checkbox().isSelected()) { if (dialog.getUpload_log_checkbox().isSelected()) {
MiscTools.createUploadLogDir();
File upload_log = new File(MiscTools.UPLOAD_LOGS_DIR + "/megabasterd_upload_" + parent_node + ".log"); File upload_log = new File(MiscTools.UPLOAD_LOGS_DIR + "/megabasterd_upload_" + parent_node + ".log");
upload_log.createNewFile(); upload_log.createNewFile();

View File

@ -2129,6 +2129,10 @@ public class SettingsDialog extends javax.swing.JDialog {
settings.put("smartproxy_timeout", String.valueOf(proxy_timeout_spinner.getValue())); settings.put("smartproxy_timeout", String.valueOf(proxy_timeout_spinner.getValue()));
settings.put("smartproxy_autorefresh_time", String.valueOf(auto_refresh_proxy_time_spinner.getValue())); settings.put("smartproxy_autorefresh_time", String.valueOf(auto_refresh_proxy_time_spinner.getValue()));
if (upload_log_checkbox.isSelected()) {
createUploadLogDir();
}
if (custom_proxy_textarea.getText().trim().length() == 0) { if (custom_proxy_textarea.getText().trim().length() == 0) {
smart_proxy_checkbox.setSelected(false); smart_proxy_checkbox.setSelected(false);
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 213 KiB

After

Width:  |  Height:  |  Size: 214 KiB