%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Browser Binding
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\chapter{Browser Binding}
\label{browser:browserbinding}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Overview
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Overview}

The CMIS Browser Binding is based upon JSON (Java Script Object Notation, \hyperref[intro:rfc4627]{[RFC4627]}) and patterns used in Web applications. This binding is specifically designed to support applications running in a web browser but is not restricted to them. It is based on technologies that developers who build such applications already understand, including HTML, HTML Forms, JavaScript and JSON (Java Script Object Notation). Importantly, it does not require a JavaScript library, but rather takes advantage of capabilities already built into modern browsers. 

While this binding is optimized for use in browser applications, it can also serve as an easy to use binding in other application models. 


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Common Service Elements
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Common Service Elements}


\subsection{Protocol}

HTTP MUST be used as the protocol for service requests. HTTP GET MUST be used for reading content and HTTP POST MUST be used for creating, updating and deleting content. Using just those two HTTP verbs makes it possible to develop applications that rely on built-in browser capabilities (e.g. HTML Forms) and typical server configurations. 

The use of HTTPS is RECOMMENDED for repositories that contain non-public data.


\subsection{Data Representation}

Browser applications are typically written in JavaScript. A popular lightweight data representation format amongst JavaScript developers is JavaScript Object Notation (JSON) as described in \hyperref[intro:rfc4627]{[RFC4627]}. JSON MUST be used to represent the various CMIS objects described by the data model.


\subsection{Schema}
\label{browser:schema}

This specification provides a formal definition of the CMIS JSON elements. The formal definition is short and precise and allows implementations to validate CMIS JSON at runtime. 

