Skip to content

Files

The phone reaches a computer’s files with its own protocol, tealhand/files/1, and not with SFTP or a general file server. The computer exposes only the folders you shared, and one piece of code, the path jail, is the only place a path from the phone becomes a path on the disk.

How to share a folder: Share folders.

Files use a second connection between the phone and the computer, next to the one that carries commands (ctl/1). It has the same protections: it is encrypted to the computer’s key, and the device-list gate lets in only your connected phones. The computer accepts at most 2 files connections per phone.

  1. The phone starts with a normal signed command: a “list the shared folders” request, signed by its device key. It needs no card because it only reads. The computer verifies it exactly like a command on ctl/1.
  2. If it is accepted, the computer answers with the list of shared folders and opens a session on that connection.
  3. From then on, reads on that connection (list a folder, look at one file) don’t need a signature of their own. They are valid only on this connection, after that opener. The computer checks every one again: the phone is still on the device list, remote control is still on, the folder is still shared, and the path is resolved from scratch. Remove a share, or switch remote control off, and the next request is refused and the session ends.

Reads carry no signature so that browsing a folder of thousands of files costs no fingerprint and no extra round trips. Anything that changes something (an upload, a new folder, a rename, a delete) is a signed command with a card, just like any other action. A session with no activity for 10 minutes is closed.

To read a file, the phone asks for a byte range: “this file, from here, this many bytes”. The computer answers with how big the file is and then sends exactly that many raw bytes, in pieces of at most 64 KiB, and finishes the stream. The phone may stop early. Up to 8 transfers run at once on a connection, and a transfer with no progress for 60 seconds is stopped. A folder with more than 100,000 entries isn’t listed.

Playback uses the same range reads. A media player on the phone wants an ordinary web address, so the phone runs a tiny server for it that is only on the phone, bound to 127.0.0.1. It makes a web address for each file with a random token in it. The player asks for a byte range, the phone turns that into a range read from the computer, and the video starts playing and can be dragged to the middle without copying the file. At most 4 files are open at a time, the server answers only a request that carries the right address and token, and a token stops after 30 minutes of no use, when you stop the player or when the computer leaves your device list.

What the phone does when you tap a file in Files:

  • An image, a video or an audio file opens in a viewer on the phone. Video and audio play through the server above, so nothing is copied.
  • A text file shows a preview of its first 256 KiB, read with a range read. A file with a NUL near the start isn’t text, and the phone says so.
  • Anything else is copied to the phone and then opened. The phone opens it with the app for its type, and asks Open with when it doesn’t know the type. The progress sheet for the copy has Open and Show folder.

An upload is a signed command with a card first (one card for a whole batch of files). The computer checks the folder, the name and the size before it accepts a single byte: the folder must not be read-only, a file can be at most 16 GiB, and at least 1 GiB must stay free on the disk afterwards.

The data goes to a temporary file in the target folder named .<name>.tealhand-part. When all of it has arrived, the computer syncs the file to disk and renames it into place. If the name is taken, the phone chose in advance what happens: pick a new name (name (1).ext), replace the file (which asks for your fingerprint), or fail. Each file in a batch is signed just before it starts, so no command expires while an earlier file is still being sent.

Large copies that survive a dropped connection

Section titled “Large copies that survive a dropped connection”

Copies in both directions go on where they stopped (decision 58):

  • To a computer. Each file is sent under a random name of the sender’s (a key). If the connection drops, the computer keeps what it has in .<name>.<8 hex>.tealhand-part, synced, and the copy shows Paused · resumes when Studio PC is back. The phone or computer tries again by itself (after 2 s, then up to every 30 s) and sends only the rest. This survives a restart of the computer, and of the sending app when it sends a file of its own (a desktop upload, or a copy back to it); a file shared from another phone app must be shared again after the phone app restarts, because Android does not let it reopen the file then.
  • To the phone or this computer. The copy is written straight to its file; after a break it asks for the rest from the byte it has (a range read). If the file changed on the computer meanwhile (size or date), it starts over.
  • Checked at the end. The SHA-256 of the whole file must match: the computer checks an upload, and a copy from a computer asks it for the file’s SHA-256 (files.hash). A damaged copy is not kept; it is sent once more from the start.
  • Stop discards it. Stopping a copy removes the partial file here and asks the computer to remove its temporary file. A paused upload nobody resumes is removed by the computer after 7 days, at its next start or its next upload. Replace is never resumable: it asks for your fingerprint each time.

