Advanced integration

Collabora Online uses a WOPI-like protocol to interact with hosts who want to integrate Collabora Online in them.

Refer to WOPI docs for further details on the protocol’s inspiration.

CheckFileInfo response properties

BaseFileName

A string containing the base name of the file, omitting its path.

DisablePrint

Disables print functionality in Collabora Online (COOL) backend. If true, HidePrintOption is assumed to be true.

OwnerID

A programmatic string identifier for the owner of the file.

PostMessageOrigin

A string for the domain the host page sends/receives PostMessages from, we only listen to messages from this domain.

Size

Size of the file in bytes (64bit)

TemplateSource

The ID of file (like the wopi/files/ID) can be a non-existing file. In that case, the file will be created from a template when the template (eg. an OTT file) is specified as TemplateSource in the CheckFileInfo response.

The TemplateSource is supposed to be an URL like https://somewhere/accessible/file.ott that is accessible by the Online.

For the actual saving of the content, normal PutFile mechanism will be used.

UserCanWrite

A boolean flag, indicating whether the user has permission to edit and/or over-write the file. If not set PutFile will fail.

UserCanNotWriteRelative

A boolean flag indicating that the user cannot Save-As on this server, so PutRelativeFile will fail.

UserId

A programmatic string identifier of the user.

UserFriendlyName

A string representing the name of the user for display in the UI.

While nominally an optional field, it is used to identify the author of changes in documents. When missing, UnknownUser will be used instead, with a possible suffix with the UserId.

Strongly recommended to set it to a valid value.

CheckFileInfo extended response properties

IsAdminUser

It should be true when the user has administrator rights in the integration, and false otherwise. Some functionality of Collabora Online, such as update check and server audit are supposed to be shown to administrators only. Since 24.04.4.

IsAnonymousUser

It should be true when the user is not authenticated in the integration, and false otherwise. Some functionality of Collabora Online is supposed to be shown to authenticated users only. Since 24.04.4.

EnableInsertRemoteImage

If set to true, this will enable the insertion of images chosen from the WOPI storage. A UI_InsertGraphic postMessage will be send to the WOPI host to request the UI to select the file.

EnableInsertRemoteFile

If set to true, this will enable the insertion of files (e.g., multimedia) chosen from the WOPI storage. A UI_InsertFile postMessage will be send to the WOPI host to request the UI to select the file. Since 24.04.10.

DisableInsertLocalImage

If set to true, this will disable the insertion of image/multimedia chosen from the local device. If EnableInsertRemoteImage is not set to true, then inserting image files is not possible.

HidePrintOption

If set to true, hides the print option from the file menu bar in the UI.

HideSaveOption

If set to true, hides the save button from the toolbar and file menubar in the UI.

HideExportOption

Hides Download as option in the file menubar.

DisableExport

Disables export functionality in backend. If set to true, HideExportOption is assumed to be true.

DisableCopy

Disables copying from the document in COOL backend. Pasting into the document would still be possible. However, it is still possible to do an “internal” cut/copy/paste.

DisableInactiveMessages

Disables displaying of the explanation text on the overlay when the document becomes inactive or killed. With this, the JS integration must provide the user with appropriate message when it gets Session_Closed or User_Idle postMessages.

DownloadAsPostMessage

Indicate that the integration wants to handle the downloading of pdf for printing or svg for slideshows or exported document, because it cannot rely on browser’s support for downloading.

When this is set to true, the user’s eg. Print action will trigger a postMessage called Download_As, with the following JSON in the Values:

{ Type: 'print'|'slideshow'|'export', URL: ...url you use for the actual downloading... }

SaveAsPostmessage

Similar to download as, doctype extensions can be provided for save-as. In this case the new file is loaded in the integration instead of downloaded.

{format: '<extension>' }

To achieve this, args: {format: '<extension>' } parameter needs to be sent inside UI_SaveAs. The integration should provide dialog with filename, there the extension will be set after the filename. The remaining work is already handled by save-as.

EnableOwnerTermination

