From 0226e0ca0dc70f9a0310b3eef045ee1c1e0ca3ac Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Tue, 13 Dec 2022 20:00:46 +0300 Subject: split into a separate repo --- .../test/test-pages/ietf-1/expected-images.json | 1 + .../test/test-pages/ietf-1/expected-metadata.json | 8 + .../test/test-pages/ietf-1/expected.html | 1115 +++++++++++++++++ .../test/test-pages/ietf-1/source.html | 1269 ++++++++++++++++++++ 4 files changed, 2393 insertions(+) create mode 100644 vendor/fivefilters/readability.php/test/test-pages/ietf-1/expected-images.json create mode 100644 vendor/fivefilters/readability.php/test/test-pages/ietf-1/expected-metadata.json create mode 100644 vendor/fivefilters/readability.php/test/test-pages/ietf-1/expected.html create mode 100644 vendor/fivefilters/readability.php/test/test-pages/ietf-1/source.html (limited to 'vendor/fivefilters/readability.php/test/test-pages/ietf-1') diff --git a/vendor/fivefilters/readability.php/test/test-pages/ietf-1/expected-images.json b/vendor/fivefilters/readability.php/test/test-pages/ietf-1/expected-images.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/vendor/fivefilters/readability.php/test/test-pages/ietf-1/expected-images.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/vendor/fivefilters/readability.php/test/test-pages/ietf-1/expected-metadata.json b/vendor/fivefilters/readability.php/test/test-pages/ietf-1/expected-metadata.json new file mode 100644 index 0000000..ddf0094 --- /dev/null +++ b/vendor/fivefilters/readability.php/test/test-pages/ietf-1/expected-metadata.json @@ -0,0 +1,8 @@ +{ + "Author": "Jong, Michiel de", + "Direction": null, + "Excerpt": null, + "Image": null, + "Title": "remoteStorage", + "SiteName": null +} diff --git a/vendor/fivefilters/readability.php/test/test-pages/ietf-1/expected.html b/vendor/fivefilters/readability.php/test/test-pages/ietf-1/expected.html new file mode 100644 index 0000000..ab794ec --- /dev/null +++ b/vendor/fivefilters/readability.php/test/test-pages/ietf-1/expected.html @@ -0,0 +1,1115 @@ +
+ +[Docs] [txt|pdf] [Tracker] [Email] [Diff1] [Diff2] [Nits]
+
+Versions: 00 01 02 03 04
+
+
INTERNET DRAFT                                      Michiel B. de Jong
+Document: draft-dejong-remotestorage-04                   IndieHosters
+                                                             F. Kooman
+Intended Status: Proposed Standard                       (independent)
+Expires: 18 June 2015                                 15 December 2014
+
+
+                            remoteStorage
+
+Abstract
+
+    This draft describes a protocol by which client-side applications,
+    running inside a web browser, can communicate with a data storage
+    server that is hosted on a different domain name. This way, the
+    provider of a web application need not also play the role of data
+    storage provider. The protocol supports storing, retrieving, and
+    removing individual documents, as well as listing the contents of an
+    individual folder, and access control is based on bearer tokens.
+
+Status of this Memo
+
+   This Internet-Draft is submitted in full conformance with the
+   provisions of BCP 78 and BCP 79.
+
+   Internet-Drafts are working documents of the Internet Engineering
+   Task Force (IETF).  Note that other groups may also distribute
+   working documents as Internet-Drafts.  The list of current Internet-
+   Drafts is at http://datatracker.ietf.org/drafts/current/.
+
+   Internet-Drafts are draft documents valid for a maximum of six months
+   and may be updated, replaced, or obsoleted by other documents at any
+   time.  It is inappropriate to use Internet-Drafts as reference
+   material or to cite them other than as "work in progress."
+
+   This Internet-Draft will expire on 15 December 2014.
+
+Copyright Notice
+
+   Copyright (c) 2014 IETF Trust and the persons identified as the
+   document authors. All rights reserved.
+
+   This document is subject to BCP 78 and the IETF Trust's Legal
+   Provisions Relating to IETF Documents
+   (http://trustee.ietf.org/license-info) in effect on the date of
+   publication of this document.  Please review these documents
+   carefully, as they describe your rights and restrictions with respect
+   to this document.  Code Components extracted from this document must
+   include Simplified BSD License text as described in Section 4.e of
+   the Trust Legal Provisions and are provided without warranty as
+   described in the Simplified BSD License.
+
+
+de Jong                                                         [Page 1]
+
 
+Internet-Draft              remoteStorage                  December 2014
+
+
+Table of Contents
+
+   1. Introduction...................................................2
+   2. Terminology....................................................3
+   3. Storage model..................................................3
+   4. Requests.......................................................4
+   5. Response codes.................................................7
+   6. Versioning.....................................................7
+   7. CORS headers...................................................8
+   8. Session description............................................8
+   9. Bearer tokens and access control...............................9
+  10. Application-first bearer token issuance.......................10
+  11. Storage-first bearer token issuance...........................11
+  12. Example wire transcripts......................................12
+     12.1. WebFinger................................................12
+     12.2. OAuth dialog form........................................13
+     12.3. OAuth dialog form submission.............................14
+     12.4. OPTIONS preflight........................................15
+     12.5. Initial PUT..............................................15
+     12.6. Subsequent PUT...........................................16
+     12.7. GET......................................................16
+     12.8. DELETE...................................................17
+  13. Distributed versioning........................................17
+  14. Security Considerations.......................................19
+  15. IANA Considerations...........................................20
+  16. Acknowledgments...............................................20
+  17. References....................................................21
+     17.1. Normative References.....................................21
+     17.2. Informative References...................................21
+  18. Authors' addresses............................................22
+
+
+1.  Introduction
+
+    Many services for data storage are available over the internet. This
+    specification describes a vendor-independent interface for such
+    services. It is based on https, CORS and bearer tokens. The
+    metaphor for addressing data on the storage is that of folders
+    containing documents and subfolders. The actions the interface
+    exposes are:
+
+       *  GET a folder: retrieve the names and current versions of the
+          documents and subfolders currently contained by the folder
+
+
+de Jong                                                         [Page 2]
+
 
+Internet-Draft              remoteStorage                  December 2014
+
+
+       *  GET a document: retrieve its content type, current version,
+          and contents
+
+       *  PUT a document: store a new version, its content type, and
+          contents, conditional on the current version
+
+       *  DELETE a document: remove it from the storage, conditional on
+          the current version
+
+       *  HEAD a folder or document: like GET, but omitting the response
+          body
+
+    The exact details of these four actions are described in this
+    specification.
+
+2. Terminology
+
+    The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+    "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+    document are to be interpreted as described in RFC 2119 [WORDS].
+
+    "SHOULD" and "SHOULD NOT" are appropriate when valid exceptions to a
+    general requirement are known to exist or appear to exist, and it is
+    infeasible or impractical to enumerate all of them.  However, they
+    should not be interpreted as permitting implementors to fail to
+    implement the general requirement when such failure would result in
+    interoperability failure.
+
+3. Storage model
+
+    The server stores data in nodes that form a tree structure.
+    Internal nodes are called 'folders' and leaf nodes are called
+    'documents'. For a folder, the server stores references to nodes
+    contained in the folder, and it should be able to produce a list of
+    them, with for each contained item:
+
+       * item name
+       * item type (folder or document)
+       * current version
+       * content type
+       * content length
+
+    For a document, the server stores, and should be able to produce:
+
+
+de Jong                                                         [Page 3]
+
 
+Internet-Draft              remoteStorage                  December 2014
+
+
+
+       * current version
+       * content type
+       * content length
+       * content
+
+4. Requests
+
+    Client-to-server requests SHOULD be made over https [HTTPS], and
+    servers MUST comply with HTTP/1.1 [HTTP]. Specifically, they
+    MUST support chunked transfer coding on PUT requests. Servers MAY
+    also offer an optional switch from https to SPDY [SPDY].
+
+    A request is considered successful if the HTTP response code is in
+    the 2xx range (e.g. 200 OK, 201 Created), and unsuccessful if an
+    error occurred or a condition was not met (response code e.g. 404
+    Not Found, 304 Not Modified).
+
+    The root folder of the storage tree is represented by the following
+    URL:
+
+        URI_ENCODE( <storage_root> '/' )
+
+    Subsequently, if <parent_folder> is the URL of a folder, then the
+    URL of an item contained in it is:
+
+        URI_ENCODE( <parent_folder> <document_name> )
+
+    for a document, or:
+
+        URI_ENCODE( <parent_folder> <folder_name> '/' )
+
+    for a folder. Item names MAY contain all characters except '/' and
+    the null character, and MUST NOT have zero length.
+
+    A document description is a map containing one string-valued 'ETag'
+    field, one string-valued 'Content-Type' and one integer-valued
+    'Content-Length' field. They represent the document's current
+    version, its content type, and its content length respectively. Note
+    that content length is measured in octets (bytes), not in
+    characters.
+
+    A folder description is a map containing a string-valued 'ETag'
+
+
+de Jong                                                         [Page 4]
+
 
+Internet-Draft              remoteStorage                  December 2014
+
+
+    field, representing the folder's current version.
+
+    A successful GET request to a folder MUST be responded to with a
+    JSON-LD [JSON-LD] document (content type 'application/ld+json'),
+    containing as its 'items' field a map in which contained documents
+    appear as entries <item_name> to a document description, and
+    contained non-empty folders appear as entries <item_name> '/' to a
+    folder description. It MUST also contain an '@context' field with
+    the value 'http://remotestorage.io/spec/folder-description'. For
+    instance:
+
+       {
+         "@context": "http://remotestorage.io/spec/folder-description",
+         "items": {
+           "abc": {
+             "ETag": "DEADBEEFDEADBEEFDEADBEEF",
+             "Content-Type": "image/jpeg",
+             "Content-Length": 82352
+           },
+           "def/": {
+             "ETag": "1337ABCD1337ABCD1337ABCD"
+           }
+         }
+       }
+
+    All folders are treated as existing, and therefore GET requests to
+    untouched folders SHOULD be responded to with a folder description
+    with no items (the items field set to '{}'). However, an empty
+    folder MUST NOT be listed as an item in its parent folder.
+
+    Also, since folders exist automatically, PUT and DELETE requests
+    only need to be made to documents, and never to folders. A document
+    PUT will make all ancestor folders along its path become non-empty;
+    deleting the last document from a subtree will make that whole
+    subtree become empty. Folders will therefore show up in their parent
+    folder descriptions if and only if their subtree contains at least
+    one document.
+
+    A successful GET request to a document SHOULD be responded to with
+    the full document contents in the body, the document's content type
+    in a 'Content-Type' header, its content length in octets (not in
+    characters) in a 'Content-Length' header, and the document's current
+    version as a strong ETag in an 'ETag' header.
+
+
+de Jong                                                         [Page 5]
+
 
+Internet-Draft              remoteStorage                  December 2014
+
+
+
+    Note that the use of strong ETags prohibits changing the response
+    body based on request headers; in particular, the server will not be
+    able to serve the same document uncompressed to some clients and
+    gzipped when requested by the client, since the two bodies would not
+    be identical byte-for-byte.
+
+    Servers MAY support Content-Range headers [RANGE] on GET requests,
+    but whether or not they do SHOULD be announced through the <ranges>
+    variable mentioned below in section 10.
+
+    A successful PUT request to a document MUST result in:
+
+       * the request body being stored as the document's new content,
+       * parent and further ancestor folders being silently created as
+         necessary, with the document (name and version) being added to
+         its parent folder, and each folder added to its subsequent
+         parent,
+       * the value of its Content-Type header being stored as the
+         document's new content type,
+       * its version being updated, as well as that of its parent folder
+         and further ancestor folders, using a strong validator [HTTP,
+         section 7.2].
+
+    The response MUST contain a strong ETag header, with the document's
+    new version (for instance a hash of its contents) as its value.
+
+    A successful DELETE request to a document MUST result in:
+
+       * the deletion of that document from the storage, and from its
+         parent folder,
+       * silent deletion of the parent folder if it is left empty by
+         this, and so on for further ancestor folders,
+       * the version of its parent folder being updated, as well as that
+         of further ancestor folders.
+
+    A successful OPTIONS request SHOULD be responded to as described in
+    the CORS section below.
+
+    A successful HEAD request SHOULD be responded to like to the
+    equivalent GET request, but omitting the response body.
+
+
+
+
+de Jong                                                         [Page 6]
+
 
+Internet-Draft              remoteStorage                  December 2014
+
+
+5. Response codes
+
+    Response codes SHOULD be given as defined by [HTTP, section 6] and
+    [BEARER, section 3.1]. The following is a non-normative checklist
+    of status codes that are likely to occur in practice:
+
+       * 500 if an internal server error occurs,
+       * 429 if the client makes too frequent requests or is suspected
+             of malicious activity,
+       * 414 if the request URI is too long,
+       * 416 if Range requests are supported by the server and the Range
+             request can not be satisfied,
+       * 401 for all requests that don't have a bearer token with
+             sufficient permissions,
+       * 404 for all DELETE and GET requests to documents that do not
+             exist on the storage,
+       * 304 for a conditional GET request whose pre-condition
+             fails (see "Versioning" below),
+       * 409 for a PUT request where any folder name in the path
+             clashes with an existing document's name at the same
+             level, or where the document name coincides with an
+             existing folder's name at the same level.
+       * 412 for a conditional PUT or DELETE request whose pre-condition
+             fails (see "Versioning" below),
+       * 507 in case the account is over its storage quota,
+       * 4xx for all malformed requests (e.g. foreign characters in the
+             path), as well as for all PUT and DELETE requests to
+             folders,
+       * 2xx for all successful requests.
+
+    Clients SHOULD also handle the case where a response takes too long
+    to arrive, or where no response is received at all.
+
+6. Versioning
+
+    All successful requests MUST return an 'ETag' header [HTTP] with, in
+    the case of GET, the current version, in the case of PUT, the new
+    version, and in case of DELETE, the version that was deleted. All
+    successful GET requests MUST return an 'Expires: 0' header. PUT and
+    DELETE requests MAY have an 'If-Match' request header [COND], and
+    MUST fail with a 412 response code if that doesn't match the
+    document's current version.
+
+
+
+de Jong                                                         [Page 7]
+
 
+Internet-Draft              remoteStorage                  December 2014
+
+
+    GET requests MAY have a comma-separated list of revisions in an
+    'If-None-Match' header [COND], and SHOULD be responded to with a 304
+    response if that list includes the document or folder's current
+    version. A PUT request MAY have an 'If-None-Match: *' header [COND],
+    in which case it MUST fail with a 412 response code if the document
+    already exists.
+
+    In all 'ETag', 'If-Match' and 'If-None-Match' headers, revision
+    strings should appear inside double quotes (").
+
+    A provider MAY offer version rollback functionality to its users,
+    but this specification does not define the user interface for that.
+
+7. CORS headers
+
+    All responses MUST carry CORS headers [CORS]. The server MUST also
+    reply to OPTIONS requests as per CORS. For GET requests, a wildcard
+    origin MAY be returned, but for PUT and DELETE requests, the
+    response MUST echo back the Origin header sent by the client.
+
+8. Session description
+
+    The information that a client needs to receive in order to be able
+    to connect to a server SHOULD reach the client as described in the
+    'bearer token issuance' sections below. It consists of:
+
+       * <storage_root>, consisting of 'https://' followed by a server
+         host, and optionally a server port and a path prefix as per
+         [IRI]. Examples:
+         * 'https://example.com' (host only)
+         * 'https://example.com:8080' (host and port)
+         * 'https://example.com/path/to/storage' (host, port and
+           path prefix; note there is no trailing slash)
+       * <access_token> as per [OAUTH]. The token SHOULD be hard to
+         guess and SHOULD NOT be reused from one client to another. It
+         can however be reused in subsequent interactions with the same
+         client, as long as that client is still trusted. Example:
+         * 'ofb24f1ac3973e70j6vts19qr9v2eei'
+       * <storage_api>, always 'draft-dejong-remotestorage-04' for this
+         alternative version of the specification.
+
+    The client can make its requests using https with CORS and bearer
+    tokens, to the URL that is the concatenation of <storage_root> with
+
+
+de Jong                                                         [Page 8]
+
 
+Internet-Draft              remoteStorage                  December 2014
+
+
+    '/' plus one or more <folder> '/' strings indicating a path in the
+    folder tree, followed by zero or one <document> strings, indicating
+    a document. For example, if <storage_root> is
+    "https://storage.example.com/bob", then to retrieve the folder
+    contents of the /public/documents/ folder, or to retrieve a
+    'draft.txt' document from that folder, the client would make
+    requests to, respectively:
+
+    * https://storage.example.com/bob/public/documents/
+    * https://storage.example.com/bob/public/documents/draft.txt
+
+9. Bearer tokens and access control
+
+    A bearer token represents one or more access scopes. These access
+    scopes are represented as strings of the form <module> <level>,
+    where the <module> string SHOULD be lower-case alphanumerical, other
+    than the reserved word 'public', and <level> can be ':r' or ':rw'.
+    The access the bearer token gives is the sum of its access scopes,
+    with each access scope representing the following permissions:
+
+    '*:rw') any request,
+
+    '*:r') any GET or HEAD request,
+
+    <module> ':rw') any requests to paths that start with
+                    '/' <module> '/' or '/public/' <module> '/',
+
+    <module> ':r') any GET or HEAD requests to paths that start with
+                   '/' <module> '/' or '/public/' <module> '/',
+
+    As a special exceptions, GET requests to a document (but not a
+    folder) whose path starts with '/public/' are always allowed. They,
+    as well as OPTIONS requests, can be made without a bearer token.
+    Unless [KERBEROS] is used (see section 10 below), all other requests
+    SHOULD present a bearer token with sufficient access scope, using a
+    header of the following form (no double quotes here):
+
+       Authorization: Bearer <access_token>
+
+    In addition, providing the access token via a HTTP query parameter
+    for GET requests MAY be supported by the server, although its use
+    is not recommended, due to its security deficiencies; see [BEARER,
+    section 2.3].
+
+
+de Jong                                                         [Page 9]
+
 
