Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 38 additions & 27 deletions src/plugins/ftp/src/android/com/foxdebug/ftp/Ftp.java
Original file line number Diff line number Diff line change
Expand Up @@ -595,24 +595,33 @@ public void run() {

ftp.setFileType(FTP.BINARY_FILE_TYPE);

InputStream inputStream = ftp.retrieveFileStream(path);
if (inputStream == null) {
Log.d(
"FTP",
"FTPClient (" + ftpId + ") path: " + path + " - not found"
);
callback.error("File not found.");
return;
// Delete existing cache file to prevent stale content
if (localFile.exists()) {
localFile.delete();
}

FileOutputStream outputStream = new FileOutputStream(localFile);
byte[] buffer = new byte[1024];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
try (
InputStream inputStream = ftp.retrieveFileStream(path)
) {
if (inputStream == null) {
Log.d(
"FTP",
"FTPClient (" + ftpId + ") path: " + path + " - not found"
);
callback.error("File not found.");
return;
}
Comment on lines +606 to +613
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When inputStream is null, the method returns early without calling ftp.completePendingCommand(). According to Apache Commons Net FTP documentation, completePendingCommand() must be called after using streaming methods like retrieveFileStream() to complete the FTP transaction, even if the stream is null.

Without calling completePendingCommand(), the FTP connection may be left in an inconsistent state, potentially causing subsequent FTP operations to fail or hang.

Consider checking for null before entering the try-with-resources block, or calling completePendingCommand() in a finally block to ensure it always executes.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/plugins/ftp/src/android/com/foxdebug/ftp/Ftp.java
Line: 606:613

Comment:
When `inputStream` is null, the method returns early without calling `ftp.completePendingCommand()`. According to Apache Commons Net FTP documentation, `completePendingCommand()` must be called after using streaming methods like `retrieveFileStream()` to complete the FTP transaction, even if the stream is null.

Without calling `completePendingCommand()`, the FTP connection may be left in an inconsistent state, potentially causing subsequent FTP operations to fail or hang.

Consider checking for null before entering the try-with-resources block, or calling `completePendingCommand()` in a finally block to ensure it always executes.

How can I resolve this? If you propose a fix, please make it concise.


try (
FileOutputStream outputStream = new FileOutputStream(localFile)
) {
byte[] buffer = new byte[1024];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
}
}
outputStream.close();
inputStream.close();

if (!ftp.completePendingCommand()) {
ftp.logout();
Expand Down Expand Up @@ -675,20 +684,22 @@ public void run() {
ftp.setFileType(FTP.BINARY_FILE_TYPE);

Log.d("FTPUpload", "Destination " + remoteFilePath);
OutputStream outputStream = ftp.storeFileStream(remoteFilePath);
if (outputStream == null) {
callback.error("File not found.");
return;
}

InputStream inputStream = new FileInputStream(localFile);
byte[] buffer = new byte[1024];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
try (
InputStream inputStream = new FileInputStream(localFile);
OutputStream outputStream = ftp.storeFileStream(remoteFilePath)
) {
if (outputStream == null) {
callback.error("File not found.");
return;
}
Comment on lines +692 to +695
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When outputStream is null, the method returns early without calling ftp.completePendingCommand(). According to Apache Commons Net FTP documentation, completePendingCommand() must be called after using streaming methods like storeFileStream() to complete the FTP transaction.

Without calling completePendingCommand(), the FTP connection may be left in an inconsistent state, potentially causing subsequent FTP operations to fail or hang.

Consider checking for null before entering the try-with-resources block, or ensuring completePendingCommand() is called in a finally block.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/plugins/ftp/src/android/com/foxdebug/ftp/Ftp.java
Line: 692:695

Comment:
When `outputStream` is null, the method returns early without calling `ftp.completePendingCommand()`. According to Apache Commons Net FTP documentation, `completePendingCommand()` must be called after using streaming methods like `storeFileStream()` to complete the FTP transaction.

Without calling `completePendingCommand()`, the FTP connection may be left in an inconsistent state, potentially causing subsequent FTP operations to fail or hang.

Consider checking for null before entering the try-with-resources block, or ensuring `completePendingCommand()` is called in a finally block.

How can I resolve this? If you propose a fix, please make it concise.


byte[] buffer = new byte[1024];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
}
outputStream.close();
inputStream.close();

if (!ftp.completePendingCommand()) {
ftp.logout();
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/sftp/src/com/foxdebug/sftp/Sftp.java
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ public void run() {
try (
InputStream inputStream = sftp.getInputStream(filename);
java.io.OutputStream outputStream =
contentResolver.openOutputStream(fileUri)
contentResolver.openOutputStream(fileUri, "wt")
) {
byte[] buffer = new byte[32768];
int bytesRead;
Expand Down
38 changes: 32 additions & 6 deletions src/utils/polyfill.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,39 @@ export default function loadPolyFill() {
if (!String.prototype.hashCode) {
Object.defineProperty(String.prototype, "hashCode", {
value: function () {
let hash = 0;
for (let i = 0; i < this.length; i++) {
const chr = this.charCodeAt(i);
hash = (hash << 5) - hash + chr;
hash |= 0; // Convert to 32bit integer
const str = this.toString();
const len = str.length;

if (len === 0) return "0";

// Produces a 48-char hex string (192 bits)
const FNV_PRIME = 0x01000193;
const FNV_OFFSET = 0x811c9dc5;

// Generate 6 different 32-bit hashes with different seeds/offsets
const hashes = [];
for (let pass = 0; pass < 6; pass++) {
let hash = FNV_OFFSET ^ (pass * 0x1234567);

for (let i = 0; i < len; i++) {
const char = str.charCodeAt(i);
// XOR with byte and multiply by prime
hash ^= char;
hash = Math.imul(hash, FNV_PRIME);
// Mix in position and pass for additional entropy
hash ^= (i + pass) & 0xff;
hash = Math.imul(hash, FNV_PRIME);
}

// Additional mixing
hash ^= len;
hash = Math.imul(hash, FNV_PRIME);
hash ^= hash >>> 16;

hashes.push((hash >>> 0).toString(16).padStart(8, "0"));
}
return Math.abs(hash) + (hash < 0 ? "N" : "");

return hashes.join("");
},
});
}
Expand Down