If set to true, it allows the document owner (the one with OwnerId =UserId) to send a closedocument message. For more information please visit protocol.txt.

UserExtraInfo

JSON object that contains additional info about the user, for example the avatar image.

Example: User’s additional info
{
  'avatar': 'http://url/to/user/avatar',
  'mail': 'user@server.com',
}
Example: User’s additional info via PHP
'UserExtraInfo' => [ 'avatar' => 'http://url/to/user/avatar', 'mail' => 'user@server.com' ]

Note: There is strict Content Security Policy that restricts image resources (img-src), therefore the avatar URL must not violate the CSP, otherwise it will show as broken images.

DEPRECATED: The is_admin boolean property is recommended to be set by integration. It should be true when the user has administrator rights in the integration, and false otherwise. Some functionality of Collabora Online, such as update check and server audit are supposed to be shown to administrators only. Use IsAdminUser instead for 24.04.4 and newer.

DEPRECATED: The is_guest boolean propery may be set by the integration, when the user is guest, i.e. the user gets a link to open a shared document. The welcome dialog of Collabora Online Development Edition (CODE) is not shown to guest users. Use IsAnonymousUser instead for 24.04.4 and newer.

UserPrivateInfo

JSON object that contains additional info about the user, but unlike the UserExtraInfo it is not shared among the views in collaborative editing sessions.

For example it can hold the ZoteroAPIKey which is the personal API key to Zotero Web API, for working with citation databases. When the integration provides a Zotero API key for the user, the functionality of handling Zotero databases gets enabled in Collabora Online’s user interface.

Document signing

When the SignatureCert, SignatureKey and SignatureCa keys in UserPrivateInfo are specified, the document signing functionality gets enabled in Collabora Online’s user interface.

For testing purposes it is OK to use self signed certificates. You can create the necessary files yourself. The following example creates a test CA, a test intermediate CA and a test certificate for document signing. The resulting .pem files provide the value for the above JSON keys.

To create the test root CA:

1 mkdir -p ca/{certs,crl,newcerts,private}
2 touch ca/index.txt
3 echo 1000 > ca/serial
4 curl -o ca/openssl.cnf https://raw.githubusercontent.com/CollaboraOnline/collabora-online-sdk-examples/master/signing/root.cnf
5 openssl genrsa -out ca/private/ca.key.pem 4096
6 openssl req -config ca/openssl.cnf -key ca/private/ca.key.pem -new -x509 -days 36500 -sha256 -extensions v3_ca -out ca/certs/ca.cert.pem -subj "/C=UK/ST=England/O=COOL Test/CN=COOL Test Root CA"

To create the test intermediate CA:

1 mkdir -p ca/intermediate/{certs,crl,csr,newcerts,private}
2 touch ca/intermediate/index.txt
3 echo 1000 > ca/intermediate/serial
4 curl -o ca/intermediate/openssl.cnf https://raw.githubusercontent.com/CollaboraOnline/collabora-online-sdk-examples/master/signing/intermediate.cnf
5 openssl genrsa -out ca/intermediate/private/intermediate.key.pem
6 openssl req -config ca/intermediate/openssl.cnf -new -sha256 -key ca/intermediate/private/intermediate.key.pem -out ca/intermediate/csr/intermediate.csr.pem -subj "/C=UK/ST=England/O=COOL Test/CN=COOL Test Intermediate CA"
7 openssl ca -batch -config ca/openssl.cnf -extensions v3_intermediate_ca -days 36500 -notext -md sha256 -in ca/intermediate/csr/intermediate.csr.pem -out ca/intermediate/certs/intermediate.cert.pem
8 cat ca/intermediate/certs/intermediate.cert.pem ca/certs/ca.cert.pem > ca/intermediate/certs/ca-chain.cert.pem

To create the signing certificate:

1 openssl genrsa -out ca/intermediate/private/example-cool-Alice.key.pem 2048
2 openssl req -config ca/intermediate/openssl.cnf -key ca/intermediate/private/example-cool-Alice.key.pem -new -sha256 -out ca/intermediate/csr/example-cool-Alice.csr.pem -subj "/C=UK/ST=England/O=COOL Test/CN=COOL Test Alice"
3 openssl ca -batch -config ca/intermediate/openssl.cnf -extensions usr_cert -days 36500 -notext -md sha256 -in ca/intermediate/csr/example-cool-Alice.csr.pem -out ca/intermediate/certs/example-cool-Alice.cert.pem

After these, you can find the CA chain at ca/intermediate/certs/ca-chain.cert.pem, the signing certificate at ca/intermediate/certs/example-cool-Alice.cert.pem and finally the signing key at ca/intermediate/private/example-cool-Alice.key.pem.

ServerPrivateInfo

JSON object that contains credentials, but unlike UserPrivateInfo, it is meant to be per-server, not per-user. Since 24.04.11.

Electronic signature handling

When the ESignatureBaseUrl, ESignatureClientId and ESignatureSecret keys in ServerPrivateInfo are specified, the electronic signing functionality for PDF files gets enabled in Collabora Online’s user interface (the Insert menu has an Electronic signature menu item).

For testing purposes it is OK to use the credentials from eID Easy’s guide. The smart-id-signature provider has test ID-codes on their test user page.

WatermarkText

If set to a non-empty string, is used for rendering a watermark-like text on each tile of the document.

Note: It is possible to just hide print, save, export options while still being able to access them from other hosts using PostMessage API.

PostMessage extensions

App_LoadingStatus

Was extended with field ‘Status’ with Document_Loaded value when document was loaded successfully and ‘Failed’ in other case.

PutFile headers

PutFile additionally indicates whether the user has modified the document before the save, or if they just pressed the Save button without any modification. The following header:

X-COOL-WOPI-IsModifiedByUser

will have the value true or false accordingly.

To distinguish auto-save vs. explicit user requests to save, the following header:

X-COOL-WOPI-IsAutosave

will have the value true when the PutFile is triggered by auto-save, and false when triggered by explicit user operation (Save button or menu entry).

When the document gets cleaned up from memory (e.g. when all users disconnect), an automatic save will be triggered. In this case the following header will be set to true:

X-COOL-WOPI-IsExitSave

Detecting external document change

Locking is omitted from our WOPI-like protocol since it goes against common EFSS solutions usage. Instead, Collabora Online uses timestamps to detect document changes.

When the document is updated in your storage while being edited in Collabora Online and there are unsaved changes, we detect it as soon as possible and ask the user if he/she would like to overwrite the changes or reload the new document from the storage.

In case there are no unsaved changes, we reload the new document without asking the user.

To support this feature, the host implementation has to specify LastModifiedTime field in both CheckFileInfo and PutFile calls.

Additionally, hosts must check for a header in PutFile response:

X-COOL-WOPI-Timestamp

This header contains the ISO8601 round-trip formatted time of file’s last modified time in storage, as known by Collabora Online. In case this header is present and its value does not match the file’s modified time in storage, it indicates that document being edited is not the one that is present in the storage.

Hosts should not save the file to storage in such cases and respond with HTTP 409 along with Collabora Online specific status code:

HTTP 409 with JSON
1 {
2     'COOLStatusCode': 1010
3 }

When the user chooses “overwrite” when asked how to resolve the conflict, Collabora Online will attempt one more save operation, but this time it will lack the X-COOL-WOPI-Timestamp header, which means “save regardless of state of the file”.

Checking for available features

With new features, it is important for the integrations to know if the Online they are using is supporting them. For this reason, we have introduced a /hosting/capabilities endpoint that returns a JSON with information about the availability of various features.

Currently the following are present:

  • convert-to: { available: true/false }

    The property available is true when the convert-to functionality is present, and is allowed from the requesting address. Because of that, the endpoint needs to be accessed from the WOPI host for it to return relevant result.

    A common use of the functionality is that WOPI hosts can use it to generate document previews to show in their file list.

  • hasTemplateSource: true/false

    is true when Collabora Online supports the TemplateSource CheckFileInfo property.

  • hasMobileSupport: true/false

    is true when Collabora Online has a good support for the mobile devices and responsive design.