+Internet-Draft              remoteStorage                  December 2014
+
+
+
+10. Application-first bearer token issuance
+
+    To make a remoteStorage server available as 'the remoteStorage of
+    <account> at <host>', exactly one link of the following format
+    SHOULD be added to the WebFinger record [WEBFINGER] of <account> at
+    <host>:
+
+    {
+      "href": <storage_root>,
+      "rel": "remotestorage",
+      "properties": {
+        "http://remotestorage.io/spec/version": <storage_api>,
+        "http://tools.ietf.org/html/rfc6749#section-4.2": <auth-dialog>,
+        ... : ... ,
+      }
+    }
+
+    Here <storage_root> and <storage_api> are as per "Session
+    description" above, and <auth-dialog> SHOULD be either null or a
+    URL where an OAuth 2.0 implicit-grant flow dialog [OAUTH] is
+    presented.
+
+    If <auth-dialog> is a URL, the user can supply their credentials
+    for accessing the account (how, is out of scope), and allow or
+    reject a request by the connecting application to obtain a bearer
+    token for a certain list of access scopes. Note that an account
+    will often belong to just one human user, but may also belong to a
+    group of multiple users (the remoteStorage of <group> at <host>).
+
+    If <auth-dialog> is null, the client will not have a way to obtain
+    an access token, and SHOULD send all requests without Authorization
+    header, and rely on Kerberos [KERBEROS] instead for requests that
+    would normally be sent with a bearer token, but servers SHOULD NOT
+    impose any such access barriers for resources that would normally
+    not require an access token.
+
+    The '...' ellipses indicate that more properties may be present.
+    Non-breaking examples that have been proposed so far, include a
+    "http://tools.ietf.org/html/rfc6750#section-2.3" property, set to
+    the string value "true" if the server supports passing the bearer
+    token in the URI query parameter as per section 2.3 of [BEARER],
+    instead of in the request header.
+
+
+de Jong                                                        [Page 10]
+
 