Move to… (long-press on the phone, a button on a row on another computer’s Files tab) moves a file or a folder into another folder: in the same shared folder, or in another shared folder of the same computer that is not read only. It is a card, like a rename: “Move “a.txt” to Projects/old on Studio PC”. A name already there asks first: Keep both (the moved one gets a number) or, for a file on the phone, Replace (with the fingerprint). A folder never moves into itself, and a shared folder itself never moves. Between two disks only a file moves (up to 512 MiB, copied through a temporary file, then the original removed); a folder there is refused.

A path from the phone is never a path as you know it. It is a shared folder’s number and a list of names below it. The jail is the only code that turns that into a real path. Its rules:

  1. Names are checked. Each name is 1 to 255 bytes, is not . or .., and holds none of / \ : * ? " < > |, no control character, and no invisible character. A name can’t end in a dot or a space, and can’t be a Windows device name such as CON. A path is at most 64 names deep. The phone checks the same rules, so a name means the same on both.
  2. Walk from the folder, one name at a time. The jail looks at each step on the disk without following it. A symbolic link, a junction or a mount point at any step is refused.
  3. Check the end. The result is made absolute, and it must lie inside the shared folder and outside the Host’s own data folder.
  4. Open without following links. A file is opened so that it can’t be swapped for a link in between, and the open file is checked again to be a plain file.
  5. Never create links. Writes never make a link. A read-only folder refuses every change. A new folder is made one level at a time in a folder that exists.
  6. Rename stays in the folder; Move walks both ends. A rename never renames a shared folder itself, and replaces only a file. A move checks the entry and the target folder by rules 1 to 4, needs both shared folders to be writable, never moves a folder into itself, and replaces only a file with a file.
  7. Delete goes to the trash. A delete moves the file or folder to the Recycle Bin or the trash. If that isn’t possible, nothing is deleted.
  8. Nothing is kept open. The computer keeps no file or folder handle between requests; each request starts from the shared folder again.
  9. Listings never follow links. Names that aren’t valid text or that break rule 1 are shown, but marked so the phone offers no action on them.

Sharing itself has rules too: you can’t share a whole drive, a system folder, the Host’s data folder, a link, or a folder inside or around one already shared.

Downloads and the rule against reaching your own network

Section titled “Downloads and the rule against reaching your own network”

“Download on Studio PC” asks the computer to fetch a web link into a shared folder. The card names the folder (Save to, with Change). A link from a web page is data from a stranger, so the computer treats it with care. This is the SSRF rule: a link must not make the computer reach into your private network.

  • The link. At most 2048 bytes, http or https, with a host, no user name or password in it, and the port must be 80, 443 or at least 1024.
  • The address. The computer looks the name up itself and refuses the download unless every address it finds is a public one. These are refused: the computer itself (loopback), private networks (10.x, 172.16 to 172.31, 192.168.x), link-local and shared addresses, documentation and benchmarking ranges, multicast, the unique-local and link-local IPv6 ranges, and IPv6 forms that carry an IPv4 address inside them (mapped, NAT64, 6to4, Teredo). It connects only to the addresses it checked, so the name can’t be changed after the check.
  • Redirects. The computer follows at most 5, checks every target the same way, and refuses a step from https back to http.
  • Limits. One download at a time, at most 8 GiB, refused at once when the announced size is bigger, and refused if less than 1 GiB would stay free.
  • Where it lands. Only in a shared folder that is not read only: the one the request names, or the computer’s default for downloads when it names none. Under a cleaned name, never replacing a file (a taken name gets (1)). The data goes to a temporary file first. A dropped connection resumes with a range request, up to 5 times. The phone chooses the folder for each download: the one it used last for that computer, the default for downloads, a folder named Downloads, or the first folder that is not read only.
  • A link that is a web page. The computer reads the page on its own side (at most 2 MiB, in memory, no scripts) and sends the phone the file links it found. The phone picks one, and that file gets its own card and goes through the same checks. A short meta refresh counts as a redirect. A Dropbox or Google Drive share link is rewritten on the phone, before the card, to the address that gives the file.
  • After it lands. The computer never opens or runs the file. On Windows the file is marked as downloaded from the internet. When a download is finished the phone opens its folder with the file marked, and Play, Open or Send to phone are done from there.

A link that leads to your own network is refused with “will not download from that address: it leads to a private network”. The card for a download shows the link’s host first, so you can see where it points before you confirm.

Files and downloads write the same kind of journal line as any action: who, what and how it was allowed. A line may name the shared folder, but never a file’s name, its contents or its path.