Modifying discovery.xml

The discovery.xml defines which part of Collabora Online can be used for a certain file type and what action should be used.

The following is a snippet from discovery.xml:

...
<app name="writer" favIconUrl="images/x-office-document.svg">
   <action name="view" default="true" ext="sxw"/>
   <action name="edit" default="true" ext="odt"/>
   ...
</app>
...
<app name="draw">
   ...
   <action name="view_comment" ext="pdf"/>
</app>

The supported actions are “edit”, “view” and a special “view_comment”. When the action is “edit”, the document will open for editing. When the action is “view”, the document will open in read-only mode for viewing. When the action is set to “view_comment”, the document will open read-only, but adding or editing comments will still be possible.

The “view_comment” mode is useful for PDF documents, where adding and editing comments is allowed, but otherwise no other editing should be allowed to be performed.

Override CheckFileInfo

DownloadAsPostMessage property of the CheckFileInfo can be overridden. This is controlled by:

<input name="checkfileinfo_override" value="DownloadAsPostMessage=VALUE" type="hidden"/>

during sending the form when the iframe is being set up (similarly as the access_token). The VALUE can be either true or false. This will override DownloadAsPostMessage value from CheckFileInfo response.

Clipboard handling

Allow the clipboard permission query

Chrome implements a JavaScript API to paste from the clipboard without using the keyboard. This relies on cross-origin iframes, which is disabled by default. To enable it in your integration, use a new attribute in the iframe element of your integration:

<iframe allow="clipboard-read *; clipboard-write *"/>

Once this is in place, the user will see a popup to allow access to the clipboard on first use.

Extensions to the HTML clipboard

HTML marker

When Collabora Online puts HTML to the clipboard, it puts a marker into the body, so it can recognize this content comes from itself and this allows performing a better internal copy:

<body>
    <div id="meta-origin" data-coolorigin="...">
        ... original body content ...
    </div>
</body>

With this, the copy of complex content like charts is performed in an improved way (on the same COOL instance or between COOL instances), better than what’s possible via HTML export and HTML import.

Spreadsheet HTML extensions

Specific to spreadsheets, Collabora Online Calc implements the following HTML extensions to maintain better copy & paste when going via HTML:

  • After the own Collabora Online marker, also a <google-sheets-html-origin/> marker is emitted to please Google Sheets.

  • In case the value of a cell is text, and it should not be recognized as a number, that can be signalled explicitly:

<table>
    <tr>
        <td data-sheets-value="{&quot;1&quot;:2,&quot;2&quot;:&quot;01&quot;}">01</td>
    </tr>
</table>

The data-sheets-value attribute on the td element has a JSON value, where the 1 key is set to 2 to say the type is text, and the 2 key contains the 01 text which won’t be auto-converted to 1 on import.

  • In case the value of a cell is boolean, the markup for that is:

<table>
    <tr>
        <td data-sheets-value="{&quot;1&quot;:4,&quot;4&quot;:1}">WAHR</td>
    </tr>
</table>

The data-sheets-value attribute on the td element has a JSON value, where the 1 key is set to 4 to say the type is boolean, and the 4 key contains 1, so even a localized TRUE value is recognized on export. 0 can be used to express FALSE.

  • Formatted numbers can have metadata to express their float values:

<table>
    <tr>
        <td data-sheets-value="{&quot;1&quot;:3,&quot;3&quot;:1000}" data-sheets-numberformat="{&quot;1&quot;:2,&quot;2&quot;:&quot;#,##0.00&quot;,&quot;3&quot;:1}">1,000.00</td>
    </tr>
</table>

The data-sheets-value attribute on the td element has a JSON value, where the 1 key is set to 3 to say the type is float, and the 3 key contains the original number. Additionally, the data-sheets-numberformat attribute also contains a JSON value. The 1 key is set to 2 to describe a number format, the 2 key contains the actual number format.