+Internet-Draft              remoteStorage                  December 2014
+
+
+
+    Another example is "http://tools.ietf.org/html/rfc7233" with a
+    string value of "GET" if Content-Range headers are supported for
+    GET requests as per [RANGE], "PUT" if they are supported for PUT
+    requests, and "GET,PUT" if supported for both.
+
+    Both these proposals are non-breaking extensions, since the client
+    will have a way to work around it if these features are not present
+    (e.g. retrieve the protected resource asynchronously in the first
+    case, or request the entire resource in the second case).
+
+    A "http://remotestorage.io/spec/web-authoring" property has been
+    proposed with a string value of the fully qualified domain name to
+    which web authoring content is published if the server supports web
+    authoring as per [AUTHORING]. Note that this extension is a breaking
+    extension in the sense that it divides users into "haves", whose
+    remoteStorage accounts allow them to author web content, and
+    "have-nots", whose remoteStorage account does not support this
+    functionality.
+
+    The server MAY expire bearer tokens, and MAY require the user to
+    register applications as OAuth clients before first use; if no
+    client registration is required, then the server MAY ignore the
+    client_id parameter in favor of relying on the redirect_uri
+    parameter for client identification.
+
+11. Storage-first bearer token issuance
+
+    The provider MAY also present a dashboard to the user, where they
+    have some way to add open web app manifests [MANIFEST]. Adding a
+    manifest to the dashboard is considered equivalent to clicking
+    'accept' in the dialog of the application-first flow. Removing one
+    is considered equivalent to revoking its access token.
+
+    As an equivalent to OAuth's 'scope' parameter, a 'datastores-access'
+    field SHOULD be present in the root of such an application manifest
+    document, with entries <module> -> '{"access": "readonly"}' for
+    <level> 'r' or '{"access": "readwrite"}' for <level> 'rw', as
+    prescribed in [DATASTORE].
+
+    When the user gestures they want to use a certain application whose
+    manifest is present on the dashboard, the dashboard SHOULD redirect
+    to the application or open it in a new window. To mimic coming back
+
+
+de Jong                                                        [Page 11]
+
 
+Internet-Draft              remoteStorage                  December 2014
+
+
+    from the OAuth dialog, it MAY add 'access_token' and 'scope'
+    fields to the URL fragment.
+
+    Regardless of whether 'access_token' and 'scope' are specified, it
+    SHOULD add a 'remotestorage' field to the URL fragment, with a
+    value of the form <account> '@' <host>. When the application detects
+    this parameter, it SHOULD resolve the WebFinger record for <account>
+    at <host> and extract the <storage_root> and <storage_api>
+    information.
+
+    If no access_token was given, then the application SHOULD also
+    extract the <auth_endpoint> information from WebFinger, and continue
+    as per application-first bearer token issuance.
+
+    Note that whereas a remoteStorage server SHOULD offer support for
+    the application-first flow with WebFinger and OAuth, it MAY choose
+    not to support the storage-first flow, provided that users will
+    easily remember their <account> '@' <host> WebFinger address at that
+    provider. Applications SHOULD, however, support both flows, which
+    means checking the URL for a 'remotestorage' parameter, but giving
+    the user a way to specify the WebFinger address if there is none.
+
+    If a server provides an application manifest dashboard, then it
+    SHOULD merge the list of applications there with the list of
+    issued access tokens as specified by OAuth into one list. Also,
+    the interface for revoking an access token as specified by OAuth
+    SHOULD coincide with removing an application from the dashboard.
+
+    Servers MAY also provide a way to create access tokens directly from
+    their user interface. Such functionality would be aimed mainly at
+    developers, to manually copy and paste a token into a script or
+    debug tool, thus bypassing the need for an OAuth dance. Clients
+    SHOULD NOT rely on this in production.
+
+12. Example wire transcripts
+
+    The following examples are not normative ("\" indicates a line was
+    wrapped).
+
+12.1. WebFinger
+
+    In application-first, an in-browser application might issue the
+    following request, using XMLHttpRequest and CORS:
+
+
+de Jong                                                        [Page 12]
+
 
+Internet-Draft              remoteStorage                  December 2014
+
+
+
+         GET /.well-known/webfinger?resource=acct:michiel@michielbdejon\
+g.com HTTP/1.1
+         Host: michielbdejong.com
+
+    and the server's response might look like this:
+
+         HTTP/1.1 200 OK
+         Access-Control-Allow-Origin: *
+         Access-Control-Allow-Methods: GET
+         Access-Control-Allow-Headers: If-Match, If-None-Match
+         Access-Control-Expose-Headers: ETag, Content-Length
+         Content-Type: application/jrd+json
+
+         {
+           "links":[{
+             "href": "https://michielbdejong.com:7678/inbox",
+             "rel": "post-me-anything"
+           }, {
+             "href": "https://michielbdejong.com/me.jpg",
+             "rel": "avatar"
+           }, {
+             "href": "https://3pp.io:4439/storage/michiel",
+             "rel": "remotestorage",
+             "properties": {
+               "http://remotestorage.io/spec/version": "draft-dejong-re\
+motestorage-04",
+               "http://tools.ietf.org/html/rfc6749#section-4.2": "https\
+://3pp.io:4439/oauth/michiel",
+               "http://tools.ietf.org/html/rfc6750#section-2.3": false,
+               "http://tools.ietf.org/html/rfc7233": false,
+               "http://remotestorage.io/spec/web-authoring": false
+             }
+           }]
+         }
+
+12.2. OAuth dialog form
+
+    Once the in-browser application has discovered the server's OAuth
+    end-point, it will typically redirect the user to this URL, in
+    order to obtain a bearer token. Say the application is hosted on
+    https://drinks-unhosted.5apps.com/ and wants read-write access to
+    the account's "myfavoritedrinks" scope:
+
+
+de Jong                                                        [Page 13]
+
 
+Internet-Draft              remoteStorage                  December 2014
+
+
+
+        GET /oauth/michiel?redirect_uri=https%3A%2F%2Fdrinks-unhosted.5\
+apps.com%2F&scope=myfavoritedrinks%3Arw&client_id=https%3A%2F%2Fdrinks-\
+unhosted.5apps.com&response_type=token HTTP/1.1
+        Host: 3pp.io
+
+    The server's response might look like this (truncated for brevity):
+
+        HTTP/1.1 200 OK
+
+        <!DOCTYPE html>
+        <html lang="en">
+          <head>
+            <title>Allow access?</title>
+        ...
+
+12.3. OAuth dialog form submission
+
+    When the user submits the form, the request would look something
+    like this:
+
+        POST /oauth HTTP/1.1
+        Host: 3pp.io:4439
+        Origin: https://3pp.io:4439
+        Content-Type: application/x-www-form-urlencoded
+        Referer: https://3pp.io:4439/oauth/michiel?redirect_uri=https%3\
+A%2F%2Fdrinks-unhosted.5apps.com%2F&scope=myfavoritedrinks%3Arw&client_\
+id=https%3A%2F%2Fdrinks-unhosted.5apps.com&response_type=token
+
+        client_id=https%3A%2F%2Fdrinks-unhosted.5apps.com&redirect_uri=\
+https%3A%2F%2Fdrinks-unhosted.5apps.com%2F&response_type=token&scope=my\
+favoritedrinks%3Arw&state=&username=michiel&password=something&allow=Al\
+low
+
+    To which the server could respond with a 302 redirect, back to the
+    origin of the requesting application:
+
+        HTTP/1.1 302 Found
+        Location:https://drinks-unhosted.5apps.com/#access_token=j2YnGt\
+XjzzzHNjkd1CJxoQubA1o%3D&token_type=bearer&state=
+
+12.4. OPTIONS preflight
+
+
+
+de Jong                                                        [Page 14]
+
 
+Internet-Draft              remoteStorage                  December 2014
+
+
+    When an in-browser application makes a cross-origin request which
+    may affect the server-state, the browser will make a preflight
+    request first, with the OPTIONS verb, for instance:
+
+        OPTIONS /storage/michiel/myfavoritedrinks/ HTTP/1.1
+        Host: 3pp.io:4439
+        Access-Control-Request-Method: GET
+        Origin: https://drinks-unhosted.5apps.com
+        Access-Control-Request-Headers: Authorization
+        Referer: https://drinks-unhosted.5apps.com/
+
+    To which the server can for instance respond:
+
+        HTTP/1.1 200 OK
+        Access-Control-Allow-Origin: https://drinks-unhosted.5apps.com
+        Access-Control-Allow-Methods: GET, PUT, DELETE
+        Access-Control-Allow-Headers: Authorization, Content-Length, Co\
+ntent-Type, Origin, X-Requested-With, If-Match, If-None-Match
+
+12.5. Initial PUT
+
+    An initial PUT may contain an 'If-None-Match: *' header, like this:
+
+        PUT /storage/michiel/myfavoritedrinks/test HTTP/1.1
+        Host: 3pp.io:4439
+        Content-Length: 91
+        Origin: https://drinks-unhosted.5apps.com
+        Authorization: Bearer j2YnGtXjzzzHNjkd1CJxoQubA1o=
+        Content-Type: application/json; charset=UTF-8
+        Referer: https://drinks-unhosted.5apps.com/?
+        If-None-Match: *
+
+        {"name":"test","@context":"http://remotestorage.io/spec/modules\
+/myfavoritedrinks/drink"}
+
+    And the server may respond with either a 201 Created or a 200 OK
+    status:
+
+        HTTP/1.1 201 Created
+        Access-Control-Allow-Origin: https://drinks-unhosted.5apps.com
+        ETag: "1382694045000"
+
+12.6. Subsequent PUT
+
+
+de Jong                                                        [Page 15]
+
 
+Internet-Draft              remoteStorage                  December 2014
+
+
+
+    A subsequent PUT may contain an 'If-Match' header referring to the
+    ETag previously returned, like this:
+
+        PUT /storage/michiel/myfavoritedrinks/test HTTP/1.1
+        Host: 3pp.io:4439
+        Content-Length: 91
+        Origin: https://drinks-unhosted.5apps.com
+        Authorization: Bearer j2YnGtXjzzzHNjkd1CJxoQubA1o=
+        Content-Type: application/json; charset=UTF-8
+        Referer: https://drinks-unhosted.5apps.com/?
+        If-Match: "1382694045000"
+
+        {"name":"test", "updated":true, "@context":"http://remotestorag\
+e.io/spec/modules/myfavoritedrinks/drink"}
+
+    And the server may respond with a 412 Conflict or a 200 OK status:
+
+        HTTP/1.1 200 OK
+        Access-Control-Allow-Origin: https://drinks-unhosted.5apps.com
+        ETag: "1382694048000"
+
+12.7. GET
+
+    A GET request would also include the bearer token, and optionally
+    an If-None-Match header:
+
+        GET /storage/michiel/myfavoritedrinks/test HTTP/1.1
+        Host: 3pp.io:4439
+        Origin: https://drinks-unhosted.5apps.com
+        Authorization: Bearer j2YnGtXjzzzHNjkd1CJxoQubA1o=
+        Referer: https://drinks-unhosted.5apps.com/?
+        If-None-Match: "1382694045000", "1382694048000"
+
+    And the server may respond with a 304 Not Modified status:
+
+        HTTP/1.1 304 Not Modified
+        Access-Control-Allow-Origin: https://drinks-unhosted.5apps.com
+        ETag: "1382694048000"
+
+    Or a 200 OK status, plus a response body:
+
+        HTTP/1.1 200 OK
+
+
+de Jong                                                        [Page 16]
+
 