Since there is not yet a JSON schema language approved by a standards body, this specification uses a schema language called Orderly that is introduced by Lloyd Hilaiel on \url{http://orderly-json.org/}. Since the definition of Orderly on \url{http://orderly-json.org/} may proceed independently of this specification, and because we may need to extend Orderly to define some elements of CMIS, we provide a description of Orderly in appendix \ref{orderly}~\nameref{orderly} of this document. 


\subsection{Mapping Schema Elements to JSON}

JSON only defines a few types, including Object, String, Number, Boolean, Null and Array. Not all types used in the CMIS schema have direct JSON equivalents. The following table describes the mapping between CMIS and JSON types. 

\begin{tabular}{p{1.3in}p{4.8in}}
	\textbf{CMIS} & \textbf{JSON}\\
	string & string\\
	boolean & boolean\\
	decimal & number\\
	integer & number\\
	datetime & number\newline (Dates are represented in milliseconds from 1970/01/01 00:00:00 UTC with a day containing 86,400,000 milliseconds. Negative numbers represent dates before 1970/01/01 00:00:00 UTC.)\\
	uri & string\\
	id & string\\
	html & string\\
\end{tabular}


\subsection{URL Patterns}

The URLs used by the Browser Binding are meant to be predictable in order to simplify client development. The URL patterns allow objects to be referenced by either object Id or path. Section \ref{browser:urls}~\nameref{browser:urls} provides the details of how clients can construct these URLs.


\subsection{Multipart Forms}

Browser applications typically use HTTP multipart forms as described in \hyperref[intro:rfc2388]{[RFC2388]} to create and update content. This is especially useful for updating file content with the addition of the FILE attribute in \hyperref[intro:rfc1867]{[RFC1867]}. In this binding, HTTP POST of \texttt{multipart/form-data} MUST be used to update content streams.


\subsection{Properties in a "value not set" state}

The JSON value "null" MUST be used by the server when returning values that have not been set.


\subsection{Callback}
\label{browser:callback}

Modern browsers restrict a JavaScript function from making HTTP calls to servers other than the one on which the function originated. This set of restrictions is called the "same-origin policy" (see \hyperref[intro:sameoriginpolicy]{[SameOriginPolicy]}). A CMIS client web application and the CMIS repositories it uses may often be deployed to different servers. This specification allows JavaScript clients to access repositories on other servers, within the constraints of the same-origin policy, by using the "JSON with Padding" (JSONP) pattern.

This binding introduces a parameter called \texttt{callback} to allow CMIS clients to use this pattern. 

The \texttt{callback} MAY be included by clients on read operations defined by this protocol that answer a JSON object. The server MUST respond to valid read requests containing this token by answering the token, followed by an open parenthesis, followed by the JSON object returned, followed by a close parenthesis. If the parameter is included in a request, the server MUST validate that its value is not empty but the server MUST NOT do any additional validation of the token, such as, for example, assuring it conforms to JavaScript function naming conventions. If the parameter value is empty, or if the parameter is used on a service for which it is not allowed, then the \cmisexceptionlink{invalidArgument} exception MUST be used to signal the error.

Example:
\begin{lstlisting}[language=CMISJSONHTTP]
showRepositoryInfo (
{
    "A1":{
        "repositoryId":"A1",        
        "repositoryDescription":"A Repository",
        "vendorName":"OASIS",
        "productName":"Repository Server",
        "productVersion":"1.0",
        "cmisVersionSupported":"1.1",
        "changesIncomplete":true,
        "rootFolderUrl":"http:\/\/example.com\/cmis\/repository\/123\/root",
        "latestChangeLogToken":"0",
        "rootFolderId":"100",
        "repositoryName":"Apache Chemistry OpenCMIS InMemory Repository",
        "repositoryUrl":"http:\/\/example.com\/cmis\/repository\/123",
        "changesOnType":[].
        "capabilities":{
            "capabilityContentStreamUpdatability":"anytime",
            "capabilityPWCSearchable":false,
            "capabilityQuery":"bothcombined",
            "capabilityRenditions":"none",
            "capabilityACL":"none",
            "capabilityGetFolderTree":true,
            "capabilityGetDescendants":true,
            "capabilityVersionSpecificFiling":false,
            "capabilityUnfiling":true,
            "capabilityJoin":"none",
            "capabilityAllVersionsSearchable":false,
            "capabilityMultifiling":true,
            "capabilityChanges":"none",
            "capabilityPWCUpdatable":true
        },
    }
}
) 
\end{lstlisting}


\subsection{Authentication}
\label{browser:authentication}

This specification RECOMMENDS the authentication mechanisms described in the following sections. Repositories MAY provide more, other or no authentication mechanisms.

Furthermore, this specification RECOMMENDS the use of HTTPS  (see \hyperref[intro:rfc2818]{[RFC2818]}) to protect credentials and data.


\subsubsection{Basic Authentication for Non-Browser Clients}

Repositories SHOULD accept HTTP Basic Authentication (see \hyperref[intro:rfc2617]{[RFC2617]} Section 2). 

If the provided credentials are incorrect or unknown or entirely missing, a repository MAY return the HTTP status code 403 (Forbidden) instead of the HTTP status code 401 (Unauthorized). This prevents web browsers from providing a login dialog and subsequently remembering the credentials. This in turn can prevent a form of cross-site request forgery (CSRF).


\subsubsection{Authentication with Tokens for Browser Clients}
\label{browser:authenticationtoken}

The authentication mechanism described in this section addresses the following scenario:

A web application is hosted on one domain; the CMIS browser binding interface is served from another domain. There is no proxy process on the server that hosts the web application. That is, all communication between the application and the repository has to happen in the web browser via JavaScript. The "same-origin policy" (see \hyperref[intro:sameoriginpolicy]{[SameOriginPolicy]}) enforced by the web browser prohibits a direct and secure two-way communication between the application and the repository.

To access the repository, a user has to authenticate and has to authorize the application (and only this application, not all scripts in the web browser) to make CMIS calls.


\paragraph{JSONP and Form Requests}

Cross-domain requests should use JSONP and callbacks (see section \ref{browser:callback}~\nameref{browser:callback}) for GET requests and should use HTML forms for POST requests.

A token SHOULD be added to each request to prevent cross-site request forgery (CSRF) attacks. For this purpose, a parameter \texttt{token} MUST be added to the parameters of a GET request and a control \texttt{token} MUST be added to the controls of a HTML form. 

The repository SHOULD return a \cmisexceptionlink{permissionDenied} error if the client sends an invalid token.

If the client sends any other form of authentication (Basic Authentication, OAuth, etc.), the token MAY be omitted. It is RECOMMENDED for web applications always to provide a token, even if another form of authentication is in place.


\paragraph{Login and Tokens}

Tokens are obtained from the repository in the following way.

The repository provides a JavaScript script that the web application includes into its HTML page via the HTML \texttt{<script>} tag.

This script provides four functions:

\begin{description}
	\item[cmisServiceURL()] This function returns the Service URL. See section \ref{browser:serviceurl}~\nameref{browser:serviceurl}.
	\item[cmisLogin(callback)] This function triggers the login process. The web application MUST call this function before it calls any other functions.
How the login works is repository specific. A repository MAY replace the application page in the web browser with a login page and later return back to the application page.

The function takes a callback function. It is called when the login process has been completed. The callback function MUST accept a boolean parameter. The repository MUST provide TRUE if the login process was successful and FALSE if it was not successful. 
	\item[cmisLogout(callback)] This function triggers the logout process. How the logout works is repository specific. After a successful logout, \texttt{cmisNextToken()} MUST NOT return a valid token. The application MAY call \texttt{cmisLogin()} again to trigger a new login.

The function takes a callback function. It is called when the logout process has been completed. The callback function MUST accept a boolean parameter. The repository MUST provide TRUE if the logout process was successful and FALSE if it was not successful.
	\item[cmisNextToken(callback)] This function calls the provided callback function with a new token. How this token is generated and obtained is repository specific. Whether the repository returns unique tokens or the same token for a user or for all users is repository specific. The repository SHOULD signal an invalid state (e.g. no logged in user) with an empty token (empty string).
\end{description}


The flow in a web application could looks like this:

\begin{lstlisting}
<script src="http://cmis.example.com/cmis.js"/>
<script>
  cmisLogin(function(success) {
    if (success) {
      displayRootFolder();
    } else {
      showLoginErrorMessage();
    }
  });


  function displayRootFolder() {
    cmisNextToken(function(token) {
      loadChildren('/', ..., token);
    });
  }

  ...

</script>
\end{lstlisting}


\subsection{Error Handling and Return Codes}

HTTP status codes MUST be used to indicate success or failure of an operation. Please see the HTTP specification for more information on the HTTP status codes. These are provided as guidance from the HTTP specification. If any conflict arises, the HTTP specification is authoritative.

\begin{tabular}{ll}
	\textbf{CMIS Services Exception} & \textbf{HTTP Status Code}\\
	\textit{General Exceptions} &\\
	\cmisexceptionlink{invalidArgument} & 400\\
	\cmisexceptionlink{notSupported} & 405\\
	\cmisexceptionlink{objectNotFound} & 404\\
	\cmisexceptionlink{permissionDenied} & 403\\
	\cmisexceptionlink{runtime} & 500\\
	\textit{Specific Exceptions} &\\
	\cmisexceptionlink{constraint} & 409\\
	\cmisexceptionlink{contentAlreadyExists} & 409\\
	\cmisexceptionlink{filterNotValid} & 400\\
	\cmisexceptionlink{nameConstraintViolation} & 409\\
	\cmisexceptionlink{storage} & 500\\
	\cmisexceptionlink{streamNotSupported} & 403\\
	\cmisexceptionlink{updateConflict} & 409\\
	\cmisexceptionlink{versioning} & 409\\
\end{tabular}


\hfill\\

This binding also introduces an object to return additional information about the response. CMIS repositories SHOULD include this object in responses. When present, the object MUST include the following JSON properties.


\begin{description}
	\item[string \texttt{exception}] A string containing one of the CMIS services exceptions describe in section \ref{dm:exceptions}~\nameref{dm:exceptions}.
	\item[string \texttt{message}] A string containing a message that provides more information about what caused the exception.
\end{description}

Example: 

\begin{lstlisting}
GET /cmis/repository/123/myFolder?maxItems=abc HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0


HTTP/1.1 400 Bad Request
Content-Type: application/json
Content-Length: xxxx

{
  "exception": "invalidArgument",
  "message": "The parameter 'maxItems' is not valid."
}
\end{lstlisting}


If the query parameter \texttt{suppressResponseCodes=true} is set, the repository MUST always return the HTTP status code 200.

Example: 

\begin{lstlisting}
GET /cmis/repository/123/myFolder?maxItems=abc&suppressResponseCodes=true HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0


HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: xxxx

{
  "exception": "invalidArgument",
  "message": "The parameter 'maxItems' is not valid."
}
\end{lstlisting}


\subsection{Succinct Representation of Properties}
\label{browser:succinct}

The default representation of properties may contain redundant information such as the display name, property type, cardinality, etc. to simplify JavaScript code in a web application. This extra data is superfluous for clients that cache type and property definitions. In order to reduce the message sizes, the Browser Binding supports a parameter, which advises the repository to send a compact form of the properties.

\begin{sloppypar}
A client MAY add the query parameter \texttt{succinct} (HTTP GET) or the control \texttt{succinct} (HTTP POST) with the value "true" to a request. If this is set, the repository MUST return properties in a succinct format. That is, whenever the repository renders an object or a query result, it MUST populate the \texttt{succinctProperties} value and MUST NOT populate the \texttt{properties} value. See the schema elements \texttt{http://docs.oasis-open.org/ns/cmis/browser/201103/object} and \texttt{http://docs.oasis-open.org/ns/cmis/browser/201103/queryResult}.
\end{sloppypar}

Example of a folder representation with \texttt{succinct} flag set to "true":

\begin{lstlisting}[language=CMISJSONHTTP]
{
  "succinctProperties" : {
    "cmis:allowedChildObjectTypeIds" : ["*"],
    "cmis:objectTypeId" : "cmis:folder",
    "cmis:lastModifiedBy" : "unknown",
    "cmis:path" : "\/My_Folder-0-0\/My_Folder-1-0",
    "cmis:name" : "My_Folder-1-0",
    "cmis:createdBy" : "unknown",
    "cmis:objectId" : "102",
    "cmis:creationDate" : 1342160009207,
    "cmis:changeToken" : "1342160009207",
    "cmis:baseTypeId" : "cmis:folder",
    "cmis:lastModificationDate" : 1342160009207,
    "cmis:parentId" : "101"
  }
}
\end{lstlisting}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% URLs
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{URLs}
\label{browser:urls}


\subsection{Service URL}
\label{browser:serviceurl}

The document returned by the Service URL provides the repository information for all available repositories. How the client will get the Service URL is repository specific.   

The Service URL MUST return the repository infos of all available repositories (see section \ref{dm:repository}~\nameref{dm:repository}). Each repository info MUST contain two additional properties:

\begin{itemize}
	\item The \nameref{browser:repositoryurl} (repository info property: \texttt{repositoryUrl}) 
	\item The \nameref{browser:rootfolderurl} (repository info property: \texttt{rootFolderUrl}) 
\end{itemize}


\subsection{Repository URL}
\label{browser:repositoryurl}

The Repository URL provides access to data that is independent of the folder hierarchy such as type definitions, query and content changes. It can be obtained using the \cmisservicelink{getRepositories} or \cmisservicelink{getRepositoryInfo} services.


\subsection{Root Folder URL}
\label{browser:rootfolderurl}

The Root Folder URL is used to build Object URLs (see section \ref{browser:objecturls}~\nameref{browser:objecturls}).  It can be obtained using the \cmisservicelink{getRepositories} or \cmisservicelink{getRepositoryInfo} services.


\subsection{Object URLs}
\label{browser:objecturls}

An object is either identified by a parameter \texttt{objectId} added to the \nameref{browser:rootfolderurl} or by a path that is appended to the \nameref{browser:rootfolderurl}. If the parameter \texttt{objectId} is set, it takes precedence over the path.

The two forms of an Object URL are:
\begin{itemize}
	\item \texttt{<root>}?objectId=\texttt{<objectId>}\\
		where \texttt{<root>} is the Root Folder URL and \texttt{<objectId>} is a CMIS object id.
	\item \texttt{<root>}/\texttt{<path>}\\
		where \texttt{<root>} is the Root Folder URL and \texttt{<path>} is an absolute CMIS path to an object. 
\end{itemize}


Examples:

\begin{sloppypar}
\begin{itemize}
	\item If the Root Folder URL is \path{http://example.com/cmis/repository/123} and the object id is \texttt{1a2b-3c4d-5e6f} then the Object URL is:\\
		\path{http://example.com/cmis/repository/123?objectId=1a2b-3c4d-5e6f}
	\item If the Root Folder URL is \path{http://example.com/cmis/repository/123} and the object path is \texttt{/myFolder/myDocument} then the Object URL is:\\
		\path{http://example.com/cmis/repository/123/myFolder/myDocument}
\end{itemize}
\end{sloppypar}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Services
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Services}
\label{browser:services}

Read operations use HTTP GET.  The particular data that is returned by a read operation is determined by the query parameter \texttt{cmisselector}.

If the \texttt{cmisselector} parameter is absent, the following default values are used: 

\begin{tabular}{p{1.3in}p{4.8in}}
	\textbf{Base Type} & \textbf{cmisselector}\\
	cmis:document & \texttt{content}\\
	cmis:folder & \texttt{children}\\
	cmis:relationship & \texttt{object}\\
	cmis:policy & \texttt{object}\\
	cmis:item & \texttt{object}
\end{tabular}

The value of the \texttt{cmisselector} parameter is case insensitive.

All operations that create, modify, or delete objects or change the state of the repository in any way use HTTP POST. Since this binding is optimized for use in browser applications, the format of the transferred data is aligned to the capabilities of HTML forms and described in this specification in HTML terms. See section \ref{browser:htmlforms}~\nameref{browser:htmlforms} for a description of how HTML forms are used for CMIS services.

All operations that return the HTTP status code 201 SHOULD also return a HTTP Location header.

The Schema Elements mentioned in the following sections refer to the CMIS Orderly schema. See also section \ref{browser:schema}~\nameref{browser:schema}.


\subsection{Service URL}

\cmisbrowserGET{getRepositories}
{}
{
\begin{itemize*}
	\item token
\end{itemize*}
}
{JSON representation of the repository infos of all repositories}
{http://docs.oasis-open.org/ns/cmis/browser/201103/repositories}

The Service URL has no selector.

\cmisexample{browser/getRepositoryInfos}


\subsection{Repository URL}

\cmisbrowserGET{getRepositoryInfo}
{repositoryInfo}
{
\begin{itemize*}
	\item token
\end{itemize*}
}
{JSON representation of the repository info of the specified repository}
{http://docs.oasis-open.org/ns/cmis/browser/201103/repositories}

\cmisexample{browser/getRepositoryInfo}


\cmisbrowserGET{getTypeChildren}
{typeChildren}
{
\begin{itemize*}
	\item typeId
	\item includePropertyDefinitions
	\item maxItems
	\item skipCount
	\item token
\end{itemize*}
}
{JSON representation of the types that are immediate children of the specified typeId, or the base types if no typeId is provided}
{http://docs.oasis-open.org/ns/cmis/browser/201103/typeList}

\cmisexample{browser/getTypeChildren}


\cmisbrowserGET{getTypeDescendants}
{typeDescendants}
{
\begin{itemize*}
	\item typeId
	\item depth
	\item includePropertyDefinitions
	\item token
\end{itemize*}
}
{JSON representation of all types descended from the specified typeId, or all the types in the repository if no typeId is provided}
{http://docs.oasis-open.org/ns/cmis/browser/201103/typeContainer}


\cmisbrowserGET{getTypeDefinition}
{typeDefinition}
{
\begin{itemize*}
	\item typeId
	\item token
\end{itemize*}
}
{JSON representation of the specified type}
{http://docs.oasis-open.org/ns/cmis/browser/201103/typeDefinitionType}

\cmisexample{browser/getTypeDefinition}


\cmisbrowserGET{getCheckedOutDocs}
{checkedOut}
{
\begin{itemize*}
	\item filter
	\item maxItems
	\item skipCount
	\item orderBy
	\item renditionFilter 
	\item includeAllowableActions
	\item includeRelationships
	\item succinct
	\item token
\end{itemize*}
}
{JSON representation of the documents that have been checked out in the repository}
{http://docs.oasis-open.org/ns/cmis/browser/201103/objectList}

\cmisexample{browser/checkOut}


\cmisbrowserPOST{createDocument}
{createDocument}
{
\begin{itemize*}
	\item \nameref{browser:control:singlevalueproperties}
	\item \nameref{browser:control:multivalueproperties}
	\item \nameref{browser:control:content}
	\item \nameref{browser:control:versioningstate}
	\item \nameref{browser:control:policies}
	\item \nameref{browser:control:addaces}
	\item \nameref{browser:control:removeaces}
	\item \nameref{browser:control:succinct}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the newly created, unfiled document}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}
{201 Created}

\cmisexample{browser/createDocument}


\cmisbrowserPOST{createDocumentFromSource}
{createDocumentFromSource}
{
\begin{itemize*}
	\item \nameref{browser:control:sourceid}
	\item \nameref{browser:control:singlevalueproperties}
	\item \nameref{browser:control:multivalueproperties}
	\item \nameref{browser:control:content}
	\item \nameref{browser:control:versioningstate}
	\item \nameref{browser:control:policies}
	\item \nameref{browser:control:addaces}
	\item \nameref{browser:control:removeaces}
	\item \nameref{browser:control:succinct}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the newly created, unfiled document}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}
{201 Created}


\cmisbrowserPOST{createRelationship}
{createRelationship}
{
\begin{itemize*}
	\item \nameref{browser:control:singlevalueproperties}
	\item \nameref{browser:control:multivalueproperties}
	\item \nameref{browser:control:policies}
	\item \nameref{browser:control:addaces}
	\item \nameref{browser:control:removeaces}
	\item \nameref{browser:control:succinct}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the newly created relationship}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}
{201 Created}


\cmisbrowserPOST{createPolicy}
{createPolicy}
{
\begin{itemize*}
	\item \nameref{browser:control:singlevalueproperties}
	\item \nameref{browser:control:multivalueproperties}
	\item \nameref{browser:control:policies}
	\item \nameref{browser:control:addaces}
	\item \nameref{browser:control:removeaces}
	\item \nameref{browser:control:succinct}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the newly created, unfiled policy}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}
{201 Created}


\cmisbrowserPOST{createItem}
{createItem}
{
\begin{itemize*}
	\item \nameref{browser:control:singlevalueproperties}
	\item \nameref{browser:control:multivalueproperties}
	\item \nameref{browser:control:policies}
	\item \nameref{browser:control:addaces}
	\item \nameref{browser:control:removeaces}
	\item \nameref{browser:control:succinct}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the newly created, unfiled item}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}
{201 Created}


\cmisbrowserPOST{bulkUpdateProperties}
{bulkUpdate}
{
\begin{itemize*}
	\item \nameref{browser:control:objectids}
	\item \nameref{browser:control:changetokens}
	\item \nameref{browser:control:singlevalueproperties}
	\item \nameref{browser:control:multivalueproperties}
	\item \nameref{browser:control:addsecondarytypeids}
	\item \nameref{browser:control:removesecondarytypeids}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{List of ids of the updated objects with their new ids and change tokens}
{<Array>http://docs.oasis-open.org/ns/cmis/browser/201103/objectIdAndChangeToken}
{200 OK}


\cmisbrowserGET{query}
{query}
{
\begin{itemize*}
	\item q (maps to the parameter \texttt{statement})
	\item searchAllVersions
	\item maxItems
	\item skipCount
	\item includeAllowableActions
	\item includeRelationships
	\item renditionFilter
	\item succinct
	\item token
\end{itemize*}
}
{JSON representation of the results of the query}
{http://docs.oasis-open.org/ns/cmis/browser/201103/queryResultList}

\cmisexample{browser/doQuery}


\cmisbrowserPOST{query}
{query}
{
\begin{itemize*}
	\item \nameref{browser:control:query}
	\item \nameref{browser:control:succinct}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the results of the query}
{http://docs.oasis-open.org/ns/cmis/browser/201103/queryResultList}
{200 OK}

\cmisexample{browser/doQuery}


\cmisbrowserGET{getContentChanges}
{contentChanges}
{
\begin{itemize*}
	\item changeLogToken
	\item includeProperties
	\item includePolicyIds
	\item includeACL
	\item maxItems
	\item succinct
	\item token
\end{itemize*}
}
{JSON representation of the changed objects. The list object SHOULD contain the next change log token.}
{http://docs.oasis-open.org/ns/cmis/browser/201103/objectList}

\cmisexample{browser/getContentChanges}


\cmisbrowserPOST{createType}
{createType}
{
\begin{itemize*}
	\item \nameref{browser:control:type}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the newly created type}
{http://docs.oasis-open.org/ns/cmis/browser/201103/typeDefinitionType}
{201 Created}


\cmisbrowserPOST{updateType}
{updateType}
{
\begin{itemize*}
	\item \nameref{browser:control:type}
	\item \nameref{browser:control:token}
\end{itemize*}

}
{JSON representation of the updated type}
{http://docs.oasis-open.org/ns/cmis/browser/201103/typeDefinitionType}
{200 OK}


\cmisbrowserPOST{deleteType}
{deleteType}
{
\begin{itemize*}
	\item \nameref{browser:control:typeid}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{\textit{empty}}
{}
{200 OK}


\cmisbrowserGET{}
{lastResult}
{
\begin{itemize*}
	\item token
\end{itemize*}
}
{See section \ref{browser:responsecontent}~\nameref{browser:responsecontent}}
{http://docs.oasis-open.org/ns/cmis/browser/201103/transaction}


\subsection{Object URL}

\cmisbrowserGET{getChildren}
{children}
{
\begin{itemize*}
	\item maxItems
	\item skipCount
	\item filter
	\item includeAllowableActions
	\item includeRelationships
	\item renditionFilter
	\item orderBy
	\item includePathSegment
	\item succinct
	\item token
\end{itemize*}
}
{JSON representation of the children of the specified folder}
{http://docs.oasis-open.org/ns/cmis/browser/201103/objectInFolderList}

The selector can be omitted since \cmisservicelink{getChildren} only works on folders and the selector "children" is the default selector for folders.

\cmisexample{browser/getChildren}


\cmisbrowserGET{getDescendants}
{descendants}
{
\begin{itemize*}
	\item filter
	\item depth
	\item includeAllowableActions
	\item includeRelationships
	\item renditionFilter
	\item includePathSegment
	\item succinct
	\item token
\end{itemize*}
}
{JSON representation of the descendants of the specified folder}
{<Array>http://docs.oasis-open.org/ns/cmis/browser/201103/objectContainer}

\cmisexample{browser/getDecendants}


\cmisbrowserGET{getFolderTree}
{folderTree}
{
\begin{itemize*}
	\item filter
	\item depth
	\item includeAllowableActions
	\item includeRelationships
	\item renditionFilter
	\item includePathSegment
	\item succinct
	\item token
\end{itemize*}
}
{JSON representation of the folder tree of the specified folder}
{<Array>http://docs.oasis-open.org/ns/cmis/browser/201103/objectContainer}


\cmisbrowserGET{getFolderParent}
{parent}
{
\begin{itemize*}
	\item filter
	\item succinct
	\item token
\end{itemize*}
}
{JSON representation of the parent folder of the specified folder}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}


\cmisbrowserGET{getObjectParents}
{parents}
{
\begin{itemize*}
	\item filter
	\item includeRelationships
	\item renditionFilter
	\item includeAllowableActions
	\item includeRelativePathSegment
	\item succinct
	\item token
\end{itemize*}
}
{JSON representation of the folders that are the parents of the specified object}
{<Array>http://docs.oasis-open.org/ns/cmis/browser/201103/objectParent}

\cmisexample{browser/getObjectParents}


\cmisbrowserGET{getCheckedOutDocs}
{checkedout}
{
\begin{itemize*}
	\item filter
	\item maxItems
	\item skipCount
	\item orderBy
	\item renditionFilter 
	\item includeAllowableActions
	\item includeRelationships
	\item succinct
	\item token
\end{itemize*}
}
{JSON representation of the documents that have been checked out in this folder}
{http://docs.oasis-open.org/ns/cmis/browser/201103/objectList}


\cmisbrowserPOST{createDocument}
{createDocument}
{
\begin{itemize*}
	\item \nameref{browser:control:singlevalueproperties}
	\item \nameref{browser:control:multivalueproperties}
	\item \nameref{browser:control:content}
	\item \nameref{browser:control:versioningstate}
	\item \nameref{browser:control:policies}
	\item \nameref{browser:control:addaces}
	\item \nameref{browser:control:removeaces}
	\item \nameref{browser:control:succinct}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the newly created document in this folder}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}
{201 Created}

\cmisexample{browser/createDocument}


\cmisbrowserPOST{createDocumentFromSource}
{createDocumentFromSource}
{
\begin{itemize*}
	\item \nameref{browser:control:sourceid}
	\item \nameref{browser:control:singlevalueproperties}
	\item \nameref{browser:control:multivalueproperties}
	\item \nameref{browser:control:content}
	\item \nameref{browser:control:versioningstate}
	\item \nameref{browser:control:policies}
	\item \nameref{browser:control:addaces}
	\item \nameref{browser:control:removeaces}
	\item \nameref{browser:control:succinct}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the newly created document in this folder}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}
{201 Created}


\cmisbrowserPOST{createFolder}
{createFolder}
{
\begin{itemize*}
	\item \nameref{browser:control:singlevalueproperties}
	\item \nameref{browser:control:multivalueproperties}
	\item \nameref{browser:control:policies}
	\item \nameref{browser:control:addaces}
	\item \nameref{browser:control:removeaces}
	\item \nameref{browser:control:succinct}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the newly created folder in this folder}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}
{201 Created}


\cmisbrowserPOST{createPolicy}
{createPolicy}
{
\begin{itemize*}
	\item \nameref{browser:control:singlevalueproperties}
	\item \nameref{browser:control:multivalueproperties}
	\item \nameref{browser:control:policies}
	\item \nameref{browser:control:addaces}
	\item \nameref{browser:control:removeaces}
	\item \nameref{browser:control:succinct}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the newly created policy in this folder}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}
{201 Created}


\cmisbrowserPOST{createItem}
{createItem}
{
\begin{itemize*}
	\item \nameref{browser:control:singlevalueproperties}
	\item \nameref{browser:control:multivalueproperties}
	\item \nameref{browser:control:policies}
	\item \nameref{browser:control:addaces}
	\item \nameref{browser:control:removeaces}
	\item \nameref{browser:control:succinct}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the newly created item in this folder}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}
{201 Created}


\cmisbrowserGET{getAllowableActions}
{allowableActions}
{
\begin{itemize*}
	\item token
\end{itemize*}
}
{JSON representation of the allowable actions of the specified object}
{http://docs.oasis-open.org/ns/cmis/browser/201103/allowableActions}

\cmisexample{browser/getAllowableActions}


\cmisbrowserGET{getObject}
{object}
{
\begin{itemize*}
	\item filter
	\item includeRelationships
	\item includePolicyIds
	\item renditionFilter
	\item includeACL
	\item includeAllowableActions
	\item succinct
	\item token
\end{itemize*}
}
{JSON representation of the specified object}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}

\cmisexample{browser/getObject}


\cmisbrowserGET{getProperties}
{properties}
{
\begin{itemize*}
	\item filter
	\item succinct
	\item token	
\end{itemize*}
}
{JSON representation of the properties of the specified object}
{http://docs.oasis-open.org/ns/cmis/browser/201103/properties}


\cmisbrowserGET{getObjectByPath}
{object}
{
\begin{itemize*}
	\item filter
	\item includeRelationships
	\item includePolicyIds
	\item renditionFilter
	\item includeACL
	\item includeAllowableActions
	\item succinct
	\item token
\end{itemize*}
}
{JSON representation of the specified object}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}


\cmisbrowserGET{getContentStream}
{content}
{
\begin{itemize*}
	\item streamId
	\item download
	\item token
\end{itemize*}
}
{The content stream}
{}

The selector can be omitted since \cmisservicelink{getContentStream} only works on documents and the selector \texttt{content} is the default selector for documents.

If the request is not authenticated (no authentication HTTP header, no token, etc.) or the authentication details are invalid (wrong credentials, expired token, etc.), the repository MAY redirect the request to a login page (using HTTP status code 307 (Temporary Redirect)).  

How the login works is repository specific. If the user can be logged on, the repository either returns the requested document content directly or redirects to a URL that provides the document content.

To control if the web browser should load and show the content or offer it for download, an application can ask the repository to set the HTTP header \texttt{Content-Disposition} (see \hyperref[intro:rfc6266]{[RFC6266]}) by setting the \texttt{download} parameter. Valid values are \texttt{inline} (default) and \texttt{attachment}. These values correspond to the \texttt{disposition-type} in \hyperref[intro:rfc6266]{[RFC6266]}. If the \texttt{download} parameter is not provides, the repository SHOULD set a \texttt{Content-Disposition} header with the disposition type \texttt{inline}.

\cmisbrowserGET{getRenditions}
{renditions}
{
\begin{itemize*}
	\item renditionFilter
	\item maxItems
	\item skipCount
	\item token
\end{itemize*}
}
{JSON representation of the renditions for the specified object}
{<Array> http://docs.oasis-open.org/ns/cmis/browser/201103/rendition}


\cmisbrowserPOST{updateProperties}
{update}
{
\begin{itemize*}
	\item \nameref{browser:control:singlevalueproperties}
	\item \nameref{browser:control:multivalueproperties}
	\item \nameref{browser:control:changetoken}
	\item \nameref{browser:control:succinct}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the updated object}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}
{200 OK, if the object has been updated\newline 201 Created, if a new version has been created}

\cmisexample{browser/updateProperties}


\cmisbrowserPOST{moveObject}
{move}
{
\begin{itemize*}
	\item \nameref{browser:control:targetfolderid}
	\item \nameref{browser:control:sourcefolderid}
	\item \nameref{browser:control:succinct}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the moved object}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}
{201 Created}


\cmisbrowserPOST{deleteObject}
{delete}
{
\begin{itemize*}
	\item \nameref{browser:control:allversions}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{\textit{empty}}
{}
{200 OK}

\cmisexample{browser/deleteObject}


\cmisbrowserPOST{deleteTree}
{deleteTree}
{
\begin{itemize*}
	\item \nameref{browser:control:allversions}
	\item \nameref{browser:control:unfileobjects}
	\item \nameref{browser:control:continueonfailure}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{\textit{empty} if successful. A list of Ids if at least one object could not been deleted.}
{}
{200 OK}

When the operation fails, meaning that some objects in the tree are not deleted, an instance of type \path{http://docs.oasis-open.org/ns/cmis/browser/201103/ids} containing a list of ids of the objects not deleted MUST be returned.


\cmisbrowserPOST{setContentStream}
{setContent}
{
\begin{itemize*}
	\item \nameref{browser:control:overwriteflag}
	\item \nameref{browser:control:changetoken}
	\item \nameref{browser:control:content}
	\item \nameref{browser:control:succinct}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the object}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}
{201 Created}


\cmisbrowserPOST{appendContentStream}
{appendContent}
{
\begin{itemize*}
	\item \nameref{browser:control:islastchunk}
	\item \nameref{browser:control:changetoken}
	\item \nameref{browser:control:content}
	\item \nameref{browser:control:succinct}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the object}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}
{200 OK}


\cmisbrowserPOST{deleteContentStream}
{deleteContent}
{
\begin{itemize*}
	\item \nameref{browser:control:changetoken}
	\item \nameref{browser:control:succinct}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the object}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}
{200 OK}


\cmisbrowserPOST{addObjectToFolder}
{addObjectToFolder}
{
\begin{itemize*}
	\item \nameref{browser:control:folderid} 
	\item \nameref{browser:control:allversions}
	\item \nameref{browser:control:succinct}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the object}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}
{201 Created}


\cmisbrowserPOST{removeObjectFromFolder}
{removeObjectFromFolder}
{
\begin{itemize*}
	\item \nameref{browser:control:folderid} 
	\item \nameref{browser:control:succinct}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the object}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}
{201 Created}

\cmisexample{browser/removeObjectFromFolder}


\cmisbrowserPOST{checkOut}
{checkOut}{
\begin{itemize*}
	\item succinct
	\item token
\end{itemize*}
}
{JSON representation of the Private Working Copy\newline Note: The \texttt{contentCopied} flag is not returned. Clients may check content related properties such as the \texttt{cmis:contentStreamLength} property if the the Private Working Copy has a content stream.}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}
{201 Created}

\cmisexample{browser/checkOut}


\cmisbrowserPOST{cancelCheckOut}
{cancelCheckOut}
{
\begin{itemize*}
	\item token
\end{itemize*}
}
{\textit{empty}}
{}
{200 OK}


\cmisbrowserPOST{checkIn}
{checkIn}
{
\begin{itemize*}
	\item \nameref{browser:control:major}
	\item \nameref{browser:control:singlevalueproperties}
	\item \nameref{browser:control:multivalueproperties}
	\item \nameref{browser:control:content}
	\item \nameref{browser:control:checkincomment}
	\item \nameref{browser:control:policies}
	\item \nameref{browser:control:addaces}
	\item \nameref{browser:control:removeaces}
	\item \nameref{browser:control:succinct}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the new version}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}
{201 Created}

\cmisexample{browser/checkIn}


\cmisbrowserGET{getObjectOfLatestVersion}
{object}
{
\begin{itemize*}
	\item filter
	\item includeRelationships
	\item includePolicyIds
	\item renditionFilter
	\item includeACL
	\item includeAllowableActions
	\item returnVersion
	\begin{itemize*}
		\item If no value is present or the value is 'this', \cmisservicelink{getObject} MUST be called. 
		\item If the value is 'latest' \cmisservicelink{getObjectOfLatestVersion} MUST be called with the parameter \texttt{major} set to FALSE.
		\item If the value is 'latestmajor' \cmisservicelink{getObjectOfLatestVersion} MUST be called with the parameter \texttt{major} set to TRUE.
	\end{itemize*}
	\item succinct
	\item token
\end{itemize*}
}
{JSON representation of the specified object}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}


\cmisbrowserGET{getPropertiesOfLatestVersion}
{properties}
{
\begin{itemize*}
	\item filter
	\item returnVersion
	\begin{itemize*}
		\item If no value is present or the value is 'this', \cmisservicelink{getProperties} MUST be called. 
		\item If the value is 'latest' \cmisservicelink{getPropertiesOfLatestVersion} MUST be called with the parameter \texttt{major} set to FALSE.
		\item If the value is 'latestmajor' \cmisservicelink{getPropertiesOfLatestVersion} MUST be called with the parameter \texttt{major} set to TRUE.
	\end{itemize*}
	\item succinct
	\item token
\end{itemize*}
}
{JSON representation of the properties of the specified object}
{http://docs.oasis-open.org/ns/cmis/browser/201103/properties}


\cmisbrowserGET{getAllVersions}
{versions}
{
\begin{itemize*}
	\item filter
	\item includeAllowableActions
	\item succinct
	\item token
\end{itemize*}
}
{JSON representation of all the versions in the Version Series}
{<array>http://docs.oasis-open.org/ns/cmis/browser/201103/object}

\cmisexample{browser/getAllVersions}


\cmisbrowserGET{getObjectRelationships}
{relationships}
{
\begin{itemize*}
	\item includeSubRelationshipTypes
	\item relationshipDirection\item typeId
	\item maxItems
	\item skipCount
	\item filter
	\item includeAllowableActions
	\item succinct
	\item token
\end{itemize*}
}
{JSON representations of the relationships of the specified object}
{http://docs.oasis-open.org/ns/cmis/browser/201103/objectList}

\cmisbrowserGET{getAppliedPolicies}
{policies}
{
\begin{itemize*}
	\item filter
	\item succinct
	\item token
\end{itemize*}
}
{JSON representations of the policies applied to the specified object}
{<array>http://docs.oasis-open.org/ns/cmis/browser/201103/object}


\cmisbrowserPOST{applyPolicy}
{applyPolicy}
{
\begin{itemize*}
	\item \nameref{browser:control:policyid}
	\item \nameref{browser:control:succinct}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the updated object}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}
{200 OK}


\cmisbrowserPOST{removePolicy}
{removePolicy}
{
\begin{itemize*}
	\item \nameref{browser:control:policyid}
	\item \nameref{browser:control:succinct}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the updated object}
{http://docs.oasis-open.org/ns/cmis/browser/201103/object}
{200 OK}


\cmisbrowserPOST{applyACL}
{applyACL}
{
\begin{itemize*}
	\item \nameref{browser:control:addaces}
	\item \nameref{browser:control:removeaces}
	\item \nameref{browser:control:aclpropagation}
	\item \nameref{browser:control:token}
\end{itemize*}
}
{JSON representation of the updated ACL}
{http://docs.oasis-open.org/ns/cmis/browser/201103/acl}
{200 OK}


\cmisbrowserGET{getACL}
{acl}
{
\begin{itemize*}
	\item onlyBasicPermissions
	\item token
\end{itemize*}
}
{JSON representation of the ACL}
{http://docs.oasis-open.org/ns/cmis/browser/201103/acl}

\cmisexample{browser/getAcl}


\subsection{Use of HTML Forms}
\label{browser:htmlforms}

As described in section \ref{browser:services}~\nameref{browser:services} HTML forms are used to create, update and delete CMIS content.   

\begin{sloppypar}
The form submission method (HTML form attribute "method") MUST be "POST". If a content stream is not attached to the form, the encoding type (HTML form attribute "enctype") MUST be either \texttt{application/x-www-form-urlencoded} or \texttt{multipart/form-data}. If a content stream is attached, the encoding type MUST be \texttt{multipart/form-data}.
\end{sloppypar}

The names of the controls within the form are defined by the patterns in the following sections. All control names are case-insensitive as defined by the HTML specification. Control names MUST be unique within a form. If the control value of an optional parameter is set to an empty string ("") the default value MUST be used.

A client MAY add controls to a form that are not defined by CMIS as long as the control names don't conflict with the patterns described in this specification.

Since control values are strings, all other data types have to be serialized to strings. 
The same rules that apply to the serialization to JSON apply here.


\subsubsection{Action}

An HTML form used to POST CMIS content MUST include a control named "cmisaction" that indicates the CMIS operation to be performed. See section \ref{browser:services}~\nameref{browser:services} for valid control values.  The value of the control is case insensitive.

Example:

\begin{lstlisting}[language=XML]
<input name="cmisaction" type="hidden" value="createDocument" />
\end{lstlisting}


\subsubsection{Structured and Array Parameters}

Some CMIS operations require structured parameters and arrays of values. Since HTML forms don't support that usage, some CMIS operation parameters are split into multiple controls in a form. 

For example, a CMIS property is split into a control that holds the property id and another control that hold property value. The association between the two controls is done by convention. 

The entirety of all properties is made up of an array of these property controls.

Names of controls that are part of an array end with "[\texttt{<index>}]" where \texttt{<index>} is a positive integer. Arrays MUST always start with the index 0 and MUST be gapless.

Example:

An array of three properties looks like this in a HTML form:

\begin{lstlisting}[language=XML]
<input name="propertyId[0]"    type="hidden" value="cmis:name" />
<input name="propertyValue[0]" type="text"   value="my document" />

<input name="propertyId[1]"    type="hidden" value="cmis:objectTypeId" />
<input name="propertyValue[1]" type="hidden" value="my:firstObjectType" />

<input name="propertyId[2]"    type="hidden" value="my:intProperty" />
<input name="propertyValue[2]" type="text"   value="42" />
\end{lstlisting}

If a client sends invalid, incomplete or inconsistent data the repository SHOULD throw an \cmisexceptionlink{invalidArgument} exception.


\subsubsection{CMIS Controls}

This section lists all HTML form controls used by CMIS services.

\paragraph{Succinct}
\label{browser:control:succinct}

This flag indicates that the property presentation must be succinct. See section \ref{browser:succinct}~\nameref{browser:succinct}.

\cmisbrowsercontrol{succinct}{"true" or not set}

Example:

\begin{lstlisting}[language=XML]
<input name="succinct" type="hidden" value="true" />
\end{lstlisting}


\paragraph{Token}
\label{browser:control:token}

This is used to authorize the request. See section \ref{browser:authenticationtoken}~\nameref{browser:authenticationtoken}.

\cmisbrowsercontrol{token}{Token String}

Example:

\begin{lstlisting}[language=XML]
<input name="token" type="hidden" value="e45ab575d6fe4aab901e9" />
\end{lstlisting}


\paragraph{Object Id}
\label{browser:control:objectid}

This is used if one object should be addressed.

\cmisbrowsercontrol{objectId}{Object Id}

Example:

\begin{lstlisting}[language=XML]
<input name="objectId" type="hidden" value="1234-abcd-5678" />
\end{lstlisting}


\paragraph{Object Ids}
\label{browser:control:objectids}

This is used if multiple objects should be addressed. (Only applies to \cmisservicelink{bulkUpdateProperties}.)


\cmisbrowsercontrol{objectId[<idIndex>]}{Object Id}

Example:

\begin{lstlisting}[language=XML]
<input name="objectId[0]" type="hidden" value="1234-abcd-5678" />
<input name="objectId[1]" type="hidden" value="9876-bcde-5432" />
<input name="objectId[2]" type="hidden" value="7654-qwer-2345" />
\end{lstlisting}



\paragraph{Folder Id}
\label{browser:control:folderid}

\cmisbrowsercontrol{folderId}{Folder Id}

Example:

\begin{lstlisting}[language=XML]
<input name="folderId" type="hidden" value="1234-abcd-5678" />
\end{lstlisting}


\paragraph{Source Id}
\label{browser:control:sourceid}

\cmisbrowsercontrol{sourceId}{Source Id}

Example:

\begin{lstlisting}[language=XML]
<input name="sourceId" type="hidden" value="1234-abcd-5678" />
\end{lstlisting}


\paragraph{Source folder Id}
\label{browser:control:sourcefolderid}

\cmisbrowsercontrol{sourceFolderId}{Folder Id}

Example:

\begin{lstlisting}[language=XML]
<input name="sourceFolderId" type="hidden" value="1234-abcd-5678" />
\end{lstlisting}


\paragraph{Target folder Id}
\label{browser:control:targetfolderid}

\cmisbrowsercontrol{targetFolderId}{Folder Id}

Example:

\begin{lstlisting}[language=XML]
<input name="targetFolderId" type="hidden" value="1234-abcd-5678" />
\end{lstlisting}


\paragraph{Policy Id}
\label{browser:control:policyid}

\cmisbrowsercontrol{policyId}{Policy Id}

Example:

\begin{lstlisting}[language=XML]
<input name="policyId" type="hidden" value="1234-abcd-5678" />
\end{lstlisting}


\paragraph{Type Id}
\label{browser:control:typeid}

\cmisbrowsercontrol{typeId}{Object-type Id}

Example:

\begin{lstlisting}[language=XML]
<input name="typeId" type="hidden" value="my:type" />
\end{lstlisting}


\paragraph{Single-value Properties}
\label{browser:control:singlevalueproperties}

A single-value property is made up of a pair of a \texttt{propertyId} control and a \texttt{propertyValue} control with the same \texttt{<propIndex>}. To unset the property, the client must submit form data in which the \texttt{propertyId} MUST be present 
and the \texttt{propertyValue} control MUST NOT be present. 

\texttt{<propIndex>} does not imply any order.


\subparagraph{Property Id}

\cmisbrowsercontrol{propertyId[<propIndex>]}{Property Id}


\subparagraph{Property Value}

\cmisbrowsercontrol{propertyValue[<propIndex>]}{Property Value}

Example:

\begin{lstlisting}[language=XML]
<input name="propertyId[0]"    type="hidden" value="my:firstname" />
<input name="propertyValue[0]" type="text"   value="John" />

<input name="propertyId[1]"    type="hidden" value="my:lastname" />
<input name="propertyValue[1]" type="text"   value="Smith" />
\end{lstlisting}


\paragraph{Multi-value Properties}
\label{browser:control:multivalueproperties}

A multi-value property is made up of a \texttt{propertyId} control and a series of \texttt{propertyValue} controls with the same \texttt{<propIndex>}. The \texttt{propertyValue} controls MUST have a second index \texttt{<seqIndex>}. This array MUST also always start with the index 0 and MUST be gapless. To unset the property, NO \texttt{propertyValue} control MUST be present. 

\texttt{<propIndex>} does not imply any order, but \texttt{<seqIndex>} defines the order of the values.


\subparagraph{Property Id}

\cmisbrowsercontrol{propertyId[<propIndex>]}{Property Id}


\subparagraph{Property Value}

\cmisbrowsercontrol{propertyValue[<propIndex>][<seqIndex>]}{Property value at position \texttt{<seqIndex>}}

Example:

\begin{lstlisting}[language=XML]
<input name="propertyId[0]"       type="hidden" value="my:countries" />
<input name="propertyValue[0][0]" type="text"   value="Germany" />
<input name="propertyValue[0][1]" type="text"   value="United States" />
<input name="propertyValue[0][2]" type="text"   value="France" />
<input name="propertyValue[0][3]" type="text"   value="United Kingdom" />
<input name="propertyValue[0][4]" type="text"   value="Switzerland" />

<input name="propertyId[1]"       type="hidden" value="my:colors" />
<input name="propertyValue[1][0]" type="text"   value="red" />
<input name="propertyValue[1][1]" type="text"   value="green" />
<input name="propertyValue[1][2]" type="text"   value="blue" />
\end{lstlisting}


\paragraph{Adding Secondary Type Ids}
\label{browser:control:addsecondarytypeids}

Secondary type ids can be added by providing a list of ids.

\cmisbrowsercontrol{addSecondaryTypeId[<typeIndex>]}{Secondary Type Id}

Example:

\begin{lstlisting}[language=XML]
<input name="addSecondaryTypeId[0]" type="hidden" value="my:audit" />
<input name="addSecondaryTypeId[1]" type="hidden" value="my:comment" />
\end{lstlisting}


\paragraph{Removing Secondary Type Ids}
\label{browser:control:removesecondarytypeids}

Secondary type ids can be removed by providing a list of ids.

\cmisbrowsercontrol{removeSecondaryTypeId[<typeIndex>]}{Secondary Type Id}

Example:

\begin{lstlisting}[language=XML]
<input name="removeSecondaryTypeId[0]" type="hidden" value="my:favorite" />
<input name="removeSecondaryTypeId[1]" type="hidden" value="my:workflow123" />
\end{lstlisting}



\paragraph{Adding Access Control Entries (ACEs)}
\label{browser:control:addaces}

In order to add an ACE to a CMIS object, a client passes a control named \texttt{addACEPrincipal} along with a set of corresponding \texttt{addACEPermission} controls. An index value \texttt{<addACEIndex>} links the principal with its permissions, and a second index \texttt{<permIndex>} differentiates the permissions. 

\texttt{<addACEIndex>} and \texttt{<permIndex>} don't imply any order.


\subparagraph{Principal}

\cmisbrowsercontrol{addACEPrincipal[<addACEIndex>]}{Principal Id}


\subparagraph{Permission}

\cmisbrowsercontrol{addACEPermission[<addACEIndex>][<permIndex>]}{Permission String}

Example:

\begin{lstlisting}[language=XML]
<input name="addACEPrincipal[0]"     type="hidden" value="john" />
<input name="addACEPermission[0][0]" type="hidden" value="cmis:read" />
<input name="addACEPermission[0][1]" type="hidden" value="perm:publish" />

<input name="addACEPrincipal[1]"     type="hidden" value="mary" />
<input name="addACEPermission[1][0]" type="hidden" value="cmis:all" />
\end{lstlisting}


\paragraph{Removing Access Control Entries (ACEs)}
\label{browser:control:removeaces}

In order to remove an ACE to a CMIS object, a client passes a control named \texttt{removeACEPrincipal} along with a set of corresponding \texttt{removeACEPermission} controls. An index value \texttt{<removeACEIndex>} links the principal with its permissions, and a second index \texttt{<permIndex>} differentiates the permissions. 

\texttt{<removeACEIndex>} and \texttt{<permIndex>} don't imply any order.


\subparagraph{Principal}

\cmisbrowsercontrol{removeACEPrincipal[<removeACEIndex>]}{Principal Id}


\subparagraph{Permission}

\cmisbrowsercontrol{removeACEPermission[<removeACEIndex>][<permIndex>]}{Permission String}

Example:

\begin{lstlisting}[language=XML]
<input name="removeACEPrincipal[0]"     type="hidden" value="tom" />
<input name="removeACEPermission[0][0]" type="hidden" value="cmis:write" />
<input name="removeACEPermission[0][1]" type="hidden" value="perm:publish" />

<input name="removeACEPrincipal[1]"     type="hidden" value="bob" />
<input name="removeACEPermission[1][0]" type="hidden" value="perm:forward" />
\end{lstlisting}


\paragraph{ACL propagation}
\label{browser:control:aclpropagation}

In order to specify how to propagate ACE's, a control named \texttt{ACLPropagation} is used. 

\cmisbrowsercontrol{ACLPropagation}{ACL propagation enum ("objectonly", "propagate", "repositorydetermined")}

Example:

\begin{lstlisting}[language=XML]
<input name="ACLPropagation" type="hidden" value="propagate" />
\end{lstlisting}


\paragraph{Policies}
\label{browser:control:policies}

Policies are assigned and removed to CMIS objects by including a control named \texttt{policy} with an index of \texttt{<policyIndex>}.  A policy list is made up of a series of these \texttt{policy} controls.

\texttt{<policyIndex>} does not imply any order.

\cmisbrowsercontrol{policy[<policyIndex>]}{Policy Id}

Example:

\begin{lstlisting}[language=XML]
<input name="policy[0]" type="hidden" value="1111-aaaa-2222" />
<input name="policy[1]" type="hidden" value="3333-bbbb-4444" />
<input name="policy[2]" type="hidden" value="5555-cccc-6666" />
\end{lstlisting}


\paragraph{Change Token}
\label{browser:control:changetoken}

A CMIS change token is included by using a form control named \texttt{changeToken}.  If the value of the control is set to the empty string, then the repository MUST treat the change token as not set. 

\cmisbrowsercontrol{changeToken}{Change Token}

Example:

\begin{lstlisting}[language=XML]
<input name="changeToken" type="hidden" value="8923653942" />
\end{lstlisting}


\paragraph{Change Tokens}
\label{browser:control:changetokens}

If multiple objects are addressed, this list of change tokens matches the list of object ids (see section \ref{browser:control:objectids}~\nameref{browser:control:objectids}). The index of each change token MUST match the index of the corresponding object id.

The rules defined in section \ref{browser:control:changetoken}~\nameref{browser:control:changetoken} apply to each change token.

\cmisbrowsercontrol{changeToken[<idIndex>]}{Change Token}

Example:

\begin{lstlisting}[language=XML]
<input name="changeToken[0]" type="hidden" value="8923653942" />
<input name="changeToken[1]" type="hidden" value="1234567890" />
<input name="changeToken[2]" type="hidden" value="5555555555" />
\end{lstlisting}



\paragraph{All Versions}
\label{browser:control:allversions}

Indicates if only this version or all versions should be affected.

\cmisbrowsercontrol{allVersions}{Boolean ("true", "false")}

Example:

\begin{lstlisting}[language=XML]
<input name="allVersions" type="hidden" value="true" />
\end{lstlisting}


\paragraph{Unfile Objects}
\label{browser:control:unfileobjects}

Indicates how \cmisservicelink{deleteTree} should delete objects.

\cmisbrowsercontrol{unfileObjects}{enumUnfileObject ("unfile", "deletesinglefiled", "delete")}

Example:

\begin{lstlisting}[language=XML]
<input name="unfileObjects" type="hidden" value="delete" />
\end{lstlisting}


\paragraph{Continue On Failure}
\label{browser:control:continueonfailure}

Indicates if \cmisservicelink{deleteTree} should continue on failure.

\cmisbrowsercontrol{continueOnFailure}{Boolean ("true", "false")}

Example:

\begin{lstlisting}[language=XML]
<input name="continueOnFailure" type="hidden" value="true" />
\end{lstlisting}


\paragraph{Overwrite Flag}
\label{browser:control:overwriteflag}

Indicates if \cmisservicelink{setContentStream} should overwrite the existing content.

\cmisbrowsercontrol{overwriteFlag}{Boolean ("true", "false")}

Example:

\begin{lstlisting}[language=XML]
<input name="overwriteFlag" type="hidden" value="true" />
\end{lstlisting}


\paragraph{IsLastChunk}
\label{browser:control:islastchunk}

Indicates if \cmisservicelink{appendContentStream} should consider this chunk the last chunk of the document content.

\cmisbrowsercontrol{isLastChunk}{Boolean ("true", "false")}

Example:

\begin{lstlisting}[language=XML]
<input name="isLastChunk" type="hidden" value="true" />
\end{lstlisting}



\paragraph{Major}
\label{browser:control:major}

Indicates if the major or minor version is expected.

\cmisbrowsercontrol{major}{Boolean ("true", "false")}

Example:

\begin{lstlisting}[language=XML]
<input name="major" type="hidden" value="true" />
\end{lstlisting}


\paragraph{Versioning State}
\label{browser:control:versioningstate}

When a document is checked in, a control named \texttt{versioningState} is used to set the versioning state.

\cmisbrowsercontrol{versioningState}{Versioning state enum ("none", "major", "minor", "checkedout")}

Example:

\begin{lstlisting}[language=XML]
<input name="versioningState" type="hidden" value="major" />
\end{lstlisting}


\paragraph{Checkin Comment}
\label{browser:control:checkincomment}

When a document is checked in, a control named \texttt{checkinComment} is used to include the checkin comment. 


\cmisbrowsercontrol{checkinComment}{Checkin comment}

Example:

\begin{lstlisting}[language=XML]
<input name="checkinComment" type="text" value="My comment" />
\end{lstlisting}


\paragraph{Query}
\label{browser:control:query}

A CMIS query can be constructed using a control named \texttt{statement} and set of controls to specify the query options.


\subparagraph{Statement}

\cmisbrowsercontrol{statement}{CMIS query statement}


\subparagraph{Search all versions}

\cmisbrowsercontrol{searchAllVersions}{Boolean ("true", "false")}


\subparagraph{Include relationships}

\cmisbrowsercontrol{includeRelationships}{includeRelationships enum  ("none", "source" ,"target", "both")}


\subparagraph{Rendition filter}

\cmisbrowsercontrol{renditionFilter}{Rendition filter. See section \ref{dm:services:renditions}~\nameref{dm:services:renditions}.}


\subparagraph{Include allowable actions}

\cmisbrowsercontrol{includeAllowableActions}{Boolean ("true", "false")}


\subparagraph{Max Items}

\cmisbrowsercontrol{maxItems}{Non-negative integer. See section \ref{dm:paging}~\nameref{dm:paging}.}


\subparagraph{Skip Count}

\cmisbrowsercontrol{skipCount}{Non-negative integer. See section \ref{dm:paging}~\nameref{dm:paging}.}

Example:

\begin{lstlisting}[language=XML]
<input name="statement" type="text"   value="SELECT * FROM cmis:document" />
<input name="searchAllVersions"       type="hidden" value="false" />
<input name="includeRelationships"    type="hidden" value="none" />
<input name="renditionFilter"         type="hidden" value="cmis:none" />
<input name="includeAllowableActions" type="hidden" value="false" />
<input name="maxItems"                type="hidden" value="100" />
<input name="skipCount"               type="hidden" value="0" />
\end{lstlisting}


\paragraph{Content}
\label{browser:control:content}

A "file" select control SHOULD be used to attach content. See \hyperref[intro:rfc1867]{[RFC1867]}.

\cmisbrowsercontrol{content}{\textit{none}}

\begin{lstlisting}[language=XML]
<input name="content" type="file" />
\end{lstlisting}

\paragraph{Type}
\label{browser:control:type}

\cmisbrowsercontrol{type}{JSON representation of the type definition.\newline Schema element:\newline \texttt{http://docs.oasis-open.org/ns/cmis/browser/201103/typeDefinitionType}}

\begin{lstlisting}[language=XML]
<textarea name="type">
{
    "id":"my:documentType",
    "baseId":"cmis:document",
    "parentId":"cmis:document",
    "displayName":"My Document Type",
    "description":"My new type",
    "localNamespace":"local",
    "localName":"my:documentType",
    "queryName":"my:documentType",
    "fileable":true,
    "includedInSupertypeQuery":true,
    "creatable":true,
    "fulltextIndexed":false,
    "queryable":false,
    "controllableACL":true,
    "controllablePolicy":false,
    "propertyDefinitions":{
        "my:stringProperty":{
            "id":"my:stringProperty",
            "localNamespace":"local",
            "localName":"my:stringProperty",
            "queryName":"my:stringProperty",
            "displayName":"My String Property",
            "description":"This is a String.",
            "propertyType":"string",
            "updatability":"readwrite",
            "inherited":false,
            "openChoice":false,
            "required":false,
            "cardinality":"single",
            "queryable":true,
            "orderable":true,
        }
    }
}
</textarea>
\end{lstlisting}


\subsubsection{Access to Form Response Content }
\label{browser:responsecontent}

JSON response content is subject to the same security constraints as any other kind of JavaScript which means that a browser will not allow JavaScript in a page to access JSON objects included in an HTML Form response if that response came from a different domain than the rest of the page content. For example, suppose a browser displayed an HTML Form from Web Server \texttt{foo.example.com} to create a document in a CMIS repository on server \texttt{bar.example.com}. When the user submits the form, there is no way for the page to access the JSON object representing the new document created as a response to the submitted form.   

\cmisgraphics{transaction1}{width=1\textwidth}{Web application cannot retrieve the JSON object returned by the repository}
%\begin{figure}[htb]
%\centering
%\includegraphics[width=0.8\textwidth]{transaction1.pdf}
%\caption{Web application cannot retrieve the JSON object returned by the repository}
%\end{figure}

To make it possible for a browser client to access the JSON content answered from the CMIS repository, the repository MUST keep the core result details (the status code, object id and potential error message) of a completed request and make those details available to the client in a later request.

To correlate the result of a CMIS request with the later call to retrieve the result of that request, the "token" is used (see section \ref{browser:authenticationtoken}~\nameref{browser:authenticationtoken}).

After the operation has been performed, the client can retrieve the result by sending a HTTP GET requested to the \nameref{browser:repositoryurl} with the selector set to \texttt{lastResult} and an parameter \texttt{token} which is set to the same token string previously sent with the form.

The result details MUST be answered as a JSON object containing these elements.

\begin{description}
	\item[integer \texttt{code}] An integer containing the HTTP status code for the operation.
	\item[string \texttt{objectId}] A string containing the id of the object, if the operation was successful. If the operation was not successful, the value of this string is undefined.
	\item[string \texttt{exception}] A string containing the exception, if the operation was not successful. If the operation was successful, the value of this string is undefined.
	\item[string \texttt{message}] A string containing the error message, if the operation was not successful. If the operation was successful, the value of this string is undefined.
\end{description}

The result details SHOULD 
\begin{itemize}
	\item only be available to the same client (as defined by the client's IP address) that called the operation.
	\item not be kept longer than an hour, since they are supposed to be retrieved immediately after the operation by the client.
	\item only be retrievable once. That is, a second attempt SHOULD return an \cmisexceptionlink{invalidArgument} error (code = 0).
\end{itemize}

If the value of the parameter \texttt{token} is invalid, the "code" field of this JSON object MUST be set to 0.

If the \texttt{token} control is not specified in the form, the repository does not need to keep the result details because there is no way for the client to retrieve them. Note that in this case some other form of authentication SHOULD be in place.

If the \texttt{token} control is specified, the repository MUST return the HTTP status code 200 and a HTML page. This is necessary to avoid problems with certain web browsers, which cannot display a JSON response or ask the end user to save the JSON response. Since the purpose of  this method is to fetch the result of the request at a later point in time, the immediate response doesn't matter and can be empty.

Example:

\cmisgraphics{transaction2}{width=1\textwidth}{Selector "lastResult" returns the last service result from the repository}

%\begin{figure}[htb]
%\centering
%\includegraphics[width=0.8\textwidth]{transaction2.pdf}
%\caption{Selector "lastResult" returns the last service result from the repository}
%\end{figure}

When the client submits the HTML form, it can include a form control with the name "token" like this:

\begin{lstlisting}[language=XML]
<input name="token" type="hidden" value="e45ab575d6fe4aab901e9" />
\end{lstlisting}

Soon thereafter, the client could retrieve the results of the form post by making a request like this

\path{http://example.com/cmis/repository/123?cmisselector=lastResult&}\\ 
\hfill\path{callback=showNewDocumentId&token=e45ab575d6fe4aab901e9}

and then, the repository would answer a JSON object that contains the result details, like

\begin{lstlisting}
{
   "code" : 201,
   "objectId" : "1234-abcd-5678",
   "exception" : null,
   "message" : null
}
\end{lstlisting}

The client can then retrieve the details for the object using its objectId.


\paragraph{Client Implementation Hints}
Whenever the \texttt{token} control is used, the repository must respond with a HTML page. The content of this page is not defined in this specification and might be empty. In general, the response is not useful for an end-user.

Therefore, clients should redirect the response to a hidden HTML iframe. The iframe's \texttt{onLoad} event can be used as an operation status notification. When it is triggered the operation is complete on the repository side and it is safe then to retrieve the results. 


\paragraph{Server Implementation Hints}
The use of this method can make CMIS stateful since the server has to remember details of a previous service request. However, the state can be kept entirely on the client, to eliminate the need for the server to be stateful at all.   


\subparagraph{State on Server}

Result details are non-permanent data and don't need to be persisted. The repository might store the state in-memory or in shared session state.

When a repository receives a \texttt{lastResult} request it should check the IP address of the client and the expiration time of the result details before it replies. This ensures that the data is not being retrieved by a malicious client, and that the requested data is relevant.


\subparagraph{State on Client}

The state can be managed on the client side using browser cookies, which keeps the repository stateless. 

When a \texttt{token} control is sent with the form data, the repository can attach a cookie to its POST response. The cookie name is derived from the \texttt{token} value and the cookie value would contain the result details.

When the repository receives a \texttt{lastResult} request, it also receives the cookies from the browser. So, if the repository can find a cookie that matches the \texttt{token} parameter value it can send back the cookie value and delete the cookie. If there is no corresponding cookie, it can reply with an error message.  

Since the browser takes care of the cookie expiration and cookies can only be sent from the originating client, there are no new additional security and lifecycle issues for the repository to handle.
