Skip to content

Commit 72cedfd

Browse files
authored
fix: prevent mixed content in SFTP/FTP cached files (#1815)
1 parent 1fbcbff commit 72cedfd

File tree

3 files changed

+71
-34
lines changed

3 files changed

+71
-34
lines changed

src/plugins/ftp/src/android/com/foxdebug/ftp/Ftp.java

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -595,24 +595,33 @@ public void run() {
595595

596596
ftp.setFileType(FTP.BINARY_FILE_TYPE);
597597

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

608-
FileOutputStream outputStream = new FileOutputStream(localFile);
609-
byte[] buffer = new byte[1024];
610-
int bytesRead = -1;
611-
while ((bytesRead = inputStream.read(buffer)) != -1) {
612-
outputStream.write(buffer, 0, bytesRead);
603+
try (
604+
InputStream inputStream = ftp.retrieveFileStream(path)
605+
) {
606+
if (inputStream == null) {
607+
Log.d(
608+
"FTP",
609+
"FTPClient (" + ftpId + ") path: " + path + " - not found"
610+
);
611+
callback.error("File not found.");
612+
return;
613+
}
614+
615+
try (
616+
FileOutputStream outputStream = new FileOutputStream(localFile)
617+
) {
618+
byte[] buffer = new byte[1024];
619+
int bytesRead = -1;
620+
while ((bytesRead = inputStream.read(buffer)) != -1) {
621+
outputStream.write(buffer, 0, bytesRead);
622+
}
623+
}
613624
}
614-
outputStream.close();
615-
inputStream.close();
616625

617626
if (!ftp.completePendingCommand()) {
618627
ftp.logout();
@@ -675,20 +684,22 @@ public void run() {
675684
ftp.setFileType(FTP.BINARY_FILE_TYPE);
676685

677686
Log.d("FTPUpload", "Destination " + remoteFilePath);
678-
OutputStream outputStream = ftp.storeFileStream(remoteFilePath);
679-
if (outputStream == null) {
680-
callback.error("File not found.");
681-
return;
682-
}
683687

684-
InputStream inputStream = new FileInputStream(localFile);
685-
byte[] buffer = new byte[1024];
686-
int bytesRead = -1;
687-
while ((bytesRead = inputStream.read(buffer)) != -1) {
688-
outputStream.write(buffer, 0, bytesRead);
688+
try (
689+
InputStream inputStream = new FileInputStream(localFile);
690+
OutputStream outputStream = ftp.storeFileStream(remoteFilePath)
691+
) {
692+
if (outputStream == null) {
693+
callback.error("File not found.");
694+
return;
695+
}
696+
697+
byte[] buffer = new byte[1024];
698+
int bytesRead = -1;
699+
while ((bytesRead = inputStream.read(buffer)) != -1) {
700+
outputStream.write(buffer, 0, bytesRead);
701+
}
689702
}
690-
outputStream.close();
691-
inputStream.close();
692703

693704
if (!ftp.completePendingCommand()) {
694705
ftp.logout();

src/plugins/sftp/src/com/foxdebug/sftp/Sftp.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ public void run() {
320320
try (
321321
InputStream inputStream = sftp.getInputStream(filename);
322322
java.io.OutputStream outputStream =
323-
contentResolver.openOutputStream(fileUri)
323+
contentResolver.openOutputStream(fileUri, "wt")
324324
) {
325325
byte[] buffer = new byte[32768];
326326
int bytesRead;

src/utils/polyfill.js

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,39 @@ export default function loadPolyFill() {
4747
if (!String.prototype.hashCode) {
4848
Object.defineProperty(String.prototype, "hashCode", {
4949
value: function () {
50-
let hash = 0;
51-
for (let i = 0; i < this.length; i++) {
52-
const chr = this.charCodeAt(i);
53-
hash = (hash << 5) - hash + chr;
54-
hash |= 0; // Convert to 32bit integer
50+
const str = this.toString();
51+
const len = str.length;
52+
53+
if (len === 0) return "0";
54+
55+
// Produces a 48-char hex string (192 bits)
56+
const FNV_PRIME = 0x01000193;
57+
const FNV_OFFSET = 0x811c9dc5;
58+
59+
// Generate 6 different 32-bit hashes with different seeds/offsets
60+
const hashes = [];
61+
for (let pass = 0; pass < 6; pass++) {
62+
let hash = FNV_OFFSET ^ (pass * 0x1234567);
63+
64+
for (let i = 0; i < len; i++) {
65+
const char = str.charCodeAt(i);
66+
// XOR with byte and multiply by prime
67+
hash ^= char;
68+
hash = Math.imul(hash, FNV_PRIME);
69+
// Mix in position and pass for additional entropy
70+
hash ^= (i + pass) & 0xff;
71+
hash = Math.imul(hash, FNV_PRIME);
72+
}
73+
74+
// Additional mixing
75+
hash ^= len;
76+
hash = Math.imul(hash, FNV_PRIME);
77+
hash ^= hash >>> 16;
78+
79+
hashes.push((hash >>> 0).toString(16).padStart(8, "0"));
5580
}
56-
return Math.abs(hash) + (hash < 0 ? "N" : "");
81+
82+
return hashes.join("");
5783
},
5884
});
5985
}

0 commit comments

Comments
 (0)