+Internet-Draft              remoteStorage                  December 2014
+
+
+        Access-Control-Allow-Origin: https://drinks-unhosted.5apps.com
+        Content-Type: application/json; charset=UTF-8
+        Content-Length: 106
+        ETag: "1382694048000"
+        Expires: 0
+
+        {"name":"test", "updated":true, "@context":"http://remotestora\
+ge.io/spec/modules/myfavoritedrinks/drink"}
+
+    If the GET URL would have been "/storage/michiel/myfavoritedrinks/",
+    a 200 OK response would have a folder description as the response
+    body:
+
+        HTTP/1.1 200 OK
+        Access-Control-Allow-Origin: https://drinks-unhosted.5apps.com
+        Content-Type: application/ld+json
+        Content-Length: 171
+        ETag: "1382694048000"
+        Expires: 0
+
+        {"@context":"http://remotestorage.io/spec/folder-version","ite\
+ms":{"test":{"ETag":"1382694048000","Content-Type":"application/json; \
+charset=UTF-8","Content-Length":106}}}
+
+    If the GET URL would have been a non-existing document like
+    "/storage/michiel/myfavoritedrinks/x", the response would have a 404
+    Not Found status, and no ETag header:
+
+        HTTP/1.1 404 Not Found
+        Access-Control-Allow-Origin: https://drinks-unhosted.5apps.com
+
+12.8. DELETE
+
+    A DELETE request may look like this:
+
+        DELETE /storage/michiel/myfavoritedrinks/test HTTP/1.1
+        Host: 3pp.io:4439
+        Origin: https://drinks-unhosted.5apps.com
+        Authorization: Bearer j2YnGtXjzzzHNjkd1CJxoQubA1o=
+        Content-Type: application/json; charset=UTF-8
+        Referer: https://drinks-unhosted.5apps.com/?
+        If-Match: "1382694045000"
+
+
+
+de Jong                                                        [Page 17]
+
 
+Internet-Draft              remoteStorage                  December 2014
+
+
+    And the server may respond with a 412 Conflict or a 200 OK status:
+
+        HTTP/1.1 412 Conflict
+        Access-Control-Allow-Origin: https://drinks-unhosted.5apps.com
+        ETag: "1382694048000"
+
+13. Distributed versioning
+
+    This section is non-normative, and is intended to explain some of
+    the design choices concerning ETags and folder listings. At the
+    same time it will hopefully help readers who intend to develop an
+    application that uses remoteStorage as its per-user data storage.
+    When multiple clients have read/write access to the same document,
+    versioning conflicts may occur. For instance, client A may make
+    a PUT request that changes the document from version 1 to version
+    2, after which client B may make a PUT request attempting to change
+    the same document from version 1 to version 3.
+
+    In this case, client B can add an 'If-Match: "1"' header, which
+    would trigger a 412 Conflict response code, since the current
+    version ("2") does not match the version required as a condition by
+    the header If-Match header ("1").
+
+    Client B is now aware of the conflict, and may consult the user,
+    saying the update to version 3 failed. The user may then choose,
+    through the user interface of client B, whether version 2 or
+    version 3 should be kept, or maybe the document should be reverted
+    on the server to version 1, or a merged version 4 is needed. Client
+    B may then make a request that puts the document to the version the
+    user wishes; this time setting an 'If-Match: "2"' header instead.
+
+    Both client A and client B would periodically poll the root
+    folder of each scope they have access to, to see if the version
+    of the root folder changed. If it did, then one of the versions
+    listed in there will necessarily have changed, and the client can
+    make a GET request to that child folder or document, to obtain
+    its latest version.
+
+    Because an update in a document will result in a version change of
+    its containing folder, and that change will propagate all the way
+    to the root folder, it is not necessary to poll each document for
+    changes individually.
+
+
+
+de Jong                                                        [Page 18]
+
 
+Internet-Draft              remoteStorage                  December 2014
+
+
+    As an example, the root folder may contain 10 directories,
+    each of which contain 10 directories, which each contain 10
+    documents, so their paths would be for instance '/0/0/1', '/0/0/2',
+    etcetera. Then one GET request to the root folder '/' will be
+    enough to know if any of these 1000 documents has changed.
+
+    Say document '/7/9/2' has changed; then the GET request to '/' will
+    come back with a different ETag, and entry '7/' will have a
+    different value in its JSON content. The client could then request
+    '/7/', '/7/9/', and '/7/9/2' to narrow down the one document that
+    caused the root folder's ETag to change.
+
+    Note that the remoteStorage server does not get involved in the
+    conflict resolution. It keeps the canonical current version at all
+    times, and allows clients to make conditional GET and PUT requests,
+    but it is up to whichever client discovers a given version
+    conflict, to resolve it.
+
+14. Security Considerations
+
+    To prevent man-in-the-middle attacks, the use of https instead of
+    http is important for both the interface itself and all end-points
+    involved in WebFinger, OAuth, and (if present) the storage-first
+    application launch dashboard.
+
+    A malicious party could link to an application, but specifying a
+    remoteStorage account address that it controls, thus tricking the
+    user into using a trusted application to send sensitive data to the
+    wrong remoteStorage server. To mitigate this, applications SHOULD
+    clearly display to which remoteStorage server they are sending the
+    user's data.
+
+    Applications could request scopes that the user did not intend to
+    give access to. The user SHOULD always be prompted to carefully
+    review which scopes an application is requesting.
+
+    An application may upload malicious html pages and then trick the
+    user into visiting them, or upload malicious client-side scripts,
+    that take advantage of being hosted on the user's domain name. The
+    origin on which the remoteStorage server has its interface SHOULD
+    therefore NOT be used for anything else, and the user SHOULD be
+    warned not to visit any web pages on that origin. In particular, the
+    OAuth dialog and launch dashboard or token revokation interface
+
+
+de Jong                                                        [Page 19]
+
 
+Internet-Draft              remoteStorage                  December 2014
+
+
+    SHOULD be on a different origin than the remoteStorage interface.
+
+    Where the use of bearer tokens is impractical, a user may choose to
+    store documents on hard-to-guess URLs whose path after
+    <storage_root> starts with '/public/', while sharing this URL only
+    with the intended audience. That way, only parties who know the
+    document's hard-to-guess URL, can access it. The server SHOULD
+    therefore make an effort to detect and stop brute-force attacks that
+    attempt to guess the location of such documents.
+
+    The server SHOULD also detect and stop denial-of-service attacks
+    that aim to overwhelm its interface with too much traffic.
+
+15. IANA Considerations
+
+    This document registers the 'remotestorage' link relation, as well
+    as the following WebFinger properties:
+      * "http://remotestorage.io/spec/version"
+      * "http://tools.ietf.org/html/rfc6749#section-4.2"
+      * "http://tools.ietf.org/html/rfc6750#section-2.3"
+      * "http://tools.ietf.org/html/rfc7233"
+      * "http://remotestorage.io/spec/web-authoring"
+
+16. Acknowledgements
+
+    The authors would like to thank everybody who contributed to the
+    development of this protocol, including Kenny Bentley, Javier Diaz,
+    Daniel Groeber, Bjarni Runar, Jan Wildeboer, Charles Schultz, Peter
+    Svensson, Valer Mischenko, Michiel Leenaars, Jan-Christoph
+    Borchardt, Garret Alfert, Sebastian Kippe, Max Wiehle, Melvin
+    Carvalho, Martin Stadler, Geoffroy Couprie, Niklas Cathor, Marco
+    Stahl, James Coglan, Ken Eucker, Daniel Brolund, elf Pavlik, Nick
+    Jennings, Markus Sabadello, Steven te Brinke, Matthias Treydte,
+    Rick van Rein, Mark Nottingham, Julian Reschke, and Markus
+    Lanthaler, among many others.
+
+17. References
+
+17.1. Normative References
+
+    [WORDS]
+        Bradner, S., "Key words for use in RFCs to Indicate Requirement
+        Levels", BCP 14, RFC 2119, March 1997.
+
+
+de Jong                                                        [Page 20]
+
 
+Internet-Draft              remoteStorage                  December 2014
+
+
+
+    [IRI]
+        Duerst, M., "Internationalized Resource Identifiers (IRIs)",
+        RFC 3987, January 2005.
+
+    [WEBFINGER]
+        Jones, P., Salguerio, G., Jones, M, and Smarr, J.,
+        "WebFinger", RFC7033, September 2013.
+
+    [OAUTH]
+        "Section 4.2: Implicit Grant", in: Hardt, D. (ed), "The OAuth
+        2.0 Authorization Framework", RFC6749, October 2012.
+
+17.2. Informative References
+
+    [HTTPS]
+        Rescorla, E., "HTTP Over TLS", RFC2818, May 2000.
+
+    [HTTP]
+        Fielding et al., "Hypertext Transfer Protocol (HTTP/1.1):
+        Semantics and Content", RFC7231, June 2014.
+
+    [COND]
+        Fielding et al., "Hypertext Transfer Protocol (HTTP/1.1):
+        Conditional Requests", RFC7232, June 2014.
+
+    [RANGE]
+        Fielding et al., "Hypertext Transfer Protocol (HTTP/1.1):
+        Conditional Requests", RFC7233, June 2014.
+
+    [SPDY]
+        Mark Belshe, Roberto Peon, "SPDY Protocol - Draft 3.1", http://
+        www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1,
+        September 2013.
+
+    [JSON-LD]
+        M. Sporny, G. Kellogg, M. Lanthaler, "JSON-LD 1.0", W3C
+        Proposed Recommendation,
+        http://www.w3.org/TR/2014/REC-json-ld-20140116/, January 2014.
+
+    [CORS]
+        van Kesteren, Anne (ed), "Cross-Origin Resource Sharing --
+        W3C Candidate Recommendation 29 January 2013",
+
+
+de Jong                                                        [Page 21]
+
 
