Shard links

How a program reads a link to a file under Shard Protection, or one on a public page: the map it asks for, the grant that carries a reading on from one page of the map to the next, what is counted, and what is refused.

How somebody who is not a protected file's owner reads it: whoever holds a link to it, or anybody, for a file on a public page. The website's share and public pages read this way. What is read, and how each fragment is checked, is in the shard format.

A link to a file under Shard Protection, or a protected file on a public page, is a shard link. Nothing about it is stored: it is a link like any other, and its kind is the file's form when it is opened. Turning protection off makes it a standard link at the same address, and turning it on makes it a shard link again once the file has been converted.

  • Whoever holds it is given the key. With each page of the file's map comes the content's key, to the link's holder (after its password, if it has one), as any link gives its holder the file. What stays true is what the feature promises: the storage accounts on their own give nobody anything, and neither does a fragment's address on its own.

  • Removing it stops the next page. So do its end date, its downloads running out, the file or the folder going to the trash, the owner's account being stopped, and for a public file, its being made private. Addresses already given work until they expire, fifteen minutes at most, as a standard link's download does. What a holder has saved, they keep, with the key, as after any download.

  • The key is not changed when a link is removed. A holder who kept the key and the fragments' names learns nothing more without a fresh address, and only a link or the owner gives one out. Changing the key would mean converting the whole file again each time a link is removed.

Asking for the map

A page of the map, for a file reached through a link, which is the link's own file or one inside its folder:

GET /api/public/shares/{token}/files/{fileId}/shards?from=0&formats=1,2

And for a public file:

GET /api/public/files/{fileId}/shards?from=0&formats=1,2
  • from is the first fragment's place on the page, from 0. A page holds up to 1,000 fragments.

  • formats names the versions of the shard format the reader reads, 1,2. Left out, the reader is taken to read version 1 alone, as every reader made before version 2 did, and a file in version 2 is refused to it (409 format_unsupported) before anything is counted.

  • view=1 asks to read the file to show it, as inline=1 does of a plain file's address. Without it, the reading is a download.

  • X-Share-Grant, a header, is what POST /api/public/shares/{token}/unlock answers for a link's password. A link with a password needs it on the first page.

  • X-Read-Grant, a header, is the grant the page before answered. Every page after the first sends the newest one.

Neither grant is ever put in an address: an address is kept in a browser's history and in logs, and a grant there could carry somebody else's reading on.

The answer

Never cached (Cache-Control: no-store). The fields of the owner's map:

FieldWhat it is
contentId In each fragment's associated data, and in version 2 the outline's.
format The version of the shard format the content is written in, 1 or 2.
sizeBytes, fragmentBytes, count The file's size, the fragment size (in version 2, the largest block's), and how many fragments there are.
key The content's key, base64.
name, contentType, revision The file as it is now.
inlineType What a browser may show it as, or null for a file that is only saved. Never SVG or a web page.
outline Version 2, on the first page only: its mac, and its blocks in order, each an id and a length. The MAC and the ids are base64. Null otherwise.
from, next This page's first place, and the next page's, or null on the last.
fragments { place, url } for each fragment on the page, from its storage lane.
expiresAt When the page's addresses stop working: fifteen minutes from when it was signed.

And two of a stranger's:

FieldWhat it is
grant The read grant, which carries this reading on to its next page.
grantExpiresAt When it stops being accepted.

A reading, and what it counts

The first page of a reading is the one that counts. Every page after it, and the first page asked for again (as when its addresses ran out before they were used), sends the read grant and counts nothing, so a file is counted once however many pages it takes.

  • A download (no view=1) is one of a link's downloads, when the link has a limit, and is held to the owner's monthly download allowance as a visitor's download is.

  • Showing it (view=1) is not one of the link's downloads, as a plain file's preview is not, for a file a browser may show. A file it may not show (inlineType null) read "to show it" is a download. A link with a download limit refuses view=1 (400 no_preview): showing the file would be a download nobody counted.

  • The owner's month counts the file's size once a day for each address that reads it, whichever kind of reading it was.

  • A reading that was only showing carries on only to show: its grant does not carry a download on. A download is a reading of its own.

The grant is renewed with every page, for four hours, and never past a day from when the reading was counted. A reading that takes longer than a day starts again from the first page, and is counted again.

A reading without a grant has to start at the first page (409 read_not_started). A grant is for one way in, one file and one content: for a file replaced since its reading began, a page answers 409 content_changed, and the reading starts again.

Refusals

Each in the API's usual form, { error, message }, with the message written for the person reading.

StatuserrorWhen
404 link_not_found No such link.
410 link_removed, link_expired, link_unavailable The link was removed, has ended, or what it points to is gone or in the trash.
410 link_used_up The link's downloads have all been used.
401 password_required The link has a password, and no X-Share-Grant for it was sent.
404 not_found No such file inside the link, or no public file by that id.
400 not_a_file A folder.
409 not_protected A plain file: ask for its address instead (/url).
400 no_such_fragment from is past the last fragment.
400 no_preview view=1 on a link with a download limit.
409 read_not_started, content_changed See above.
409 format_unsupported The file is in a version of the format formats did not name.
402 download_limit, spending_limit The owner's allowance, in a sentence for the visitor.
429 rate_limited Too many pages from one address: 120 in fifteen minutes. With Retry-After.
503 protection_unavailable, lane_unavailable The key, or a storage lane, cannot be reached here now.
500 map_incomplete Part of the map is missing. Logged.

The limit by address is the first thing a page does, before anything is looked up: every page opens a key in the one key vault every account shares, and nobody is signed in.

What a plain tool gets

  • A protected file's address (/url) is 409 shard_protected, with a sentence that says to open its link in a browser, or to save it with filefreak get or the SDK's get().

  • A protected public file's direct address (/api/public/files/{id}/raw) answers 303 with the file's page, on the links host where there is one, and counts nothing. An <img> elsewhere that holds it shows nothing, since there is no address of the file's own to send it to.

  • The page itself, fetched without running its script, says that the file is shard-protected, and so does the card a chat shows for the link.

filefreak get and the SDK's get()

Both read a link as its page does, asking the site the link names with nothing that says who is asking: no key, and from a browser no cookies.

  1. GET /api/public/shares/{token}, or GET /api/public/files/{id} for a public page, which is refused when the address names someone other than the file's owner, as the website's page is. A link with a password is opened with POST /api/public/shares/{token}/unlock, and every request after that sends the grant as X-Share-Grant.

  2. For a folder, its listing and each folder's in it, 200 at a time, each folder once and none deeper than FileFreak's 32 levels.

  3. Before anything is fetched, the files to fetch are counted against the link's downloadsLeft. An empty file is not one: it is written without asking, since asking would count a download of nothing. With too few left, nothing is fetched.

  4. A protected file is read from the first page of its map, and each page after with the newest X-Read-Grant; a plain file through its address (/url). A file converted since the listing is refused by the way the listing chose (409 not_protected or shard_protected), and read the other way, once.