ffsend icon indicating copy to clipboard operation
ffsend copied to clipboard

Download of a ZIP seems to just concatenate content files

Open dbenjaminmiller opened this issue 4 years ago • 9 comments

Currently using ffsend in Termux on Android to try to download some ZIPs. Seems to be the case that when I upload a ZIP, it downloads fine in the browser, but ffsend delivers the content files within the ZIP in a single unzipped file.

For instance, upload 1.jpg and 2.jpg in the browser. The resultant download in ffsend is a .zip which is actually just the two JPEGs concatenated. This amounts to being a valid JPEG as one of the two JPEGs, but which contains the data for both and is the according size.

Don't know if this is a problem on other platforms. But it's odd.

dbenjaminmiller avatar Dec 13 '21 08:12 dbenjaminmiller

I'm not quite sure what you're trying to explain here, sorry.

Send only supports uploading a single file. That's why, when choosing multiple files in the Send interface, or when selecting multiple files with ffsend, an archive is created which is then uploaded.

Are you saying that something breaks when extracting such archive?

ffsend archives to the TAR format by default. Which is not much more than concatenating files together along with metadata. Extracting this TAR should give you the original files back.

An image viewer might succeed in reading an image from the TAR archive. But you should extract the archive first instead.

timvisee avatar Dec 13 '21 15:12 timvisee

OK, let me make it a bit clearer. Here's the chronology to reproduce.

  1. Use the browser, not FFsend, to send multiple files, which results in them being sent as a ZIP.
  2. Download the ZIP with the browser and observe that it is actually a ZIP.
  3. Download the ZIP with ffsend (on Android, at least), and find that it is not an actual ZIP, but a concatenation of the files inside the ZIP.

It's very odd.

This only seems to apply if the ZIP was compressed in the browser rather than an existing ZIP being uploaded.

dbenjaminmiller avatar Dec 13 '21 15:12 dbenjaminmiller

I see. Does a file uploaded in this way fail to extract (on other platforms as well)?

ffsend does not do any file modifications, except for extracting an archive it if you tell it to. With that I mean that you should get the exact same binary file (the ZIP archive) when you download it through a browser as well.

It has been a while since I worked last with ZIP internals. I don't recall if there's a mode to concatenate files without applying compression, to simply merge all into a single file. There probably is.

In any case, I'll take a look into it.

timvisee avatar Dec 13 '21 15:12 timvisee

Woah, you're right!

I was able to reproduce this. I'm seeing the same on my Linux machine. This is super weird.

I don't understand yet how something like this can happen.

timvisee avatar Dec 13 '21 15:12 timvisee

I believe I'm running into the same problem. Person A uploads a number of files to https://send.vis.ee/. Person B tries downloading the link from https://send.vis.ee/, but it reports an error after downloading. Person B tries using ffsend, which saves a file named Send-Archive.zip, but that file is reported as corrupt. Person B finds this issue, inspects the Send-Archive.zip, and finds that it does indeed appear to be the concatenation of the files uploaded by person A. Person B is using ffsend 0.2.74 on macOS from Homebrew.

spl avatar Jan 07 '22 18:01 spl

I am inspecting https://github.com/timvisee/send/tree/6ad2885a168148fb996d3983457bc39527c7c8e5/ (current master)…

Send

Send supports uploading multiple files. If so, it'll concatenate the contents into a stream, call it Send-Archive.zip, and annotate it as a send-archive-type file. Note that the stream is just raw bytes (not a real zip), although the file name is *.zip.

https://github.com/timvisee/send/blob/6ad2885a168148fb996d3983457bc39527c7c8e5/app/archive.js#L26-L32

export default class Archive {
  get name() {
    return this.files.length > 1 ? 'Send-Archive.zip' : this.files[0].name;
  }
  get type() {
    return this.files.length > 1 ? 'send-archive' : this.files[0].type;
  }
  // …
}

Receive

After downloading & decrypting the raw stream, the browser will check the manifest. If it's a send-archive-type file, a zip will be created from the raw stream. (This is done at the client side)

https://github.com/timvisee/send/blob/6ad2885a168148fb996d3983457bc39527c7c8e5/app/fileReceiver.js#L95-L101

      let plainStream = this.keychain.decryptStream(blobStream(ciphertext));
      if (this.fileInfo.type === 'send-archive') {
        const zip = new Zip(this.fileInfo.manifest, plainStream);
        plainStream = zip.stream;
        size = zip.size;
      }
      // And convert `plainStream` to array buffer, …

I search this repo and https://github.com/timvisee/ffsend-api, and find nothing related to send-archive or Send-Archive.zip. Therefore I guess it's not implemented yet.

API responses

Example metadata:

https://github.com/timvisee/ffsend/blob/238f1f54d7bde88c0e525dd0d5c4c6aa251a3634/src/action/download.rs#L98

Multiple files:

MetadataResponse {
    metadata: V3 {
        name: "Send-Archive.zip",
        mime: "send-archive",
        size: 52,
        manifest: Manifest {
            files: [
                ManifestFile {
                    name: "a",
                    mime: "",
                    size: 26,
                },
                ManifestFile {
                    name: "b",
                    mime: "",
                    size: 26,
                },
            ],
        },
    },
    ..
}

Normal (single) files:

MetadataResponse {
    metadata: V3 {
        name: "b",
        mime: "application/octet-stream",
        size: 26,
        manifest: Manifest {
            files: [
                ManifestFile {
                    name: "b",
                    mime: "",
                    size: 26,
                },
            ],
        },
    },
    ..
}

YDX-2147483647 avatar Sep 29 '23 05:09 YDX-2147483647

Hi everyone! I've worked out #169 and https://github.com/timvisee/ffsend-api/pull/82, and you can try it by:

cargo install --git https://github.com/YDX-2147483647/ffsend.git --branch multi-with-api
$ ffsend download https://…
Download & Decrypt …/… [==========] 100.00 % … KB/s
Download complete
Splitting... 👈 This infers that ffsend is downloaing multiple files.

To revert: cargo uninstall ffsend

YDX-2147483647 avatar Sep 29 '23 15:09 YDX-2147483647