+Internet-Draft              remoteStorage                  December 2014
+
+
+        http://www.w3.org/TR/cors/, January 2013.
+
+    [MANIFEST]
+        Mozilla Developer Network (ed), "App manifest -- Revision
+        330541", https://developer.mozilla.org/en-
+        US/Apps/Build/Manifest$revision/566677, April 2014.
+
+    [DATASTORE]
+        "WebAPI/DataStore", MozillaWiki, retrieved May 2014.
+        https://wiki.mozilla.org/WebAPI/DataStore#Manifest
+
+    [KERBEROS]
+        C. Neuman et al., "The Kerberos Network Authentication Service
+        (V5)", RFC4120, July 2005.
+
+    [BEARER]
+        M. Jones, D. Hardt, "The OAuth 2.0 Authorization Framework:
+        Bearer Token Usage", RFC6750, October 2012.
+
+    [AUTHORING]
+        "Using remoteStorage for web authoring", reSite wiki, retrieved
+        September 2014. https://github.com/michielbdejong/resite/wiki
+        /Using-remoteStorage-for-web-authoring
+
+18. Authors' addresses
+
+    Michiel B. de Jong
+    IndieHosters
+
+    Email: michiel@michielbdejong.com
+
+
+    F. Kooman
+    (independent)
+
+    Email: fkooman@tuxed.net
+
+
+
+
+
+
+
+
+
+de Jong                                                        [Page 22]
+
+

+Html markup produced by rfcmarkup 1.111, available from +https://tools.ietf.org/tools/rfcmarkup/ + +
\ No newline at end of file diff --git a/vendor/fivefilters/readability.php/test/test-pages/ietf-1/source.html b/vendor/fivefilters/readability.php/test/test-pages/ietf-1/source.html new file mode 100644 index 0000000..ded744e --- /dev/null +++ b/vendor/fivefilters/readability.php/test/test-pages/ietf-1/source.html @@ -0,0 +1,1269 @@ + + + + + + + + + + + + + + + + + draft-dejong-remotestorage-04 - remoteStorage + + + + + + + + +
+
+ +
+[Docs] [txt|pdf] [Tracker] [Email] [Diff1] [Diff2] [Nits]
+
+Versions: 00 01 02 03 04
+
+
INTERNET DRAFT                                      Michiel B. de Jong
+Document: draft-dejong-remotestorage-04                   IndieHosters
+                                                             F. Kooman
+Intended Status: Proposed Standard                       (independent)
+Expires: 18 June 2015                                 15 December 2014
+
+
+                            remoteStorage
+
+Abstract
+
+    This draft describes a protocol by which client-side applications,
+    running inside a web browser, can communicate with a data storage
+    server that is hosted on a different domain name. This way, the
+    provider of a web application need not also play the role of data
+    storage provider. The protocol supports storing, retrieving, and
+    removing individual documents, as well as listing the contents of an
+    individual folder, and access control is based on bearer tokens.
+
+Status of this Memo
+
+   This Internet-Draft is submitted in full conformance with the
+   provisions of BCP 78 and BCP 79.
+
+   Internet-Drafts are working documents of the Internet Engineering
+   Task Force (IETF).  Note that other groups may also distribute
+   working documents as Internet-Drafts.  The list of current Internet-
+   Drafts is at http://datatracker.ietf.org/drafts/current/.
+
+   Internet-Drafts are draft documents valid for a maximum of six months
+   and may be updated, replaced, or obsoleted by other documents at any
+   time.  It is inappropriate to use Internet-Drafts as reference
+   material or to cite them other than as "work in progress."
+
+   This Internet-Draft will expire on 15 December 2014.
+
+Copyright Notice
+
+   Copyright (c) 2014 IETF Trust and the persons identified as the
+   document authors. All rights reserved.
+
+   This document is subject to BCP 78 and the IETF Trust's Legal
+   Provisions Relating to IETF Documents
+   (http://trustee.ietf.org/license-info) in effect on the date of
+   publication of this document.  Please review these documents
+   carefully, as they describe your rights and restrictions with respect
+   to this document.  Code Components extracted from this document must
+   include Simplified BSD License text as described in Section 4.e of
+   the Trust Legal Provisions and are provided without warranty as
+   described in the Simplified BSD License.
+
+
+de Jong                                                         [Page 1]
+

+Internet-Draft              remoteStorage                  December 2014
+
+
+Table of Contents
+
+   1. Introduction...................................................2
+   2. Terminology....................................................3
+   3. Storage model..................................................3
+   4. Requests.......................................................4
+   5. Response codes.................................................7
+   6. Versioning.....................................................7
+   7. CORS headers...................................................8
+   8. Session description............................................8
+   9. Bearer tokens and access control...............................9
+  10. Application-first bearer token issuance.......................10
+  11. Storage-first bearer token issuance...........................11
+  12. Example wire transcripts......................................12
+     12.1. WebFinger................................................12
+     12.2. OAuth dialog form........................................13
+     12.3. OAuth dialog form submission.............................14
+     12.4. OPTIONS preflight........................................15
+     12.5. Initial PUT..............................................15
+     12.6. Subsequent PUT...........................................16
+     12.7. GET......................................................16
+     12.8. DELETE...................................................17
+  13. Distributed versioning........................................17
+  14. Security Considerations.......................................19
+  15. IANA Considerations...........................................20
+  16. Acknowledgments...............................................20
+  17. References....................................................21
+     17.1. Normative References.....................................21
+     17.2. Informative References...................................21
+  18. Authors' addresses............................................22
+
+
+1.  Introduction
+
+    Many services for data storage are available over the internet. This
+    specification describes a vendor-independent interface for such
+    services. It is based on https, CORS and bearer tokens. The
+    metaphor for addressing data on the storage is that of folders
+    containing documents and subfolders. The actions the interface
+    exposes are:
+
+       *  GET a folder: retrieve the names and current versions of the
+          documents and subfolders currently contained by the folder
+
+
+de Jong                                                         [Page 2]
+

+Internet-Draft              remoteStorage                  December 2014
+
+
+       *  GET a document: retrieve its content type, current version,
+          and contents
+
+       *  PUT a document: store a new version, its content type, and
+          contents, conditional on the current version
+
+       *  DELETE a document: remove it from the storage, conditional on
+          the current version
+
+       *  HEAD a folder or document: like GET, but omitting the response
+          body
+
+    The exact details of these four actions are described in this
+    specification.
+
+2. Terminology
+
+    The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+    "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+    document are to be interpreted as described in RFC 2119 [WORDS].
+
+    "SHOULD" and "SHOULD NOT" are appropriate when valid exceptions to a
+    general requirement are known to exist or appear to exist, and it is
+    infeasible or impractical to enumerate all of them.  However, they
+    should not be interpreted as permitting implementors to fail to
+    implement the general requirement when such failure would result in
+    interoperability failure.
+
+3. Storage model
+
+    The server stores data in nodes that form a tree structure.
+    Internal nodes are called 'folders' and leaf nodes are called
+    'documents'. For a folder, the server stores references to nodes
+    contained in the folder, and it should be able to produce a list of
+    them, with for each contained item:
+
+       * item name
+       * item type (folder or document)
+       * current version
+       * content type
+       * content length
+
+    For a document, the server stores, and should be able to produce:
+
+
+de Jong                                                         [Page 3]
+

+Internet-Draft              remoteStorage                  December 2014
+
+
+
+       * current version
+       * content type
+       * content length
+       * content
+
+4. Requests
+
+    Client-to-server requests SHOULD be made over https [HTTPS], and
+    servers MUST comply with HTTP/1.1 [HTTP]. Specifically, they
+    MUST support chunked transfer coding on PUT requests. Servers MAY
+    also offer an optional switch from https to SPDY [SPDY].
+
+    A request is considered successful if the HTTP response code is in
+    the 2xx range (e.g. 200 OK, 201 Created), and unsuccessful if an
+    error occurred or a condition was not met (response code e.g. 404
+    Not Found, 304 Not Modified).
+
+    The root folder of the storage tree is represented by the following
+    URL:
+
+        URI_ENCODE( <storage_root> '/' )
+
+    Subsequently, if <parent_folder> is the URL of a folder, then the
+    URL of an item contained in it is:
+
+        URI_ENCODE( <parent_folder> <document_name> )
+
+    for a document, or:
+
+        URI_ENCODE( <parent_folder> <folder_name> '/' )
+
+    for a folder. Item names MAY contain all characters except '/' and
+    the null character, and MUST NOT have zero length.
+
+    A document description is a map containing one string-valued 'ETag'
+    field, one string-valued 'Content-Type' and one integer-valued
+    'Content-Length' field. They represent the document's current
+    version, its content type, and its content length respectively. Note
+    that content length is measured in octets (bytes), not in
+    characters.
+
+    A folder description is a map containing a string-valued 'ETag'
+
+
+de Jong                                                         [Page 4]
+

+Internet-Draft              remoteStorage                  December 2014
+
+
+    field, representing the folder's current version.
+
+    A successful GET request to a folder MUST be responded to with a
+    JSON-LD [JSON-LD] document (content type 'application/ld+json'),
+    containing as its 'items' field a map in which contained documents
+    appear as entries <item_name> to a document description, and
+    contained non-empty folders appear as entries <item_name> '/' to a
+    folder description. It MUST also contain an '@context' field with
+    the value 'http://remotestorage.io/spec/folder-description'. For
+    instance:
+
+       {
+         "@context": "http://remotestorage.io/spec/folder-description",
+         "items": {
+           "abc": {
+             "ETag": "DEADBEEFDEADBEEFDEADBEEF",
+             "Content-Type": "image/jpeg",
+             "Content-Length": 82352
+           },
+           "def/": {
+             "ETag": "1337ABCD1337ABCD1337ABCD"
+           }
+         }
+       }
+
+    All folders are treated as existing, and therefore GET requests to
+    untouched folders SHOULD be responded to with a folder description
+    with no items (the items field set to '{}'). However, an empty
+    folder MUST NOT be listed as an item in its parent folder.
+
+    Also, since folders exist automatically, PUT and DELETE requests
+    only need to be made to documents, and never to folders. A document
+    PUT will make all ancestor folders along its path become non-empty;
+    deleting the last document from a subtree will make that whole
+    subtree become empty. Folders will therefore show up in their parent
+    folder descriptions if and only if their subtree contains at least
+    one document.
+
+    A successful GET request to a document SHOULD be responded to with
+    the full document contents in the body, the document's content type
+    in a 'Content-Type' header, its content length in octets (not in
+    characters) in a 'Content-Length' header, and the document's current
+    version as a strong ETag in an 'ETag' header.
+
+
+de Jong                                                         [Page 5]
+

+Internet-Draft              remoteStorage                  December 2014
+
+
+
+    Note that the use of strong ETags prohibits changing the response
+    body based on request headers; in particular, the server will not be
+    able to serve the same document uncompressed to some clients and
+    gzipped when requested by the client, since the two bodies would not
+    be identical byte-for-byte.
+
+    Servers MAY support Content-Range headers [RANGE] on GET requests,
+    but whether or not they do SHOULD be announced through the <ranges>
+    variable mentioned below in section 10.
+
+    A successful PUT request to a document MUST result in:
+
+       * the request body being stored as the document's new content,
+       * parent and further ancestor folders being silently created as
+         necessary, with the document (name and version) being added to
+         its parent folder, and each folder added to its subsequent
+         parent,
+       * the value of its Content-Type header being stored as the
+         document's new content type,
+       * its version being updated, as well as that of its parent folder
+         and further ancestor folders, using a strong validator [HTTP,
+         section 7.2].
+
+    The response MUST contain a strong ETag header, with the document's
+    new version (for instance a hash of its contents) as its value.
+
+    A successful DELETE request to a document MUST result in:
+
+       * the deletion of that document from the storage, and from its
+         parent folder,
+       * silent deletion of the parent folder if it is left empty by
+         this, and so on for further ancestor folders,
+       * the version of its parent folder being updated, as well as that
+         of further ancestor folders.
+
+    A successful OPTIONS request SHOULD be responded to as described in
+    the CORS section below.
+
+    A successful HEAD request SHOULD be responded to like to the
+    equivalent GET request, but omitting the response body.
+
+
+
+
+de Jong                                                         [Page 6]
+

+Internet-Draft              remoteStorage                  December 2014
+
+
+5. Response codes
+
+    Response codes SHOULD be given as defined by [HTTP, section 6] and
+    [BEARER, section 3.1]. The following is a non-normative checklist
+    of status codes that are likely to occur in practice:
+
+       * 500 if an internal server error occurs,
+       * 429 if the client makes too frequent requests or is suspected
+             of malicious activity,
+       * 414 if the request URI is too long,
+       * 416 if Range requests are supported by the server and the Range
+             request can not be satisfied,
+       * 401 for all requests that don't have a bearer token with
+             sufficient permissions,
+       * 404 for all DELETE and GET requests to documents that do not
+             exist on the storage,
+       * 304 for a conditional GET request whose pre-condition
+             fails (see "Versioning" below),
+       * 409 for a PUT request where any folder name in the path
+             clashes with an existing document's name at the same
+             level, or where the document name coincides with an
+             existing folder's name at the same level.
+       * 412 for a conditional PUT or DELETE request whose pre-condition
+             fails (see "Versioning" below),
+       * 507 in case the account is over its storage quota,
+       * 4xx for all malformed requests (e.g. foreign characters in the
+             path), as well as for all PUT and DELETE requests to
+             folders,
+       * 2xx for all successful requests.
+
+    Clients SHOULD also handle the case where a response takes too long
+    to arrive, or where no response is received at all.
+
+6. Versioning
+
+    All successful requests MUST return an 'ETag' header [HTTP] with, in
+    the case of GET, the current version, in the case of PUT, the new
+    version, and in case of DELETE, the version that was deleted. All
+    successful GET requests MUST return an 'Expires: 0' header. PUT and
+    DELETE requests MAY have an 'If-Match' request header [COND], and
+    MUST fail with a 412 response code if that doesn't match the
+    document's current version.
+
+
+
+de Jong                                                         [Page 7]
+

+Internet-Draft              remoteStorage                  December 2014
+
+
+    GET requests MAY have a comma-separated list of revisions in an
+    'If-None-Match' header [COND], and SHOULD be responded to with a 304
+    response if that list includes the document or folder's current
+    version. A PUT request MAY have an 'If-None-Match: *' header [COND],
+    in which case it MUST fail with a 412 response code if the document
+    already exists.
+
+    In all 'ETag', 'If-Match' and 'If-None-Match' headers, revision
+    strings should appear inside double quotes (").
+
+    A provider MAY offer version rollback functionality to its users,
+    but this specification does not define the user interface for that.
+
+7. CORS headers
+
+    All responses MUST carry CORS headers [CORS]. The server MUST also
+    reply to OPTIONS requests as per CORS. For GET requests, a wildcard
+    origin MAY be returned, but for PUT and DELETE requests, the
+    response MUST echo back the Origin header sent by the client.
+
+8. Session description
+
+    The information that a client needs to receive in order to be able
+    to connect to a server SHOULD reach the client as described in the
+    'bearer token issuance' sections below. It consists of:
+
+       * <storage_root>, consisting of 'https://' followed by a server
+         host, and optionally a server port and a path prefix as per
+         [IRI]. Examples:
+         * 'https://example.com' (host only)
+         * 'https://example.com:8080' (host and port)
+         * 'https://example.com/path/to/storage' (host, port and
+           path prefix; note there is no trailing slash)
+       * <access_token> as per [OAUTH]. The token SHOULD be hard to
+         guess and SHOULD NOT be reused from one client to another. It
+         can however be reused in subsequent interactions with the same
+         client, as long as that client is still trusted. Example:
+         * 'ofb24f1ac3973e70j6vts19qr9v2eei'
+       * <storage_api>, always 'draft-dejong-remotestorage-04' for this
+         alternative version of the specification.
+
+    The client can make its requests using https with CORS and bearer
+    tokens, to the URL that is the concatenation of <storage_root> with
+
+
+de Jong                                                         [Page 8]
+

+Internet-Draft              remoteStorage                  December 2014
+
+
+    '/' plus one or more <folder> '/' strings indicating a path in the
+    folder tree, followed by zero or one <document> strings, indicating
+    a document. For example, if <storage_root> is
+    "https://storage.example.com/bob", then to retrieve the folder
+    contents of the /public/documents/ folder, or to retrieve a
+    'draft.txt' document from that folder, the client would make
+    requests to, respectively:
+
+    * https://storage.example.com/bob/public/documents/
+    * https://storage.example.com/bob/public/documents/draft.txt
+
+9. Bearer tokens and access control
+
+    A bearer token represents one or more access scopes. These access
+    scopes are represented as strings of the form <module> <level>,
+    where the <module> string SHOULD be lower-case alphanumerical, other
+    than the reserved word 'public', and <level> can be ':r' or ':rw'.
+    The access the bearer token gives is the sum of its access scopes,
+    with each access scope representing the following permissions:
+
+    '*:rw') any request,
+
+    '*:r') any GET or HEAD request,
+
+    <module> ':rw') any requests to paths that start with
+                    '/' <module> '/' or '/public/' <module> '/',
+
+    <module> ':r') any GET or HEAD requests to paths that start with
+                   '/' <module> '/' or '/public/' <module> '/',
+
+    As a special exceptions, GET requests to a document (but not a
+    folder) whose path starts with '/public/' are always allowed. They,
+    as well as OPTIONS requests, can be made without a bearer token.
+    Unless [KERBEROS] is used (see section 10 below), all other requests
+    SHOULD present a bearer token with sufficient access scope, using a
+    header of the following form (no double quotes here):
+
+       Authorization: Bearer <access_token>
+
+    In addition, providing the access token via a HTTP query parameter
+    for GET requests MAY be supported by the server, although its use
+    is not recommended, due to its security deficiencies; see [BEARER,
+    section 2.3].
+
+
+de Jong                                                         [Page 9]
+