This allows copying not only the formatted number, but also the generator float value and its number format.

  • In case the float number of a cell is a result of a formula, the original formula can be also described:

<table>
    <tr>
        <td data-sheets-value="{&quot;1&quot;:3,&quot;3&quot;:1}">1</td>
        <td data-sheets-value="{&quot;1&quot;:3,&quot;3&quot;:2}">2</td>
        <td data-sheets-value="{&quot;1&quot;:3,&quot;3&quot;:3}" data-sheets-formula="=SUM(R[0]C[-2]:R[0]C[-1])">3</td>
    </tr>
</table>

The data-sheets-formula attribute on the td element contains the formula, grammar is R1C1 reference style.

  • In case one or multiple cells are copied, then one table element, one or more tr elements and one or more td elements are to be used. If a single cell is copied, then the above data-* attributes can be also emitted on a span element:

<span data-sheets-value="{&quot;1&quot;:3,&quot;3&quot;:3}" data-sheets-formula="=SUM(R[0]C[-2]:R[0]C[-1])">3</span>

This <span> syntax is read, but not written by Collabora Online.

Google Sheets seems to not publish a specification for their HTML extensions. We figured out, that the markup is something like the above. Comments regarding this markup are welcome on the devel@documentliberation.org mailing list.

URL query parameters

Some additional options can be passed using URL query parameters.

Those suported are:

  • closebutton: allows to display a close button, that will emit the UI_Close message on the postMessage API, with the parameter EverModified, telling if the file had any modification. Example: &closebutton=true

  • revisionhistory: allows to display the See history option in the File tab or File menu. This button, when clicked, emits the UI_FileVersions message on the postMessage API. Example: &revisionhistory=true

  • target: allows to focus a section in the document opened upon loading. Example: &target=image6.png|graphic

  • timestamp: allows to pass in the modification time of the document as a Unix timestamp that will be passed to the server.

  • startPresentation: in Impress, allows to start in presentation mode. Due to browser restriction, this can only render in the current tab rather than in fullscreen. Example: &startPresentation=true. ppsx or pps files load by default with this mode, this can be disabled with &startPresentation=false. Since 24.04.

And some debug and testing utilities:

  • lang: allows to manually overwrite the language. Example &lang=ar or &lang=fr

  • permission: allows to load a document in readonly mode. Example: &permission=readonly

  • debug: enables debug mode, displaying controls useful to debug Collabora Online. Example: &debug=true, there is a shortcut Ctrl+Shift+Alt+D.

  • randomUser: enables debug mode and loads a random language. Example: &randomUser=true

WOPI proof

When processing WOPI requests from Collabora Online, sometimes it is desirable to verify that these requests are actually coming from the expected Collabora Online server. A common use case is when the access to a document is restricted, for example download is forbidden. If someone knows the WOPISrc and the access token, it is enough to get the whole file data, circumventing the protection. You can block WOPI-like protocol at the firewall, or IP filter on source in your server implementation, but the best practice is to use WOPI proof.

When the WOPI proof keypair is present in configuration, Collabora Online signs every WOPI request with the private key. The corresponding public key can be found in the proof-key element of the WOPI discovery XML. Each request includes the signature in the X-WOPI-Proof and X-WOPI-ProofOld HTTP headers.

The WOPI proof keypair is automatically generated when Collabora Online is installed from rpm or deb packages. In case of docker, the WOPI proof keypair is not part of the docker image, for obvious reasons. The docker image is public and giving away a pair of keys that anyone can have access to is not smart. In the docker case the WOPI proof keypair has to be generated and added as a volume to the container.

To generate WOPI proof keypair use the following command:

sudo coolconfig generate-proof-key

or if your configuration directory is not /etc, you can run ssh-keygen manually:

ssh-keygen -t rsa -N "" -m PEM -f /some/path/proof_key

Note: the proof_key file must be readable by the coolwsd process.