+Internet-Draft              remoteStorage                  December 2014
+
+
+
+10. Application-first bearer token issuance
+
+    To make a remoteStorage server available as 'the remoteStorage of
+    <account> at <host>', exactly one link of the following format
+    SHOULD be added to the WebFinger record [WEBFINGER] of <account> at
+    <host>:
+
+    {
+      "href": <storage_root>,
+      "rel": "remotestorage",
+      "properties": {
+        "http://remotestorage.io/spec/version": <storage_api>,
+        "http://tools.ietf.org/html/rfc6749#section-4.2": <auth-dialog>,
+        ... : ... ,
+      }
+    }
+
+    Here <storage_root> and <storage_api> are as per "Session
+    description" above, and <auth-dialog> SHOULD be either null or a
+    URL where an OAuth 2.0 implicit-grant flow dialog [OAUTH] is
+    presented.
+
+    If <auth-dialog> is a URL, the user can supply their credentials
+    for accessing the account (how, is out of scope), and allow or
+    reject a request by the connecting application to obtain a bearer
+    token for a certain list of access scopes. Note that an account
+    will often belong to just one human user, but may also belong to a
+    group of multiple users (the remoteStorage of <group> at <host>).
+
+    If <auth-dialog> is null, the client will not have a way to obtain
+    an access token, and SHOULD send all requests without Authorization
+    header, and rely on Kerberos [KERBEROS] instead for requests that
+    would normally be sent with a bearer token, but servers SHOULD NOT
+    impose any such access barriers for resources that would normally
+    not require an access token.
+
+    The '...' ellipses indicate that more properties may be present.
+    Non-breaking examples that have been proposed so far, include a
+    "http://tools.ietf.org/html/rfc6750#section-2.3" property, set to
+    the string value "true" if the server supports passing the bearer
+    token in the URI query parameter as per section 2.3 of [BEARER],
+    instead of in the request header.
+
+
+de Jong                                                        [Page 10]
+

+Internet-Draft              remoteStorage                  December 2014
+
+
+
+    Another example is "http://tools.ietf.org/html/rfc7233" with a
+    string value of "GET" if Content-Range headers are supported for
+    GET requests as per [RANGE], "PUT" if they are supported for PUT
+    requests, and "GET,PUT" if supported for both.
+
+    Both these proposals are non-breaking extensions, since the client
+    will have a way to work around it if these features are not present
+    (e.g. retrieve the protected resource asynchronously in the first
+    case, or request the entire resource in the second case).
+
+    A "http://remotestorage.io/spec/web-authoring" property has been
+    proposed with a string value of the fully qualified domain name to
+    which web authoring content is published if the server supports web
+    authoring as per [AUTHORING]. Note that this extension is a breaking
+    extension in the sense that it divides users into "haves", whose
+    remoteStorage accounts allow them to author web content, and
+    "have-nots", whose remoteStorage account does not support this
+    functionality.
+
+    The server MAY expire bearer tokens, and MAY require the user to
+    register applications as OAuth clients before first use; if no
+    client registration is required, then the server MAY ignore the
+    client_id parameter in favor of relying on the redirect_uri
+    parameter for client identification.
+
+11. Storage-first bearer token issuance
+
+    The provider MAY also present a dashboard to the user, where they
+    have some way to add open web app manifests [MANIFEST]. Adding a
+    manifest to the dashboard is considered equivalent to clicking
+    'accept' in the dialog of the application-first flow. Removing one
+    is considered equivalent to revoking its access token.
+
+    As an equivalent to OAuth's 'scope' parameter, a 'datastores-access'
+    field SHOULD be present in the root of such an application manifest
+    document, with entries <module> -> '{"access": "readonly"}' for
+    <level> 'r' or '{"access": "readwrite"}' for <level> 'rw', as
+    prescribed in [DATASTORE].
+
+    When the user gestures they want to use a certain application whose
+    manifest is present on the dashboard, the dashboard SHOULD redirect
+    to the application or open it in a new window. To mimic coming back
+
+
+de Jong                                                        [Page 11]
+

+Internet-Draft              remoteStorage                  December 2014
+
+
+    from the OAuth dialog, it MAY add 'access_token' and 'scope'
+    fields to the URL fragment.
+
+    Regardless of whether 'access_token' and 'scope' are specified, it
+    SHOULD add a 'remotestorage' field to the URL fragment, with a
+    value of the form <account> '@' <host>. When the application detects
+    this parameter, it SHOULD resolve the WebFinger record for <account>
+    at <host> and extract the <storage_root> and <storage_api>
+    information.
+
+    If no access_token was given, then the application SHOULD also
+    extract the <auth_endpoint> information from WebFinger, and continue
+    as per application-first bearer token issuance.
+
+    Note that whereas a remoteStorage server SHOULD offer support for
+    the application-first flow with WebFinger and OAuth, it MAY choose
+    not to support the storage-first flow, provided that users will
+    easily remember their <account> '@' <host> WebFinger address at that
+    provider. Applications SHOULD, however, support both flows, which
+    means checking the URL for a 'remotestorage' parameter, but giving
+    the user a way to specify the WebFinger address if there is none.
+
+    If a server provides an application manifest dashboard, then it
+    SHOULD merge the list of applications there with the list of
+    issued access tokens as specified by OAuth into one list. Also,
+    the interface for revoking an access token as specified by OAuth
+    SHOULD coincide with removing an application from the dashboard.
+
+    Servers MAY also provide a way to create access tokens directly from
+    their user interface. Such functionality would be aimed mainly at
+    developers, to manually copy and paste a token into a script or
+    debug tool, thus bypassing the need for an OAuth dance. Clients
+    SHOULD NOT rely on this in production.
+
+12. Example wire transcripts
+
+    The following examples are not normative ("\" indicates a line was
+    wrapped).
+
+12.1. WebFinger
+
+    In application-first, an in-browser application might issue the
+    following request, using XMLHttpRequest and CORS:
+
+
+de Jong                                                        [Page 12]
+

+Internet-Draft              remoteStorage                  December 2014
+
+
+
+         GET /.well-known/webfinger?resource=acct:michiel@michielbdejon\
+g.com HTTP/1.1
+         Host: michielbdejong.com
+
+    and the server's response might look like this:
+
+         HTTP/1.1 200 OK
+         Access-Control-Allow-Origin: *
+         Access-Control-Allow-Methods: GET
+         Access-Control-Allow-Headers: If-Match, If-None-Match
+         Access-Control-Expose-Headers: ETag, Content-Length
+         Content-Type: application/jrd+json
+
+         {
+           "links":[{
+             "href": "https://michielbdejong.com:7678/inbox",
+             "rel": "post-me-anything"
+           }, {
+             "href": "https://michielbdejong.com/me.jpg",
+             "rel": "avatar"
+           }, {
+             "href": "https://3pp.io:4439/storage/michiel",
+             "rel": "remotestorage",
+             "properties": {
+               "http://remotestorage.io/spec/version": "draft-dejong-re\
+motestorage-04",
+               "http://tools.ietf.org/html/rfc6749#section-4.2": "https\
+://3pp.io:4439/oauth/michiel",
+               "http://tools.ietf.org/html/rfc6750#section-2.3": false,
+               "http://tools.ietf.org/html/rfc7233": false,
+               "http://remotestorage.io/spec/web-authoring": false
+             }
+           }]
+         }
+
+12.2. OAuth dialog form
+
+    Once the in-browser application has discovered the server's OAuth
+    end-point, it will typically redirect the user to this URL, in
+    order to obtain a bearer token. Say the application is hosted on
+    https://drinks-unhosted.5apps.com/ and wants read-write access to
+    the account's "myfavoritedrinks" scope:
+
+
+de Jong                                                        [Page 13]
+

+Internet-Draft              remoteStorage                  December 2014
+
+
+
+        GET /oauth/michiel?redirect_uri=https%3A%2F%2Fdrinks-unhosted.5\
+apps.com%2F&scope=myfavoritedrinks%3Arw&client_id=https%3A%2F%2Fdrinks-\
+unhosted.5apps.com&response_type=token HTTP/1.1
+        Host: 3pp.io
+
+    The server's response might look like this (truncated for brevity):
+
+        HTTP/1.1 200 OK
+
+        <!DOCTYPE html>
+        <html lang="en">
+          <head>
+            <title>Allow access?</title>
+        ...
+
+12.3. OAuth dialog form submission
+
+    When the user submits the form, the request would look something
+    like this:
+
+        POST /oauth HTTP/1.1
+        Host: 3pp.io:4439
+        Origin: https://3pp.io:4439
+        Content-Type: application/x-www-form-urlencoded
+        Referer: https://3pp.io:4439/oauth/michiel?redirect_uri=https%3\
+A%2F%2Fdrinks-unhosted.5apps.com%2F&scope=myfavoritedrinks%3Arw&client_\
+id=https%3A%2F%2Fdrinks-unhosted.5apps.com&response_type=token
+
+        client_id=https%3A%2F%2Fdrinks-unhosted.5apps.com&redirect_uri=\
+https%3A%2F%2Fdrinks-unhosted.5apps.com%2F&response_type=token&scope=my\
+favoritedrinks%3Arw&state=&username=michiel&password=something&allow=Al\
+low
+
+    To which the server could respond with a 302 redirect, back to the
+    origin of the requesting application:
+
+        HTTP/1.1 302 Found
+        Location:https://drinks-unhosted.5apps.com/#access_token=j2YnGt\
+XjzzzHNjkd1CJxoQubA1o%3D&token_type=bearer&state=
+
+12.4. OPTIONS preflight
+
+
+
+de Jong                                                        [Page 14]
+

+Internet-Draft              remoteStorage                  December 2014
+
+
+    When an in-browser application makes a cross-origin request which
+    may affect the server-state, the browser will make a preflight
+    request first, with the OPTIONS verb, for instance:
+
+        OPTIONS /storage/michiel/myfavoritedrinks/ HTTP/1.1
+        Host: 3pp.io:4439
+        Access-Control-Request-Method: GET
+        Origin: https://drinks-unhosted.5apps.com
+        Access-Control-Request-Headers: Authorization
+        Referer: https://drinks-unhosted.5apps.com/
+
+    To which the server can for instance respond:
+
+        HTTP/1.1 200 OK
+        Access-Control-Allow-Origin: https://drinks-unhosted.5apps.com
+        Access-Control-Allow-Methods: GET, PUT, DELETE
+        Access-Control-Allow-Headers: Authorization, Content-Length, Co\
+ntent-Type, Origin, X-Requested-With, If-Match, If-None-Match
+
+12.5. Initial PUT
+
+    An initial PUT may contain an 'If-None-Match: *' header, like this:
+
+        PUT /storage/michiel/myfavoritedrinks/test HTTP/1.1
+        Host: 3pp.io:4439
+        Content-Length: 91
+        Origin: https://drinks-unhosted.5apps.com
+        Authorization: Bearer j2YnGtXjzzzHNjkd1CJxoQubA1o=
+        Content-Type: application/json; charset=UTF-8
+        Referer: https://drinks-unhosted.5apps.com/?
+        If-None-Match: *
+
+        {"name":"test","@context":"http://remotestorage.io/spec/modules\
+/myfavoritedrinks/drink"}
+
+    And the server may respond with either a 201 Created or a 200 OK
+    status:
+
+        HTTP/1.1 201 Created
+        Access-Control-Allow-Origin: https://drinks-unhosted.5apps.com
+        ETag: "1382694045000"
+
+12.6. Subsequent PUT
+
+
+de Jong                                                        [Page 15]
+

+Internet-Draft              remoteStorage                  December 2014
+
+
+
+    A subsequent PUT may contain an 'If-Match' header referring to the
+    ETag previously returned, like this:
+
+        PUT /storage/michiel/myfavoritedrinks/test HTTP/1.1
+        Host: 3pp.io:4439
+        Content-Length: 91
+        Origin: https://drinks-unhosted.5apps.com
+        Authorization: Bearer j2YnGtXjzzzHNjkd1CJxoQubA1o=
+        Content-Type: application/json; charset=UTF-8
+        Referer: https://drinks-unhosted.5apps.com/?
+        If-Match: "1382694045000"
+
+        {"name":"test", "updated":true, "@context":"http://remotestorag\
+e.io/spec/modules/myfavoritedrinks/drink"}
+
+    And the server may respond with a 412 Conflict or a 200 OK status:
+
+        HTTP/1.1 200 OK
+        Access-Control-Allow-Origin: https://drinks-unhosted.5apps.com
+        ETag: "1382694048000"
+
+12.7. GET
+
+    A GET request would also include the bearer token, and optionally
+    an If-None-Match header:
+
+        GET /storage/michiel/myfavoritedrinks/test HTTP/1.1
+        Host: 3pp.io:4439
+        Origin: https://drinks-unhosted.5apps.com
+        Authorization: Bearer j2YnGtXjzzzHNjkd1CJxoQubA1o=
+        Referer: https://drinks-unhosted.5apps.com/?
+        If-None-Match: "1382694045000", "1382694048000"
+
+    And the server may respond with a 304 Not Modified status:
+
+        HTTP/1.1 304 Not Modified
+        Access-Control-Allow-Origin: https://drinks-unhosted.5apps.com
+        ETag: "1382694048000"
+
+    Or a 200 OK status, plus a response body:
+
+        HTTP/1.1 200 OK
+
+
+de Jong                                                        [Page 16]
+

+Internet-Draft              remoteStorage                  December 2014
+
+
+        Access-Control-Allow-Origin: https://drinks-unhosted.5apps.com
+        Content-Type: application/json; charset=UTF-8
+        Content-Length: 106
+        ETag: "1382694048000"
+        Expires: 0
+
+        {"name":"test", "updated":true, "@context":"http://remotestora\
+ge.io/spec/modules/myfavoritedrinks/drink"}
+
+    If the GET URL would have been "/storage/michiel/myfavoritedrinks/",
+    a 200 OK response would have a folder description as the response
+    body:
+
+        HTTP/1.1 200 OK
+        Access-Control-Allow-Origin: https://drinks-unhosted.5apps.com
+        Content-Type: application/ld+json
+        Content-Length: 171
+        ETag: "1382694048000"
+        Expires: 0
+
+        {"@context":"http://remotestorage.io/spec/folder-version","ite\
+ms":{"test":{"ETag":"1382694048000","Content-Type":"application/json; \
+charset=UTF-8","Content-Length":106}}}
+
+    If the GET URL would have been a non-existing document like
+    "/storage/michiel/myfavoritedrinks/x", the response would have a 404
+    Not Found status, and no ETag header:
+
+        HTTP/1.1 404 Not Found
+        Access-Control-Allow-Origin: https://drinks-unhosted.5apps.com
+
+12.8. DELETE
+
+    A DELETE request may look like this:
+
+        DELETE /storage/michiel/myfavoritedrinks/test HTTP/1.1
+        Host: 3pp.io:4439
+        Origin: https://drinks-unhosted.5apps.com
+        Authorization: Bearer j2YnGtXjzzzHNjkd1CJxoQubA1o=
+        Content-Type: application/json; charset=UTF-8
+        Referer: https://drinks-unhosted.5apps.com/?
+        If-Match: "1382694045000"
+
+
+
+de Jong                                                        [Page 17]
+

+Internet-Draft              remoteStorage                  December 2014
+
+
+    And the server may respond with a 412 Conflict or a 200 OK status:
+
+        HTTP/1.1 412 Conflict
+        Access-Control-Allow-Origin: https://drinks-unhosted.5apps.com
+        ETag: "1382694048000"
+
+13. Distributed versioning
+
+    This section is non-normative, and is intended to explain some of
+    the design choices concerning ETags and folder listings. At the
+    same time it will hopefully help readers who intend to develop an
+    application that uses remoteStorage as its per-user data storage.
+    When multiple clients have read/write access to the same document,
+    versioning conflicts may occur. For instance, client A may make
+    a PUT request that changes the document from version 1 to version
+    2, after which client B may make a PUT request attempting to change
+    the same document from version 1 to version 3.
+
+    In this case, client B can add an 'If-Match: "1"' header, which
+    would trigger a 412 Conflict response code, since the current
+    version ("2") does not match the version required as a condition by
+    the header If-Match header ("1").
+
+    Client B is now aware of the conflict, and may consult the user,
+    saying the update to version 3 failed. The user may then choose,
+    through the user interface of client B, whether version 2 or
+    version 3 should be kept, or maybe the document should be reverted
+    on the server to version 1, or a merged version 4 is needed. Client
+    B may then make a request that puts the document to the version the
+    user wishes; this time setting an 'If-Match: "2"' header instead.
+
+    Both client A and client B would periodically poll the root
+    folder of each scope they have access to, to see if the version
+    of the root folder changed. If it did, then one of the versions
+    listed in there will necessarily have changed, and the client can
+    make a GET request to that child folder or document, to obtain
+    its latest version.
+
+    Because an update in a document will result in a version change of
+    its containing folder, and that change will propagate all the way
+    to the root folder, it is not necessary to poll each document for
+    changes individually.
+
+
+
+de Jong                                                        [Page 18]
+

+Internet-Draft              remoteStorage                  December 2014
+
+
+    As an example, the root folder may contain 10 directories,
+    each of which contain 10 directories, which each contain 10
+    documents, so their paths would be for instance '/0/0/1', '/0/0/2',
+    etcetera. Then one GET request to the root folder '/' will be
+    enough to know if any of these 1000 documents has changed.
+
+    Say document '/7/9/2' has changed; then the GET request to '/' will
+    come back with a different ETag, and entry '7/' will have a
+    different value in its JSON content. The client could then request
+    '/7/', '/7/9/', and '/7/9/2' to narrow down the one document that
+    caused the root folder's ETag to change.
+
+    Note that the remoteStorage server does not get involved in the
+    conflict resolution. It keeps the canonical current version at all
+    times, and allows clients to make conditional GET and PUT requests,
+    but it is up to whichever client discovers a given version
+    conflict, to resolve it.
+
+14. Security Considerations
+
+    To prevent man-in-the-middle attacks, the use of https instead of
+    http is important for both the interface itself and all end-points
+    involved in WebFinger, OAuth, and (if present) the storage-first
+    application launch dashboard.
+
+    A malicious party could link to an application, but specifying a
+    remoteStorage account address that it controls, thus tricking the
+    user into using a trusted application to send sensitive data to the
+    wrong remoteStorage server. To mitigate this, applications SHOULD
+    clearly display to which remoteStorage server they are sending the
+    user's data.
+
+    Applications could request scopes that the user did not intend to
+    give access to. The user SHOULD always be prompted to carefully
+    review which scopes an application is requesting.
+
+    An application may upload malicious html pages and then trick the
+    user into visiting them, or upload malicious client-side scripts,
+    that take advantage of being hosted on the user's domain name. The
+    origin on which the remoteStorage server has its interface SHOULD
+    therefore NOT be used for anything else, and the user SHOULD be
+    warned not to visit any web pages on that origin. In particular, the
+    OAuth dialog and launch dashboard or token revokation interface
+
+
+de Jong                                                        [Page 19]
+

+Internet-Draft              remoteStorage                  December 2014
+
+
+    SHOULD be on a different origin than the remoteStorage interface.
+
+    Where the use of bearer tokens is impractical, a user may choose to
+    store documents on hard-to-guess URLs whose path after
+    <storage_root> starts with '/public/', while sharing this URL only
+    with the intended audience. That way, only parties who know the
+    document's hard-to-guess URL, can access it. The server SHOULD
+    therefore make an effort to detect and stop brute-force attacks that
+    attempt to guess the location of such documents.
+
+    The server SHOULD also detect and stop denial-of-service attacks
+    that aim to overwhelm its interface with too much traffic.
+
+15. IANA Considerations
+
+    This document registers the 'remotestorage' link relation, as well
+    as the following WebFinger properties:
+      * "http://remotestorage.io/spec/version"
+      * "http://tools.ietf.org/html/rfc6749#section-4.2"
+      * "http://tools.ietf.org/html/rfc6750#section-2.3"
+      * "http://tools.ietf.org/html/rfc7233"
+      * "http://remotestorage.io/spec/web-authoring"
+
+16. Acknowledgements
+
+    The authors would like to thank everybody who contributed to the
+    development of this protocol, including Kenny Bentley, Javier Diaz,
+    Daniel Groeber, Bjarni Runar, Jan Wildeboer, Charles Schultz, Peter
+    Svensson, Valer Mischenko, Michiel Leenaars, Jan-Christoph
+    Borchardt, Garret Alfert, Sebastian Kippe, Max Wiehle, Melvin
+    Carvalho, Martin Stadler, Geoffroy Couprie, Niklas Cathor, Marco
+    Stahl, James Coglan, Ken Eucker, Daniel Brolund, elf Pavlik, Nick
+    Jennings, Markus Sabadello, Steven te Brinke, Matthias Treydte,
+    Rick van Rein, Mark Nottingham, Julian Reschke, and Markus
+    Lanthaler, among many others.
+
+17. References
+
+17.1. Normative References
+
+    [WORDS]
+        Bradner, S., "Key words for use in RFCs to Indicate Requirement
+        Levels", BCP 14, RFC 2119, March 1997.
+
+
+de Jong                                                        [Page 20]
+

+Internet-Draft              remoteStorage                  December 2014
+
+
+
+    [IRI]
+        Duerst, M., "Internationalized Resource Identifiers (IRIs)",
+        RFC 3987, January 2005.
+
+    [WEBFINGER]
+        Jones, P., Salguerio, G., Jones, M, and Smarr, J.,
+        "WebFinger", RFC7033, September 2013.
+
+    [OAUTH]
+        "Section 4.2: Implicit Grant", in: Hardt, D. (ed), "The OAuth
+        2.0 Authorization Framework", RFC6749, October 2012.
+
+17.2. Informative References
+
+    [HTTPS]
+        Rescorla, E., "HTTP Over TLS", RFC2818, May 2000.
+
+    [HTTP]
+        Fielding et al., "Hypertext Transfer Protocol (HTTP/1.1):
+        Semantics and Content", RFC7231, June 2014.
+
+    [COND]
+        Fielding et al., "Hypertext Transfer Protocol (HTTP/1.1):
+        Conditional Requests", RFC7232, June 2014.
+
+    [RANGE]
+        Fielding et al., "Hypertext Transfer Protocol (HTTP/1.1):
+        Conditional Requests", RFC7233, June 2014.
+
+    [SPDY]
+        Mark Belshe, Roberto Peon, "SPDY Protocol - Draft 3.1", http://
+        www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1,
+        September 2013.
+
+    [JSON-LD]
+        M. Sporny, G. Kellogg, M. Lanthaler, "JSON-LD 1.0", W3C
+        Proposed Recommendation,
+        http://www.w3.org/TR/2014/REC-json-ld-20140116/, January 2014.
+
+    [CORS]
+        van Kesteren, Anne (ed), "Cross-Origin Resource Sharing --
+        W3C Candidate Recommendation 29 January 2013",
+
+
+de Jong                                                        [Page 21]
+

+Internet-Draft              remoteStorage                  December 2014
+
+
+        http://www.w3.org/TR/cors/, January 2013.
+
+    [MANIFEST]
+        Mozilla Developer Network (ed), "App manifest -- Revision
+        330541", https://developer.mozilla.org/en-
+        US/Apps/Build/Manifest$revision/566677, April 2014.
+
+    [DATASTORE]
+        "WebAPI/DataStore", MozillaWiki, retrieved May 2014.
+        https://wiki.mozilla.org/WebAPI/DataStore#Manifest
+
+    [KERBEROS]
+        C. Neuman et al., "The Kerberos Network Authentication Service
+        (V5)", RFC4120, July 2005.
+
+    [BEARER]
+        M. Jones, D. Hardt, "The OAuth 2.0 Authorization Framework:
+        Bearer Token Usage", RFC6750, October 2012.
+
+    [AUTHORING]
+        "Using remoteStorage for web authoring", reSite wiki, retrieved
+        September 2014. https://github.com/michielbdejong/resite/wiki
+        /Using-remoteStorage-for-web-authoring
+
+18. Authors' addresses
+
+    Michiel B. de Jong
+    IndieHosters
+
+    Email: michiel@michielbdejong.com
+
+
+    F. Kooman
+    (independent)
+
+    Email: fkooman@tuxed.net
+
+
+
+
+
+
+
+
+
+de Jong                                                        [Page 22]
+
+

+Html markup produced by rfcmarkup 1.111, available from +https://tools.ietf.org/tools/rfcmarkup/ + + -- cgit v1.2.3