https://oxpedia.org/wiki/api.php?action=feedcontributions&user=Viktor.Pracht&feedformat=atomOpen-Xchange - User contributions [en]2024-03-29T11:42:30ZUser contributionsMediaWiki 1.31.0https://oxpedia.org/wiki/index.php?title=AppSuite:Running_a_cluster&diff=22782AppSuite:Running a cluster2016-12-09T14:07:41Z<p>Viktor.Pracht: /* Other Considerations */ Added a link to "Updating UI plugins"</p>
<hr />
<div><div class="title">Running a cluster</div><br />
<br />
__TOC__<br />
<br />
= Concepts =<br />
<br />
For inter-OX-communication over the network, multiple Open-Xchange servers can form a cluster. This brings different advantages regarding distribution and caching of volatile data, load balancing, scalability, fail-safety and robustness. Additionally, it provides the infrastructure for upcoming features of the Open-Xchange server. <br />
The clustering capabilities of the Open-Xchange server are mainly built up on [http://hazelcast.com Hazelcast], an open source clustering and highly scalable data distribution platform for Java. The following article provides an overview about the current featureset and configuration options.<br />
<br />
= Requirements =<br />
<br />
== Synchronized system clock times ==<br />
It is crucial that all involved members in a cluster do have their system clock times in sync with each other; e.g. by using an NTP service.<br />
<br />
== HTTP routing ==<br />
An OX cluster is always part of a larger picture. Usually there is front level loadbalancer as central HTTPS entry point to the platform. This loadbalancer optionally performs HTTPS termination and forwards HTTP(S) requests to webservers (the usual and only supported choice as of now is Apache). These webservers are performing HTTPS termination (if this is not happening on the loadbalancer) and serve static content, and (which is what is relevant for our discussion here) they forward dynamic requests to the OX backends.<br />
<br />
A central requirement for the interaction of these components (loadbalancer, webservers, OX nodes) is that we have session stability based on the JSESSIONID cookie / jsessionid path component suffix. This means that our application sets a cookie named JSESSIONID which has a value like <large decimal number>.<route identifier>, e.g. "5661584529655240315.OX1". The route identifier here ("OX1" in this example) is taken by the OX node from a configuration setting from a config file and is specific to one OX node. HTTP routing must happen such that HTTP requests with a cookie with such a suffix always end up the corresponding OX node. There are furthermore specific cirumstances when passing this information via cookie is not possible. Then the JSESSIONID is transferred in a path component as "jsessionid=..." in the HTTP request. The routing mechanism needs to take that into account also.<br />
<br />
There are mainly two options to implement this. If the Apache processes are running co-located on the same machines running the OX groupware processes, it is often desired to have the front level loadbalancer perform HTTP routing to the correct machines. If dedicated Apache nodes are employed, is is usually sufficient to have the front-level loadbalancer do HTTP routing to the Apache nodes in a round-robin fashion and perform routing to the correct OX nodes in the Apache nodes.<br />
<br />
We provide sample configuration files to configure Apache (with mod_proxy_http) to perform HTTP routing correctly in our guides on OXpedia, e.g. [[AppSuite:Main_Page_AppSuite#quickinstall]]. Central elements are the directives "ProxySet stickysession=JSESSIONID|jsessionid scolonpathdelim=On" in conjunction with the "route=OX1" parameters to the BalancerMember lines in the Proxy definition. This is valid for Apache 2.2 as of Sep-2014.<br />
<br />
How to configure a front level loadbalancer to perform HTTP equivalent HTTP routing is dependent on the specific loadbalancer implementation. If Apache is used as front level loadbalancer, the same configuration as discussed in the previous section can be employed. As of time of writing this text (Sep 2014), the alternative choices are thin. F5 BigIP is reported to be able to implement "jsessionid based persistence using iRules". nginx has the functionality in their commercial "nginx plus" product. (Both of these options have not been tested by OX.) Other loadbalancers with this functionality are not known to us.<br />
<br />
If the front level loadbalancer is not capable of performing correct HTTP routing, is is required to configure correct HTTP routing on Apache level, even if Apache runs co-located on the OX nodes and thus cross-routing happens.<br />
<br />
There are several reasons why we require session stability in exactly this way. We require session stabilty for horizontal scale-out; while we support transparent resuming / migration of user sessions in the OX cluster without need for users to re-authenticate, sessions wandering around randomly will consume a fixed amount resources corresponding to a running session on each OX node in the cluster, while a session sticky to one OX node will consume this fixed amount of resources only on one OX node. Furthermore there are mechanisms in OX like TokenLogin which work only of all requests beloning to one sequence get routed to the same OX node even if they stem from different machines with different IPs. Only the JSESSIONID (which in this case is transferred as jsessionid path component, as cookies do not work during a 302 redirect, which is part of this sequence) carries the required information where the request must be routed to.<br />
<br />
Usual "routing based on cookie hash" is not sufficient here since it disregards the information which machine originally issued the cookie. It only ensures that the session will be sticky to any target, which statistically will not be the same machine that issued the cookie. OX will then set a new JSESSIONID cookie, assuming the session had been migrated. The loadbalancer will then route the session to a different target, as the hash of the cookie will differ. This procedure then happens iteratively until by chance the routing based on cookie hash will route the session to the correct target. By then, a lot of resources will have been wasted, by creating full (short-term) sessions on all OX nodes. Furthermore, processes like TokenLogin will not work this way.<br />
<br />
= Configuration =<br />
<br />
All settings regarding cluster setup are located in the configuration file ''hazelcast.properties''. The former used additional files ''cluster.properties'', ''mdns.properties'' and ''static-cluster-discovery.properties'' are no longer needed. The following gives an overview about the most important settings - please refer to the inline documentation of the configuration file for more advanced options.<br />
<br />
Note: The configuration guide targets v7.4.0 of the OX server (and above). For older versions, please consult the history of this page.<br />
<br />
== General ==<br />
<br />
To restrict access to the cluster and to separate the cluster from others in the local network, a name and password needs to be defined. Only backend nodes having the same values for those properties are able to join and form a cluster. <br />
<br />
# Configures the name of the cluster. Only nodes using the same group name <br />
# will join each other and form the cluster. Required if <br />
# "com.openexchange.hazelcast.network.join" is not "empty" (see below).<br />
com.openexchange.hazelcast.group.name=<br />
<br />
# The password used when joining the cluster. Defaults to "wtV6$VQk8#+3ds!a". <br />
# Please change this value, and ensure it's equal on all nodes in the cluster.<br />
com.openexchange.hazelcast.group.password=wtV6$VQk8#+3ds!a<br />
<br />
== Network ==<br />
<br />
It's required to define the network interface that is used for cluster communication via ''com.openexchange.hazelcast.network.interfaces''. By default, the interface is restricted to the local loopback address only. To allow the same configuration amongst all nodes in the cluster, it's recommended to define the value using a wildcard matching the IP addresses of all nodes participating in the cluster, e.g. ''192.168.0.*''<br />
<br />
# Comma-separated list of interface addresses hazelcast should use. Wildcards <br />
# (*) and ranges (-) can be used. Leave blank to listen on all interfaces<br />
# Especially in server environments with multiple network interfaces, it's <br />
# recommended to specify the IP-address of the network interface to bind to <br />
# explicitly. Defaults to "127.0.0.1" (local loopback only), needs to be <br />
# adjusted when building a cluster of multiple backend nodes.<br />
com.openexchange.hazelcast.network.interfaces=127.0.0.1<br />
<br />
To form a cluster of multiple OX server nodes, different discovery mechanisms can be used. The discovery mechanism is specified via the property ''com.openexchange.hazelcast.network.join'':<br />
<br />
# Specifies which mechanism is used to discover other backend nodes in the <br />
# cluster. Possible values are "empty" (no discovery for single-node setups),<br />
# "static" (fixed set of cluster member nodes) or "multicast" (automatic <br />
# discovery of other nodes via multicast). Defaults to "empty". Depending on <br />
# the specified value, further configuration might be needed, see "Networking"<br />
# section below. <br />
com.openexchange.hazelcast.network.join=empty<br />
<br />
Generally, it's advised to use the same network join mechanism for all nodes in the cluster, and, in most cases, it's strongly recommended to use a ''static'' network join configuration. This will allow the nodes to join the cluster directly upon startup. With a ''multicast'' based setup, nodes will merge to an existing cluster possibly at some later time, thus not being able to access the distributed data until they've joined.<br />
<br />
Depending on the network join setting, further configuration may be necessary, as decribed in the following paragraphs.<br />
<br />
=== empty ===<br />
<br />
When using the default value ''empty'', no other nodes are discovered in the cluster. This value is suitable for single-node installations. Note that other nodes that are configured to use other network join mechanisms may be still able to still to connect to this node, e.g. using a ''static'' network join, having the IP address of this host in the list of potential cluster members (see below).<br />
<br />
=== static ===<br />
<br />
The most common setting for ''com.openexchange.hazelcast.network.join'' is ''static''. A static cluster discovery uses a fixed list of IP addresses of the nodes in the cluster. During startup and after a specific interval, the underlying Hazelcast library probes for not yet joined nodes from this list and adds them to the cluster automatically. The address list is configured via ''com.openexchange.hazelcast.network.join.static.nodes'':<br />
<br />
# Configures a comma-separated list of IP addresses / hostnames of possible <br />
# nodes in the cluster, e.g. "10.20.30.12, 10.20.30.13:5701, 192.178.168.110".<br />
# Only used if "com.openexchange.hazelcast.network.join" is set to "static". <br />
# It doesn't hurt if the address of the local host appears in the list, so <br />
# that it's still possible to use the same list throughout all nodes in the <br />
# cluster.<br />
com.openexchange.hazelcast.network.join.static.nodes=<br />
<br />
For a fixed set of backend nodes, it's recommended to simply include the IP addresses of all nodes in the list, and use the same configuration for each node. However, it's only required to add the address of at least one other node in the cluster to allow the node to join the cluster. Also, when adding a new node to the cluster and this list is extended accordingly, existing nodes don't need to be shut down to recognize the new node, as long as the new node's address list contains at least one of the already running nodes. <br />
<br />
=== multicast ===<br />
<br />
For highly dynamic setups where nodes are added and removed from the cluster quite often and/or the host's IP addresses are not fixed, it's also possible to configure the network join via multicast. During startup and after a specific interval, the backend nodes initiate the multicast join process automatically, and discovered nodes form or join the cluster afterwards. The multicast group and port can be configured as follows:<br />
<br />
# Configures the multicast address used to discover other nodes in the cluster<br />
# dynamically. Only used if "com.openexchange.hazelcast.network.join" is set <br />
# to "multicast". If the nodes reside in different subnets, please ensure that <br />
# multicast is enabled between the subnets. Defaults to "224.2.2.3". <br />
com.openexchange.hazelcast.network.join.multicast.group=224.2.2.3<br />
<br />
# Configures the multicast port used to discover other nodes in the cluster<br />
# dynamically. Only used if "com.openexchange.hazelcast.network.join" is set <br />
# to "multicast". Defaults to "54327". <br />
com.openexchange.hazelcast.network.join.multicast.port=54327<br />
<br />
== Example ==<br />
<br />
The following example shows how a simple cluster named ''MyCluster'' consisting of 4 backend nodes can be configured using ''static'' cluster discovery. The node's IP addresses are 10.0.0.15, 10.0.0.16, 10.0.0.17 and 10.0.0.18. Note that the same ''hazelcast.properties'' is used by all nodes.<br />
<br />
com.openexchange.hazelcast.group.name=MyCluster<br />
com.openexchange.hazelcast.group.password=secret<br />
com.openexchange.hazelcast.network.join=static<br />
com.openexchange.hazelcast.network.join.static.nodes=10.0.0.15,10.0.0.16,10.0.0.17,10.0.0.18<br />
com.openexchange.hazelcast.network.interfaces=10.0.0.*<br />
<br />
<br />
== Advanced Configuration ==<br />
<br />
=== Custom Partitioning (preliminary) ===<br />
<br />
While originally being desgined to separate the nodes holding distributed data into different risk groups for increased fail safety, a custom partioning strategy may also be used to distinguish between nodes holding distributed data from those who should not. <br />
<br />
This approach of custom partitioning may be used in a OX cluster, where usually different backend nodes serve different purposes. A common scenario is that there are nodes handling requests from the web interfaces, and others being responsible for USM/EAS traffic. Due to their nature of processing large chunks of synchronization data in memory, the USM/EAS nodes may encounter small delays when the Java garbage collector kicks in and suspends the Java Virtual Machine. Since those delays may also have an influence on hazelcast-based communication in the cluster, the idea is to instruct hazelcast to not store distributed data on that nodes. This is where a custom partitioning scheme comes into play.<br />
<br />
To setup a custom paritioning scheme in the cluster, an additional ''hazelcast.xml'' configuration file is used, which should be placed into the ''hazelcast'' subdirectory of the OX configuration folder, usually at ''/opt/openexchange/etc/hazelcast''. Please note that it's vital that each node in the cluster is configured equally here, so the same ''hazelcast.xml'' file should be copied to each server. The configuration read from there is used as basis for all further settings that are taken from the ordinary ''hazelcast.properties'' config file. <br />
<br />
To setup a custom paritioning scheme, the partition groups must be defined in the ''hazelcast.xml'' file. See the following file for an example configuration, where the three nodes ''10.10.10.60'', ''10.10.10.61'' and ''10.10.10.62'' are defined to form an own paritioning group each. Doing so, all distributed data will be stored at one of those nodes physically, while the corresponding backup data (if configured) at one of the other two nodes. All other nodes in the cluster will not be used to store distributed data, but will still be "full" hazelcast members, which is necessary for other cluster-wide operations the OX backends use. <br />
<br />
Please note that the configured backup count in the map configurations should be smaller than the number of nodes here, otherwise, there may be problems if one of those data nodes is shut down temporarily for maintenance. So, the minimum number of nodes to define in the partition group sections is implicitly bound to the sum of a map's ''backupCount'' and ''asyncBackupCount'' properties, plus ''1'' for the original data partition. <br />
<br />
<br />
<?xml version="1.0" encoding="UTF-8"?><br />
<!--<br />
~ Copyright (c) 2008-2013, Hazelcast, Inc. All Rights Reserved.<br />
~<br />
~ Licensed under the Apache License, Version 2.0 (the "License");<br />
~ you may not use this file except in compliance with the License.<br />
~ You may obtain a copy of the License at<br />
~<br />
~ http://www.apache.org/licenses/LICENSE-2.0<br />
~<br />
~ Unless required by applicable law or agreed to in writing, software<br />
~ distributed under the License is distributed on an "AS IS" BASIS,<br />
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.<br />
~ See the License for the specific language governing permissions and<br />
~ limitations under the License.<br />
--><br />
<br />
<hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.1.xsd"<br />
xmlns="http://www.hazelcast.com/schema/config"<br />
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><br />
<partition-group enabled="true" group-type="CUSTOM"><br />
<member-group><br />
<interface>10.10.10.60</interface><br />
</member-group><br />
<member-group><br />
<interface>10.10.10.61</interface><br />
</member-group><br />
<member-group><br />
<interface>10.10.10.62</interface><br />
</member-group><br />
</partition-group><br />
</hazelcast><br />
<br />
More general information regarding custom partioning is available at http://hazelcast.org/docs/latest/manual/html/partitiongroupconfig.html . <br />
<br />
It's also recommended to use a "static" cluster discovery for the network join, and list same the nodes that are also configured in the parition groups here, so that join requests are handled by those nodes, too (and not the other nodes that are potentially prone to garbage collection delays. <br />
<br />
After configuring a custom paritioning scheme, the data distribution may be verified, e.g. by inspecting the MBeans of the distributed maps via JMX.<br />
<br />
= Features =<br />
<br />
The following list gives an overview about different features that were implemented using the new cluster capabilities.<br />
<br />
== Distributed Session Storage ==<br />
<br />
Previously, when an Open-Xchange server was shutdown for maintenance, all user sessions that were bound to that machine were lost, i.e. the users needed to login again. With the distributed session storage, all sessions are backed by a distributed map in the cluster, so that they are no longer bound to a specific node in the cluster. When a node is shut down, the session data is still available in the cluster and can be accessed from the remaining nodes. The load-balancing techniques of the webserver then seamlessly routes the user session to another node, with no ''session expired'' errors. The distributed session storage comes with the package ''open-xchange-sessionstorage-hazelcast''. It's recommended to install this optional package in all clustered environments with multiple groupware server nodes.<br />
<br />
'''Notes:''' <br />
* While there's some kind of built-in session distribution among the nodes in the cluster, this should not be seen as a replacement for session-stickiness between the loadbalancer and groupware nodes, i.e. one should still configure the webserver to use sticky sessions for performance reasons.<br />
* The distributed session storage is still an in-memory storage. While the session data is distributed and backed up on multiple nodes in the cluster, shutting down multiple or all nodes at the same time will lead to loss of the the distributed data. To avoid such data loss when shutting down a node, please follow the guidelines at [[ Updating_a_Cluster ]].<br />
<br />
Depending on the cluster infrastructure, different backup-count configuration options might be set for the distributed session storage in the map configuration file ''sessions.properties'' in the ''hazelcast'' subdirectory:<br />
<br />
com.openexchange.hazelcast.configuration.map.backupCount=1<br />
<br />
The ''backupcount'' property configures the number of nodes with synchronized backups. Synchronized backups block operations until backups are successfully copied and acknowledgements are received. If 1 is set as the backup-count for example, then all entries of the map will be copied to another JVM for fail-safety. 0 means no backup. Any integer between 0 and 6. Default is 1, setting bigger than 6 has no effect.<br />
<br />
com.openexchange.hazelcast.configuration.map.asyncBackupCount=0<br />
<br />
The ''asyncbackup'' property configures the number of nodes with async backups. Async backups do not block operations and do not require acknowledgements. 0 means no backup. Any integer between 0 and 6. Default is 0, setting bigger than 6 has no effect.<br />
<br />
Since session data is backed up by default continously by multiple nodes in the cluster, the steps described in [[ Session_Migration ]] to trigger session mirgration to other nodes explicitly is obsolete and no longer needed with the distributed session storage.<br />
<br />
Normally, sessions in the distributed storages are not evicted automatically, but are only removed when they're also removed from the session handler, either due to a logout operation or when exceeding the long-term session lifetime as configured by ''com.openexchange.sessiond.sessionLongLifeTime'' in ''sessiond.properties''. Under certain circumstances, i.e. the session is no longer accessed by the client and the OX node hosting the session in it's long-life container being shutdown, the remove operation from the distributed storage might not be triggered. Therefore, additionaly a maximum idle time of map-entries can be configured for the distributed sessions map via <br />
<br />
com.openexchange.hazelcast.configuration.map.maxIdleSeconds=640000<br />
<br />
To avoid unnecessary eviction, the value should be higher than the configured ''com.openexchange.sessiond.sessionLongLifeTime'' in ''sessiond.properties''.<br />
<br />
== Remote Cache Invalidation ==<br />
<br />
For faster access, groupware data is held in different caches by the server. Formerly, the caches utilized the TCP Lateral Auxiliary Cache plug in (LTCP) for the underlying JCS caches to broadcast updates and removals to caches on other OX nodes in the cluster. This could potentially lead to problems when remote invalidation was not working reliably due to network discovery problems. As an alternative, remote cache invalidation can also be performed using reliable publish/subscribe events built up on Hazelcast topics. This can be configured in the ''cache.properties'' configuration file, where the 'eventInvalidation' property can either be set to 'false' for the legacy behavior or 'true' for the new mechanism:<br />
<br />
com.openexchange.caching.jcs.eventInvalidation=true<br />
<br />
All nodes participating in the cluster should be configured equally.<br />
<br />
Internally, if ''com.openexchange.caching.jcs.eventInvalidation'' is set to ''true'', LTCP is disabled in JCS caches. Instead, an internal mechanism based on distributed Hazelcast event topics is used to invalidate data throughout all nodes in the cluster after local update- and remove-operations. Put-operations aren't propagated (and haven't been with LTCP either), since all data put into caches can be locally loaded/evaluated at each node from the persistent storage layer.<br />
<br />
Using Hazelcast-based cache invalidation also makes further configuration of the JCS auxiliaries obsolete in the ''cache.ccf'' configuration file. In that case, all ''jcs.auxiliary.LTCP.*'' configuration settings are virtually ignored. However, it's still required to mark caches that require cluster-wide invalidation via ''jcs.region.<cache_name>=LTCP'', just as before. So basically, when using the new default setting ''com.openexchange.caching.jcs.eventInvalidation=true'', it's recommended to just use the stock ''cache.ccf'' file, since no further LTCP configuration is required.<br />
<br />
<br />
= Adminstration / Troubleshooting =<br />
<br />
== Hazelcast Configuration ==<br />
<br />
The underlying Hazelcast library can be configured using the file ''hazelcast.properties''.<br />
<br />
'''Important''':<br><br />
By default property ''com.openexchange.hazelcast.network.interfaces'' is set to ''127.0.0.1''; meaning Hazelcast listens only to loop-back device. To build a cluster among remote nodes the appropriate network interface needs to be configured there. Leaving that property empty lets Hazelcast listen to all available network interfaces.<br />
<br />
The Hazelcast JMX MBean can be enabled or disabled with the property ''com.openexchange.hazelcast.jmx''. The properties ''com.openexchange.hazelcast.mergeFirstRunDelay'' and ''com.openexchange.hazelcast.mergeRunDelay'' control the run intervals of the so-called ''Split Brain Handler'' of Hazelcast that initiates the cluster join process when a new node is started. More details can be found at http://www.hazelcast.com/docs/2.5/manual/single_html/#NetworkPartitioning. <br />
<br />
The port ranges used by Hazelcast for incoming and outgoing connections can be controlled via the configuration parameters ''com.openexchange.hazelcast.networkConfig.port'', ''com.openexchange.hazelcast.networkConfig.portAutoIncrement'' and ''com.openexchange.hazelcast.networkConfig.outboundPortDefinitions''.<br />
<br />
== Commandline Tool ==<br />
<br />
To print out statistics about the cluster and the distributed data, the ''showruntimestats'' commandline tool can be executed witht the ''clusterstats'' ('c') argument. This provides an overview about the runtime cluster configuration of the node, other members in the cluster and distributed data structures.<br />
<br />
== JMX ==<br />
<br />
In the Open-Xchange server Java process, the MBean ''com.hazelcast'' can be used to monitor and manage different aspects of the underlying Hazelcast cluster. The ''com.hazelcast'' MBean provides detailed information about the cluster configuration and distributed data structures.<br />
<br />
== Hazelcast Errors ==<br />
<br />
When experiencing hazelcast related errors in the logfiles, most likely different versions of the packages are installed, leading to different message formats that can't be understood by nodes using another version. Examples for such errors are exceptions in hazelcast components regarding (de)serialization or other message processing.<br />
This may happen when performing a consecutive update of all nodes in the cluster, where temporarily nodes with a heterogeneous setup try to communicate with each other. If the errors don't disappear after all nodes in the cluster have been update to the same package versions, it might be necessary to shutdown the cluster completely, so that all distributed data is cleared.<br />
<br />
== Cluster Discovery Errors ==<br />
<br />
* If the started OX nodes don't form a cluster, please double-check your configuration in ''hazelcast.properties''<br />
* It's important to have the same cluster name defined in ''hazelcast.properties'' throughout all nodes in the cluster<br />
* Especially when using multicast cluster discovery, it might take some time until the cluster is formed<br />
* When using ''static'' cluster discovery, at least one other node in the cluster has to be configured in ''com.openexchange.hazelcast.network.join.static.nodes'' to allow joining, however, it's recommended to list all nodes in the cluster here<br />
<br />
== Disable Cluster Features ==<br />
<br />
The Hazelcast based clustering features can be disabled with the following property changes:<br />
* Disable cluster discovery by setting ''com.openexchange.hazelcast.network.join'' to ''empty'' in ''hazelcast.properties''<br />
* Disable Hazelcast by setting ''com.openexchange.hazelcast.enabled'' to false in ''hazelcast.properties''<br />
* Disable message based cache event invalidation by setting ''com.openexchange.caching.jcs.eventInvalidation'' to ''false'' in ''cache.properties''<br />
<br />
== Update from 6.22.1 to version 6.22.2 and above ==<br />
<br />
As hazelcast will be used by default for the distribution of sessions starting 6.22.2 you have to adjust hazelcast according to our old cache configuration. First of all it's important that you install the open-xchange-sessionstorage-hazelcast package. This package will add the binding between hazelcast and the internal session management. Next you have to set a cluster name to the cluster.properties file (see [[#Cluster Discovery Errors]]). Furthermore you will have to add one of the two discovery modes mentioned in [[#Cluster Discovery]].<br />
<br />
<br />
= Updating a Cluster =<br />
<br />
Running a cluster means built-in failover on the one hand, but might require some attention when it comes to the point of upgrading the services on all nodes in the cluster. This chapter gives an overview about general concepts and hints for silent updates of the cluster.<br />
<br />
== Limitations ==<br />
<br />
While in most cases a seamless, rolling upgrade of all nodes in the cluster is possible, there may be situations where nodes running a newer version of the Open-Xchange Server are not able to communicate with older nodes in the cluster, i.e. can't access distributed data or consume incompatible event notifications - especially, when the underlying Hazelcast library is part of the update, which does not support this scenario at the moment. In such cases, the release notes will contain corresponding information, so please have a look there before applying an update.<br />
<br />
Additionally, there may always be some kind of race conditions during an update, i.e. client requests that can't be completed successfully or internal events not being deliverd to all nodes in the cluster. That's why the following information should only serve as a best-practices guide to minimize the impact of upgrades to the user experience.<br />
<br />
== Upgrading a single Node ==<br />
<br />
Upgrading all nodes in the cluster should usually be done sequentially, i.o.w. one node after the other. This means that during the upgrade of one node, the node is temporarily disconnected from the other nodes in the cluster, and will join the cluster again after the update is completed. From the backend perspective, this is as easy as stopping the open-xchange service. other nodes in the cluster will recognize the disconnected node and start to repartition the shared cluster data automatically. But wait a minute - doing so would potentially lead to the webserver not registering the node being stopped immediately, resulting in temporary errors for currently logged in users until they are routed to another machine in the cluster. That's why it's good practice to tell the webserver's load balancer that the node should no longer fulfill incoming requests. The Apache Balancer Manager is an excellent tool for this ([http://httpd.apache.org/docs/2.2/mod/mod_status.html module ''mod_status'']). Look at the screen shot. Every node can be put into a disabled mode. Further requests will the redirected to other nodes in the cluster:<br />
<br />
<br />
[[Image:balancer_manager.jpg]]<br />
<br />
<br />
Afterwards, the open-xchange service on the disabled node can be stopped by executing:<br />
<br />
$ /etc/init.d/open-xchange stop<br />
<br />
or <br />
<br />
$ service open-xchange stop<br />
<br />
Now, the node is effectively in maintenance mode and any updates can take place. One could now verify the changed cluster infrastructure by accessing the Hazelcast MBeans either via JMX or the ''showruntimestats -c'' commandline tool (see above for details). There, the shut down node should no longer appear in the 'Member' section (com.hazelcast:type=Member).<br />
<br />
When all upgrades are processed, the node open-xchange service can be started again by executing:<br />
<br />
$ /etc/init.d/open-xchange start<br />
<br />
or <br />
<br />
$ service open-xchange start<br />
<br />
As stated above, depending on the chosen cluster discovery mechanism, it might take some time until the node joins the cluster again. When using static cluster discovery, it will join the existing cluster usually directly during serivce startup, i.o.w. before other depending OSGi services are started. Otherwise, there might also be situations where the node cannot join the cluster directly, for example when there were no mDNS advertisments for other nodes in the cluster received yet. Then, it can take some additional time until the node finally joins the cluster. During startup of the node, you can observe the JMX console or the output of ''showruntimestats -c'' (com.hazelcast:type=Member) of another node in the cluster to verify when the node has joined. <br />
<br />
After the node has joined, distributed data is re-partioned automatically, and the node is ready to server incoming requests again - so now the node can finally be enabled again in the load balancer configuration of the webserver. Afterwards, the next node in the cluster can be upgraded using the same procedure, until all nodes were processed.<br />
<br />
== Upgrades of the Hazelcast library ==<br />
<br />
In case an upgrade includes a major update of the Hazelcast library, a newly upgraded node will usually not be able to connect to the nodes running the previous version. In this case, volatile cluster data is lost after all nodes in the cluster have been updated, including sessions held in the distributed session storage. As outlined above, the release notes will contain a corresponding warning in such cases.<br />
<br />
Besides upgraded nodes not being able to access distributed data of the legacy cluster, this also affects new data not being available in the legacy cluster, which may cause troubles if the updated backend version needs to perform database update tasks. Database update tasks usually operate in a "blocking" way and all contexts associated with the schema being upgraded are disabled temporarily. Since context data itself is being held in caches on potentially each node in the cluster, the affected cache entries are invalidated during the database update. And, since cluster-wide cache invalidations again utilize Hazelcast functionality ([[#Remote Cache Invalidation]]), such invalidations normally won't be propagated to nodes running a previous version of the Hazelcast library.<br />
<br />
To work around this specific scenario where an incompatible upgrade of the Hazelcast library needs to be performed along with blocking database update tasks, starting with v7.8.0, a supplementary package is available that explicitly enables the context cache invalidation of nodes running the previous Hazelcast library. This package follows the naming scheme ''open-xchange-cluster-upgrade-from-XXX'' (where XXX representing the version of the legacy version of the Open-Xchange server), and is available in the repositories for the updated server packages. This package should only be installed on the first node of the cluster that is going to be upgraded to the new version, and can be deactivated once the database upgrade tasks were executed successfully. <br />
<br />
Once installed, a legacy cluster is discovered based on the available information in the ''hazelcast.properties'' configuration file in case cluster discovery is set to ''static''. If ''multicast'' is used, there's an alternative option to configure at least one of the addresses of the legacy cluster via ''com.openexchange.hazelcast.network.client.nodes''.<br />
<br />
As an example, along with the server v7.8.0, a new package named ''open-xchange-cluster-upgrade-from-76x'' can be installed that aids in invalidating cluster server nodes running v7.6.x (which includes the Hazelcast library in version 3.2.4). Using this package, the recommended steps to update an OX cluster from version 7.6.x to version 7.8.0 would be:<br />
# Pick a node from your cluster that you want to use for executing the database update tasks shipped with the new release<br />
# Disable this node for incoming HTTP requests in your webserver configuration as described at [[#Upgrading a single Node]]<br />
# Update the OX packages on this node, additionally install the package ''open-xchange-cluster-upgrade-from-76x''<br />
# Restart the open-xchange services on this node<br />
# Trigger the update task executions using the ''runUpdate'' commandline utitlty as described at [[UpdateTasks]]<br />
# Once they are finished, uninstall the package ''open-xchange-cluster-upgrade-from-76x'' again<br />
# Restart the open-xchange services on this node<br />
# Re-enable the node for incoming HTTP requests in your webserver configuration as described at [[#Upgrading a single Node]]<br />
# Upgrade all other nodes in the cluster as described at [[#Upgrading a single Node]]<br />
<br />
Same steps apply to upgrading from v7.8.0 through v7.8.2 (incl.) to v7.8.3 using the package named ''open-xchange-cluster-upgrade-from-780-782'', since v7.8.0 through v7.8.2 (incl.) utilize Hazelcast v3.5.x, while v7.8.3 uses Hazelcast v3.6.4<br />
<br />
== Other Considerations ==<br />
<br />
* It's always recommended to only upgrade one node after the other, always ensuring that the cluster has formed correctly between each shutdown/startup of a node.<br />
* Do not stop a node while running the runUpdate script or the associated update task.<br />
* During the time of such a rolling upgrade of all nodes, we have effectively heterogeneous software versions in the cluster, which potentially might lead to temporary inconsistencies. Therefore, all nodes in the cluster should be updated in one cycle (but still one after the other).<br />
* Following the above guideline, it's also possible to add or remove nodes dynamically to the cluster, not only when disconnecting a node temporary for updates.<br />
* In case of trouble, i.e. a node refuses to join the cluster again after restart, consult the logfiles first for any hints about what is causing the problem - both on the disconnected node, and also on other nodes in the network<br />
* If there are general incompatibilities between two revisions of the Open-Xchange Server that prevent an operation in a cluster (release notes), it's recommended to choose another name for the cluster in ''cluster.properties'' for the nodes with the new version. This will temporary lead to two separate clusters during the rolling upgrade, and finally the old cluster being shut down completely after the last node was updated to the new version. While distributed data can't be migrated from one server version to another in this scenario due to incompatibilities, the uptime of the system itself is not affected, since the nodes in the new cluster are able to serve new incoming requests directly.<br />
* When updating only UI plugins without also updating to a new version of the core UI, you also need to perform the additional step from [[AppSuite:UpdatingOXPackages#Updating_UI_plugins|Updating UI plugins]].<br />
<br />
[[Category: AppSuite]] [[Category: Administration]] [[Category: Cluster]]</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:UpdatingOXPackages&diff=22781AppSuite:UpdatingOXPackages2016-12-09T14:01:47Z<p>Viktor.Pracht: /* Updating UI plugins */</p>
<hr />
<div><div class="title">Updating OX App Suite packages</div><br />
<br />
''Synopsys'': This article describes how to update OX App Suite packages from one service pack to another.<br />
<br />
== Warnings ==<br />
<br />
Before we begin, here are several things that you should keep in mind:<br />
* If you are '''updating a cluster, please do it one node after the other'''. Turn the node off, update, turn it on again, make sure it works in the cluster. Have a look here, too: [[Running_a_cluster#Upgrading_a_single_Node|Upgrading a single node]]<br />
* If you don't have a cluster of OX nodes, then your complete installation needs to be taken down temporarily.<br />
* Please '''update the frontend before the backend'''. Otherwise the old frontend won't work with the new backend and it's manifests.<br />
* Please '''do not restart Open-Xchange during the database update'''. A database update can happen after installing minor or major updates. As soon as the first user tries to log in to the system or if any provisioning action is done, this update starts.<br />
<br />
== How to get updates? ==<br />
<br />
OX App Suite updates can be accessed by customers with a valid license.<br />
<br />
In addition, you need to configure the [[OXReportClient]].<br />
<br />
= Updating OX App Suite Packages =<br />
<br />
<br />
== Installing Updates ==<br />
<br />
A new service pack usually introduces new packages and requires configuration changes. To get all required new packages and configuration changes, the following '''must''' be done when installing updates.<br />
<br />
(Please, keep the [[#Warning|warning about frontend updates before backend updates]] in mind)<br />
<br />
=== On Debian based distributions ===<br />
<br />
Add the following entry to <tt>/etc/apt/sources.list.d/open-xchange.list</tt><br />
<br />
deb http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/stable/appsuiteui/updates/DebianJessie/ /<br />
deb http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/stable/backend/updates/DebianJessie /<br />
Then run<br />
<br />
$ apt-get update<br />
$ apt-get dist-upgrade<br />
<br />
If you want to see, what apt-get is going to do without actually doing it, you can run:<br />
<br />
$ apt-get dist-upgrade -s<br />
<br />
After the new packages are installed, the open-xchange process needs a restart:<br />
<br />
<pre>$ /etc/init.d/open-xchange restart</pre><br />
<br />
=== On RPM based distributions ===<br />
<br />
==== RHEL6/CentOS6 ====<br />
<br />
Add the following entries to <tt>/etc/yum.repos.d/ox.repo</tt>:<br />
<br />
[ox-updates-appsuiteui]<br />
name=Open-Xchange Updates<br />
baseurl=http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/stable/appsuiteui/updates/RHEL6/<br />
gpgkey=http://software.open-xchange.com/oxbuildkey.pub<br />
enabled=1<br />
gpgcheck=1<br />
metadata_expire=0m<br />
<br />
[ox-updates-backend]<br />
name=Open-Xchange Updates<br />
baseurl=http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/stable/backend/updates/RHEL6/<br />
gpgkey=http://software.open-xchange.com/oxbuildkey.pub<br />
enabled=1<br />
gpgcheck=1<br />
metadata_expire=0m<br />
<br />
and run<br />
<br />
$ yum update<br />
<br />
$ yum upgrade<br />
<br />
After the new packages are installed, the open-xchange process needs a restart:<br />
<br />
<pre>$ /etc/init.d/open-xchange restart</pre><br />
(Please, keep the [[#Warnings|warning about database updates]] in mind)<br />
<br />
==== RHEL7/CentOS7 ====<br />
<br />
Add the following entries to <tt>/etc/yum.repos.d/ox.repo</tt>:<br />
<br />
[ox-updates-appsuiteui]<br />
name=Open-Xchange Updates<br />
baseurl=http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/stable/appsuiteui/updates/RHEL7/<br />
gpgkey=http://software.open-xchange.com/oxbuildkey.pub<br />
enabled=1<br />
gpgcheck=1<br />
metadata_expire=0m<br />
<br />
[ox-updates-backend]<br />
name=Open-Xchange Updates<br />
baseurl=http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/stable/backend/updates/RHEL7/<br />
gpgkey=http://software.open-xchange.com/oxbuildkey.pub<br />
enabled=1<br />
gpgcheck=1<br />
metadata_expire=0m<br />
<br />
and run<br />
<br />
$ yum update<br />
<br />
$ yum upgrade<br />
<br />
After the new packages are installed, the open-xchange process needs a restart:<br />
<br />
<pre>$ /etc/init.d/open-xchange restart</pre><br />
(Please, keep the [[#Warnings|warning about database updates]] in mind)<br />
<br />
==== SLES12 ====<br />
<br />
Add the updates repository to the repository list:<br />
<br />
$ zypper ar http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/stable/appsuiteui/updates/SLE_12/ OXAPPSUITEUIUPDATES<br />
$ zypper ar http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/stable/backend/updates/SLE_12/ OXBACKENDUPDATES<br />
<br />
and run<br />
<br />
$ zypper dup -r OXAPPSUITEUIUPDATES<br />
$ zypper dup -r OXBACKENDUPDATES<br />
<br />
You might need to run<br />
<br />
$ zypper ref<br />
<br />
to update the repository metadata before running ''zypper up''.<br />
<br />
After the new packages are installed, the open-xchange process needs a restart:<br />
<br />
<pre>$ rcopen-xchange restart</pre><br />
(Please, keep the [[#Warnings|warning about database updates]] in mind.<br />
<br />
= Updating OX App Suite Packages for older versions =<br />
<br />
<br />
== Installing Updates ==<br />
<br />
A new service pack usually introduces new packages and requires configuration changes. To get all required new packages and configuration changes, the following '''must''' be done when installing updates.<br />
<br />
(Please, keep the [[#Warning|warning about frontend updates before backend updates]] in mind)<br />
<br />
=== On Debian based distributions ===<br />
<br />
If you want to update an older version of Open-Xchange App Suite to the latest maintenance release, add the following entry to <tt>/etc/apt/sources.list.d/open-xchange.list</tt>. Replace VERSION with the version you are using (e.g. 7.6.2). See [[AppSuite:Version_Support_Committment]] for the currently supported versions. Also, make sure that your repository configuration points at the versioned base installation repositories (instead of using the <tt>stable</tt> symlink.)<br />
<br />
deb http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/appsuiteui/updates/DebianWheezy/ /<br />
deb http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/backend/updates/DebianWheezy/ /<br />
<br />
deb http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/appsuiteui/updates/DebianJessie/ /<br />
deb http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/backend/updates/DebianJessie /<br />
<br />
Then run<br />
<br />
$ apt-get update<br />
$ apt-get dist-upgrade<br />
<br />
If you want to see, what apt-get is going to do without actually doing it, you can run:<br />
<br />
$ apt-get dist-upgrade -s<br />
<br />
After the new packages are installed, the open-xchange process needs a restart:<br />
<br />
<pre>$ /etc/init.d/open-xchange restart</pre><br />
<br />
=== On RPM based distributions ===<br />
<br />
==== RHEL6/CentOS6 ====<br />
<br />
If you want to update an older version of Open-Xchange App Suite to the latest maintenance release, add the following entry to <tt>/etc/yum.repos.d/ox.repo</tt>. Replace VERSION with the version you are using (e.g. 7.4.2, 7.6.0). See [[AppSuite:Version_Support_Committment]] for the currently supported versions. Also, make sure that your repository configuration points at the versioned base installation repositories (instead of using the <tt>stable</tt> symlink.)<br />
<br />
[ox-updates-appsuiteui]<br />
name=Open-Xchange Updates<br />
baseurl=http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/appsuiteui/updates/RHEL6/<br />
gpgkey=http://software.open-xchange.com/oxbuildkey.pub<br />
enabled=1<br />
gpgcheck=1<br />
metadata_expire=0m<br />
<br />
[ox-updates-backend]<br />
name=Open-Xchange Updates<br />
baseurl=http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/backend/updates/RHEL6/<br />
gpgkey=http://software.open-xchange.com/oxbuildkey.pub<br />
enabled=1<br />
gpgcheck=1<br />
metadata_expire=0m<br />
<br />
and run<br />
<br />
$ yum update<br />
<br />
$ yum upgrade<br />
<br />
After the new packages are installed, the open-xchange process needs a restart:<br />
<br />
<pre>$ /etc/init.d/open-xchange restart</pre><br />
(Please, keep the [[#Warnings|warning about database updates]] in mind)<br />
<br />
==== RHEL7/CentOS7 ====<br />
<br />
If you want to update an older version of Open-Xchange App Suite to the latest maintenance release, add the following entry to <tt>/etc/yum.repos.d/ox.repo</tt>. Replace VERSION with the version you are using (e.g. 7.4.2, 7.6.0). See [[AppSuite:Version_Support_Committment]] for the currently supported versions. Also, make sure that your repository configuration points at the versioned base installation repositories (instead of using the <tt>stable</tt> symlink.)<br />
<br />
[ox-updates-appsuiteui]<br />
name=Open-Xchange Updates<br />
baseurl=http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/appsuiteui/updates/RHEL7/<br />
gpgkey=http://software.open-xchange.com/oxbuildkey.pub<br />
enabled=1<br />
gpgcheck=1<br />
metadata_expire=0m<br />
<br />
[ox-updates-backend]<br />
name=Open-Xchange Updates<br />
baseurl=http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/backend/updates/RHEL7/<br />
gpgkey=http://software.open-xchange.com/oxbuildkey.pub<br />
enabled=1<br />
gpgcheck=1<br />
metadata_expire=0m<br />
<br />
and run<br />
<br />
$ yum update<br />
<br />
$ yum upgrade<br />
<br />
After the new packages are installed, the open-xchange process needs a restart:<br />
<br />
<pre>$ /etc/init.d/open-xchange restart</pre><br />
(Please, keep the [[#Warnings|warning about database updates]] in mind)<br />
<br />
==== SLES 11 ====<br />
<br />
If you want to update an older version of Open-Xchange App Suite to the latest maintenance release, add the following entry to the repository list. Replace VERSION with the version you are using (e.g. 7.4.2, 7.6.0). See [[AppSuite:Version_Support_Committment]] for the currently supported versions. Also, make sure that your repository configuration points at the versioned base installation repositories (instead of using the <tt>stable</tt> symlink.)<br />
<br />
$ zypper ar http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/appsuiteui/updates/SLES11/ OXAPPSUITEUIUPDATES<br />
$ zypper ar http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/backend/updates/SLES11/ OXBACKENDUPDATES<br />
<br />
and run<br />
<br />
$ zypper dup -r OXAPPSUITEUIUPDATES<br />
$ zypper dup -r OXBACKENDUPDATES<br />
<br />
You might need to run<br />
<br />
$ zypper ref<br />
<br />
to update the repository metadata before running ''zypper up''.<br />
<br />
After the new packages are installed, the open-xchange process needs a restart:<br />
<br />
<pre>$ rcopen-xchange restart</pre><br />
(Please, keep the [[#Warnings|warning about database updates]] in mind.<br />
<br />
==== SLES 12 ====<br />
<br />
If you want to update an older version of Open-Xchange App Suite to the latest maintenance release, add the following entry to the repository list. Replace VERSION with the version you are using (e.g. 7.4.2, 7.6.0). See [[AppSuite:Version_Support_Committment]] for the currently supported versions. Also, make sure that your repository configuration points at the versioned base installation repositories (instead of using the <tt>stable</tt> symlink.)<br />
<br />
$ zypper ar http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/appsuiteui/updates/SLE_12/ OXAPPSUITEUIUPDATES<br />
$ zypper ar http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/backend/updates/SLE_12/ OXBACKENDUPDATES<br />
<br />
and run<br />
<br />
$ zypper dup -r OXAPPSUITEUIUPDATES<br />
$ zypper dup -r OXBACKENDUPDATES<br />
<br />
You might need to run<br />
<br />
$ zypper ref<br />
<br />
to update the repository metadata before running ''zypper up''.<br />
<br />
After the new packages are installed, the open-xchange process needs a restart:<br />
<br />
<pre>$ rcopen-xchange restart</pre><br />
(Please, keep the [[#Warnings|warning about database updates]] in mind.<br />
<br />
= Updating UI plugins =<br />
<br />
If you update only UI plugins without simultaneously upgrading the core UI packages to a new version, you need to perform an additional step after the update to make the changes visible to users.<br />
<br />
The package <tt>open-xchange-appsuite</tt> contains a timestamp which is different in each version. The JavaScript UI in every user's browser will reload all cached code and data whenever this value changes. Since this value does not change when updating only plugin packages, the value must be changed manually with the following command:<br />
<br />
$ /opt/open-xchange/sbin/touch-appsuite --timestamp=20170101.123400<br />
<br />
If you only have one OX node, the parameter <code>--timestamp</code> can be omitted. It defaults to the current UTC time anyway.<br />
<br />
When updating a cluster, the command must use the same timestamp value on every node. Otherwise, browsers will clear their cache and re-download the entire UI code every time load balancer sends them to a different node (i.e. on almost every login). This is also why the timestamps can't be updated automatically: a node doesn't know which value other nodes will pick, which of them are part of the same update, etc.<br />
<br />
The quickest way to obtain a value for the timestamp parameter is to run the command with the parameter <code>-h</code>. It will then print a help message with the current time as an example. For automation, you can use the output of<br />
<br />
date -u +%Y%m%d.%H%M%S<br />
<br />
Again: this value must be computed once, and then the same value must be used on every node in the cluster.<br />
<br />
This step can be performed on each node separately after each node has been updated, or on all nodes at once after all nodes have been updated. If Apache has its own set of dedicated nodes, the <tt>touch-appsuite</tt> call must be performed on the web server nodes, after all corresponding <tt><plugin>-static</tt> packages have been updated.<br />
<br />
[[Category: OX7]]<br />
[[Category: AppSuite]]<br />
<br />
[[Category: Administrator]]</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:UpdatingOXPackages&diff=22780AppSuite:UpdatingOXPackages2016-12-09T14:00:22Z<p>Viktor.Pracht: Added a section about UI plugins</p>
<hr />
<div><div class="title">Updating OX App Suite packages</div><br />
<br />
''Synopsys'': This article describes how to update OX App Suite packages from one service pack to another.<br />
<br />
== Warnings ==<br />
<br />
Before we begin, here are several things that you should keep in mind:<br />
* If you are '''updating a cluster, please do it one node after the other'''. Turn the node off, update, turn it on again, make sure it works in the cluster. Have a look here, too: [[Running_a_cluster#Upgrading_a_single_Node|Upgrading a single node]]<br />
* If you don't have a cluster of OX nodes, then your complete installation needs to be taken down temporarily.<br />
* Please '''update the frontend before the backend'''. Otherwise the old frontend won't work with the new backend and it's manifests.<br />
* Please '''do not restart Open-Xchange during the database update'''. A database update can happen after installing minor or major updates. As soon as the first user tries to log in to the system or if any provisioning action is done, this update starts.<br />
<br />
== How to get updates? ==<br />
<br />
OX App Suite updates can be accessed by customers with a valid license.<br />
<br />
In addition, you need to configure the [[OXReportClient]].<br />
<br />
= Updating OX App Suite Packages =<br />
<br />
<br />
== Installing Updates ==<br />
<br />
A new service pack usually introduces new packages and requires configuration changes. To get all required new packages and configuration changes, the following '''must''' be done when installing updates.<br />
<br />
(Please, keep the [[#Warning|warning about frontend updates before backend updates]] in mind)<br />
<br />
=== On Debian based distributions ===<br />
<br />
Add the following entry to <tt>/etc/apt/sources.list.d/open-xchange.list</tt><br />
<br />
deb http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/stable/appsuiteui/updates/DebianJessie/ /<br />
deb http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/stable/backend/updates/DebianJessie /<br />
Then run<br />
<br />
$ apt-get update<br />
$ apt-get dist-upgrade<br />
<br />
If you want to see, what apt-get is going to do without actually doing it, you can run:<br />
<br />
$ apt-get dist-upgrade -s<br />
<br />
After the new packages are installed, the open-xchange process needs a restart:<br />
<br />
<pre>$ /etc/init.d/open-xchange restart</pre><br />
<br />
=== On RPM based distributions ===<br />
<br />
==== RHEL6/CentOS6 ====<br />
<br />
Add the following entries to <tt>/etc/yum.repos.d/ox.repo</tt>:<br />
<br />
[ox-updates-appsuiteui]<br />
name=Open-Xchange Updates<br />
baseurl=http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/stable/appsuiteui/updates/RHEL6/<br />
gpgkey=http://software.open-xchange.com/oxbuildkey.pub<br />
enabled=1<br />
gpgcheck=1<br />
metadata_expire=0m<br />
<br />
[ox-updates-backend]<br />
name=Open-Xchange Updates<br />
baseurl=http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/stable/backend/updates/RHEL6/<br />
gpgkey=http://software.open-xchange.com/oxbuildkey.pub<br />
enabled=1<br />
gpgcheck=1<br />
metadata_expire=0m<br />
<br />
and run<br />
<br />
$ yum update<br />
<br />
$ yum upgrade<br />
<br />
After the new packages are installed, the open-xchange process needs a restart:<br />
<br />
<pre>$ /etc/init.d/open-xchange restart</pre><br />
(Please, keep the [[#Warnings|warning about database updates]] in mind)<br />
<br />
==== RHEL7/CentOS7 ====<br />
<br />
Add the following entries to <tt>/etc/yum.repos.d/ox.repo</tt>:<br />
<br />
[ox-updates-appsuiteui]<br />
name=Open-Xchange Updates<br />
baseurl=http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/stable/appsuiteui/updates/RHEL7/<br />
gpgkey=http://software.open-xchange.com/oxbuildkey.pub<br />
enabled=1<br />
gpgcheck=1<br />
metadata_expire=0m<br />
<br />
[ox-updates-backend]<br />
name=Open-Xchange Updates<br />
baseurl=http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/stable/backend/updates/RHEL7/<br />
gpgkey=http://software.open-xchange.com/oxbuildkey.pub<br />
enabled=1<br />
gpgcheck=1<br />
metadata_expire=0m<br />
<br />
and run<br />
<br />
$ yum update<br />
<br />
$ yum upgrade<br />
<br />
After the new packages are installed, the open-xchange process needs a restart:<br />
<br />
<pre>$ /etc/init.d/open-xchange restart</pre><br />
(Please, keep the [[#Warnings|warning about database updates]] in mind)<br />
<br />
==== SLES12 ====<br />
<br />
Add the updates repository to the repository list:<br />
<br />
$ zypper ar http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/stable/appsuiteui/updates/SLE_12/ OXAPPSUITEUIUPDATES<br />
$ zypper ar http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/stable/backend/updates/SLE_12/ OXBACKENDUPDATES<br />
<br />
and run<br />
<br />
$ zypper dup -r OXAPPSUITEUIUPDATES<br />
$ zypper dup -r OXBACKENDUPDATES<br />
<br />
You might need to run<br />
<br />
$ zypper ref<br />
<br />
to update the repository metadata before running ''zypper up''.<br />
<br />
After the new packages are installed, the open-xchange process needs a restart:<br />
<br />
<pre>$ rcopen-xchange restart</pre><br />
(Please, keep the [[#Warnings|warning about database updates]] in mind.<br />
<br />
= Updating OX App Suite Packages for older versions =<br />
<br />
<br />
== Installing Updates ==<br />
<br />
A new service pack usually introduces new packages and requires configuration changes. To get all required new packages and configuration changes, the following '''must''' be done when installing updates.<br />
<br />
(Please, keep the [[#Warning|warning about frontend updates before backend updates]] in mind)<br />
<br />
=== On Debian based distributions ===<br />
<br />
If you want to update an older version of Open-Xchange App Suite to the latest maintenance release, add the following entry to <tt>/etc/apt/sources.list.d/open-xchange.list</tt>. Replace VERSION with the version you are using (e.g. 7.6.2). See [[AppSuite:Version_Support_Committment]] for the currently supported versions. Also, make sure that your repository configuration points at the versioned base installation repositories (instead of using the <tt>stable</tt> symlink.)<br />
<br />
deb http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/appsuiteui/updates/DebianWheezy/ /<br />
deb http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/backend/updates/DebianWheezy/ /<br />
<br />
deb http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/appsuiteui/updates/DebianJessie/ /<br />
deb http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/backend/updates/DebianJessie /<br />
<br />
Then run<br />
<br />
$ apt-get update<br />
$ apt-get dist-upgrade<br />
<br />
If you want to see, what apt-get is going to do without actually doing it, you can run:<br />
<br />
$ apt-get dist-upgrade -s<br />
<br />
After the new packages are installed, the open-xchange process needs a restart:<br />
<br />
<pre>$ /etc/init.d/open-xchange restart</pre><br />
<br />
=== On RPM based distributions ===<br />
<br />
==== RHEL6/CentOS6 ====<br />
<br />
If you want to update an older version of Open-Xchange App Suite to the latest maintenance release, add the following entry to <tt>/etc/yum.repos.d/ox.repo</tt>. Replace VERSION with the version you are using (e.g. 7.4.2, 7.6.0). See [[AppSuite:Version_Support_Committment]] for the currently supported versions. Also, make sure that your repository configuration points at the versioned base installation repositories (instead of using the <tt>stable</tt> symlink.)<br />
<br />
[ox-updates-appsuiteui]<br />
name=Open-Xchange Updates<br />
baseurl=http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/appsuiteui/updates/RHEL6/<br />
gpgkey=http://software.open-xchange.com/oxbuildkey.pub<br />
enabled=1<br />
gpgcheck=1<br />
metadata_expire=0m<br />
<br />
[ox-updates-backend]<br />
name=Open-Xchange Updates<br />
baseurl=http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/backend/updates/RHEL6/<br />
gpgkey=http://software.open-xchange.com/oxbuildkey.pub<br />
enabled=1<br />
gpgcheck=1<br />
metadata_expire=0m<br />
<br />
and run<br />
<br />
$ yum update<br />
<br />
$ yum upgrade<br />
<br />
After the new packages are installed, the open-xchange process needs a restart:<br />
<br />
<pre>$ /etc/init.d/open-xchange restart</pre><br />
(Please, keep the [[#Warnings|warning about database updates]] in mind)<br />
<br />
==== RHEL7/CentOS7 ====<br />
<br />
If you want to update an older version of Open-Xchange App Suite to the latest maintenance release, add the following entry to <tt>/etc/yum.repos.d/ox.repo</tt>. Replace VERSION with the version you are using (e.g. 7.4.2, 7.6.0). See [[AppSuite:Version_Support_Committment]] for the currently supported versions. Also, make sure that your repository configuration points at the versioned base installation repositories (instead of using the <tt>stable</tt> symlink.)<br />
<br />
[ox-updates-appsuiteui]<br />
name=Open-Xchange Updates<br />
baseurl=http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/appsuiteui/updates/RHEL7/<br />
gpgkey=http://software.open-xchange.com/oxbuildkey.pub<br />
enabled=1<br />
gpgcheck=1<br />
metadata_expire=0m<br />
<br />
[ox-updates-backend]<br />
name=Open-Xchange Updates<br />
baseurl=http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/backend/updates/RHEL7/<br />
gpgkey=http://software.open-xchange.com/oxbuildkey.pub<br />
enabled=1<br />
gpgcheck=1<br />
metadata_expire=0m<br />
<br />
and run<br />
<br />
$ yum update<br />
<br />
$ yum upgrade<br />
<br />
After the new packages are installed, the open-xchange process needs a restart:<br />
<br />
<pre>$ /etc/init.d/open-xchange restart</pre><br />
(Please, keep the [[#Warnings|warning about database updates]] in mind)<br />
<br />
==== SLES 11 ====<br />
<br />
If you want to update an older version of Open-Xchange App Suite to the latest maintenance release, add the following entry to the repository list. Replace VERSION with the version you are using (e.g. 7.4.2, 7.6.0). See [[AppSuite:Version_Support_Committment]] for the currently supported versions. Also, make sure that your repository configuration points at the versioned base installation repositories (instead of using the <tt>stable</tt> symlink.)<br />
<br />
$ zypper ar http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/appsuiteui/updates/SLES11/ OXAPPSUITEUIUPDATES<br />
$ zypper ar http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/backend/updates/SLES11/ OXBACKENDUPDATES<br />
<br />
and run<br />
<br />
$ zypper dup -r OXAPPSUITEUIUPDATES<br />
$ zypper dup -r OXBACKENDUPDATES<br />
<br />
You might need to run<br />
<br />
$ zypper ref<br />
<br />
to update the repository metadata before running ''zypper up''.<br />
<br />
After the new packages are installed, the open-xchange process needs a restart:<br />
<br />
<pre>$ rcopen-xchange restart</pre><br />
(Please, keep the [[#Warnings|warning about database updates]] in mind.<br />
<br />
==== SLES 12 ====<br />
<br />
If you want to update an older version of Open-Xchange App Suite to the latest maintenance release, add the following entry to the repository list. Replace VERSION with the version you are using (e.g. 7.4.2, 7.6.0). See [[AppSuite:Version_Support_Committment]] for the currently supported versions. Also, make sure that your repository configuration points at the versioned base installation repositories (instead of using the <tt>stable</tt> symlink.)<br />
<br />
$ zypper ar http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/appsuiteui/updates/SLE_12/ OXAPPSUITEUIUPDATES<br />
$ zypper ar http://CUSTOMERID:PASSWORD@software.open-xchange.com/products/appsuite/VERSION/backend/updates/SLE_12/ OXBACKENDUPDATES<br />
<br />
and run<br />
<br />
$ zypper dup -r OXAPPSUITEUIUPDATES<br />
$ zypper dup -r OXBACKENDUPDATES<br />
<br />
You might need to run<br />
<br />
$ zypper ref<br />
<br />
to update the repository metadata before running ''zypper up''.<br />
<br />
After the new packages are installed, the open-xchange process needs a restart:<br />
<br />
<pre>$ rcopen-xchange restart</pre><br />
(Please, keep the [[#Warnings|warning about database updates]] in mind.<br />
<br />
= Updating UI plugins =<br />
<br />
If you update only UI plugins without simultaneously upgrading the core UI packages to a new version, you need to perform an additional step after the update to make the changes visible to users.<br />
<br />
The package <tt>open-xchange-appsuite</tt> contains a timestamp which is different in each version. The JavaScript UI in every user's browser will reload all cached code and data whenever this value changes. Since this value does not change when updating only plugin packages, the value must be changed manually with the following command:<br />
<br />
$ /opt/open-xchange/sbin/touch-appsuite --timestamp=20170101.123400<br />
<br />
If you only have one OX node, the parameter <code>--timestamp</code> can be omitted. It defaults to the current UTC time anyway.<br />
<br />
When updating a cluster, the command must use the same timestamp value on every node. Otherwise, browsers will clear their cache and re-download the entire UI code every time load balancer sends them to a different node (i.e. on almost every login). This is also why the timestamps can't be updated automatically: a node doesn't know which value other nodes will pick, which of them are part of the same update, etc.<br />
<br />
The quickest way to obtain a value for the timestamp parameter is to run the command with the parameter <code>-h</code>. It will then print a help message with the current time as an example. For automation, you can use the output of<br />
<br />
date -u +%Y%m%d.%H%M%S<br />
<br />
Again: this value must be computed once, and then the same value must used on every node in the cluster.<br />
<br />
This step can be performed on each node separately after each node has been updated, or on all nodes at once after all nodes have been updated. If Apache has its own set of dedicated nodes, the <tt>touch-appsuite</tt> call must be performed on the web server nodes, after all corresponding <tt><plugin>-static</tt> packages have been updated.<br />
<br />
[[Category: OX7]]<br />
[[Category: AppSuite]]<br />
<br />
[[Category: Administrator]]</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:UI_build_system&diff=22288AppSuite:UI build system2016-08-10T09:00:18Z<p>Viktor.Pracht: Undo revision 22287 by Khgras (talk)</p>
<hr />
<div>{{Stability-deprecated}}<br />
<br />
<div class="title">Build System</div><br />
<br />
'''Abstract:''' This document describes the build system of OX App Suite. It is intended for app developers who use the build system to create apps as well as for OX App Suite developers who not only use the build system but also may wish to extend it.<br />
<br />
The build system is used to create source archives from source files. These source archives can be used to compile installable packages for various Linux distributions. The build system can generate archives for the core UI as well as for independently installed apps.<br />
<br />
The OX App Suite build system uses [https://github.com/mde/jake Jake], a port of Rake from Ruby to [http://nodejs.org Node.js]. Both Rake and Jake are dependency-based build systems like Make, which allows quick incremental builds. But unlike Make, Jake doesn't have its own syntax. Instead, it provides an API in JavaScript. The API is used not only to specify dependencies between files using a full programming language, but also to implement the generation of files in the same language. This allows easy implementation of complex build systems, of which the OX App Suite build system is an example. Using the same language for the developed project and for its build system also allows any core developer to quickly extend the build system without having to switch to another language.<br />
<br />
== Using the Build System ==<br />
<br />
While easily extensible, most of the time the build system will be used as-is. This chapter describes how to set up and use the build system to develop apps and the OX App Suite core.<br />
<br />
All command examples are given for the Debian operating system. The instructions should work similarly on other POSIX systems. The first character of each command indicates whether it should be executed as root (#) or as a normal user ($).<br />
<br />
== Installing ==<br />
<br />
Installing the right environment for running the <code>appserver</code> and the UI build system is described in [[AppSuite:GettingStarted#Installing | the getting started article]].<br />
<br />
== Running ==<br />
<br />
The build system is executed by invoking the command <code>build-appsuite</code>. Similar to most build systems, the build system can perform multiple tasks, which are specified as parameters on the command line. Each task can require any number of parameters. These parameters can be specified either on the command line, using the syntax <code>name=value</code>, or as environment variables.<br />
<br />
If present, the file <code>local.conf</code> is sourced by a shell script before the build process starts. This file can export environment variables which are specific to the local system, without checking them into a version control system. Typically, it defines values for <code>[[#builddir|builddir]]</code> and <code>[[#debug|debug]]</code>.<br />
<br />
Since the build system is based on Jake, it also accepts all other Jake options. In addition, the environment variable <code>$nodeopts</code> can be used to pass command line parameters to Node.js. One of the most useful parameters is <code>--debug-brk</code>, which can be used to debug the build system.<br />
<br />
When developing external apps, the build system must be run from the top directory of the app's source. As a safety precaution, execution is aborted if the subdirectory <code>apps</code>, which usually contains JavaScript source code, is not found. This Article is written assuming, you're working in your workspace directory, containing the subfolder <code>apps</code>.<br />
<br />
== Workflow ==<br />
<br />
The build system is used not only to create source archives for packaging. It can also directly install and update the built UI in a directory during development, help with the setup of the source of a new external app and more. While all of these tasks are described in the reference section, daily work involves just a few of them.<br />
<br />
To have an easy example about how to [[AppSuite:GettingStarted#Writing | write]], [[AppSuite:GettingStarted#Building | build]] & [[AppSuite:GettingStarted#Running | host]] your javascript code and how to [[AppSuite:GettingStarted#Initialization | initialize]] & [[AppSuite:GettingStarted#Building_Packages | build]] your packages, please have a look at the [[AppSuite:GettingStarted | GettingStarted article]].<br />
<br />
==== JSHINT ====<br />
<br />
One step of the build process is running jshint to statically analyse the sources for certain errors. JSHint is configured with (what we think) sane defaults, but if you want to configure your own rules, edit <code>.jshintrc</code> in your project`s root folder, according to your needs.<br />
<br />
=== default ===<br />
<br />
The default task is used instead of the app task when building the core OX App Suite. Since it is the default Jake task, it is not necessary to specify it on the command line when it's the only task.<br />
<br />
The top directory of OX App Suite source code includes the script <code>build.sh</code>, which should be used instead of calling a potentially unrelated version of <code>build-appsuite</code>. The script changes the current directory to its own, so that it can be called from any directory.<br />
<br />
$ web/ui/build.sh<br />
<br />
=== clean ===<br />
<br />
The build system uses dependencies and file timestamps to decide which files to rebuild. This assumes that any change to a file increases its timestamp to a value which is greater than the timestamp of any existing file. When this assumption is violated (e.g. after switching to a different source control branch with older files) it may become necessary to rebuild everything to restore the assumption about timestamps. The simplest way to achieve this is the clean task, which simply deletes all generated files.<br />
<br />
WARNING: This can be potentially dangerous, since the clean task simply deletes the directories specified by the variables builddir, destDir, l10nDir, manifestDir, and helpDir.<br />
<br />
=== dist ===<br />
<br />
When the app is ready to be shipped, or rather all the time on a continuous build system, the app needs to be packaged in a format suitable for installation on a production system. Since there already exist tools to create packages from suitably arranged source code archives, the OX App Suite build system merely prepares such source archives.<br />
<br />
The dist task creates an archive with the source (the one ending in .orig.tar.bz2) and a few additional files necessary for Debian packaging. RPM packages can be generated using the same source archive and the .spec file created by init-packaging. The version of the package is extracted from the newest entry in the file debian/changelog.<br />
<br />
Debian packages can also be generated manually either from the temporary directory left behind by dist, or even directly from the source tree. The second option pollutes the source tree with generated files, so it is not recommended, although the .gitignore file created by init-packaging can handle these generated files.<br />
<br />
$ build-appsuite dist<br />
$ ls tmp/packaging/<br />
example-app-0.0.1 example-app_0.0.1-1.dsc<br />
example-app_0.0.1-1.debian.tar.bz2 example-app_0.0.1.orig.tar.bz2<br />
$ cd tmp/packaging/example-app-0.0.1/<br />
$ dpkg-buildpackage -b<br />
<br />
== Reference ==<br />
<br />
=== Variables ===<br />
<br />
==== BASEDIR ====<br />
The top directory of the build system.<br />
<br />
<b>Used by:</b> all tasks.<br />
<br />
<b>Default:</b> installation directory of the build system<br />
<br />
Required to build external apps, since in this case, the build<br />
system is not installed in the current directory. This variable is<br />
automatically set as an environment variable by the build system<br />
executable based on <code>$OX_APPSUITE_DEV</code>.<br />
<br />
==== branch ====<br />
The Subversion branch of the CLDR to checkout.<br />
<br />
<b>Used by:</b> <code>update-i18n</code>.<br />
<br />
==== builddir ====<br />
The target directory for generated files.<br />
<br />
<b>Used by:</b> <code>app</code>, <code>clean</code>,<br />
<code>default</code>, <code>dist</code>, <code>docs</code>,<br />
<code>jakedeps</code>.<br />
<br />
Default: <code>build</code><br />
<br />
==== copyright ====<br />
The copyright line to be included in packaging metadata.<br />
<br />
<b>Used by:</b> <code>[[#init-packaging|init-packaging]]</code>.<br />
<br />
<b>Example:</b> <code>2012 Open-Xchange, Inc</code><br />
<br />
==== coreDir ====<br />
Location of OX App Suite UI files.<br />
<br />
<b>Used by:</b> <code>[[#app|app]]</code>, <code>[[#default|default]]</code>.<br />
<br />
<b>Default:</b> same as <code>[[#builddir|builddir]]</code><br />
<br />
Some tasks depend on installed files from the OX App Suite. When building external apps, <code>[[#coreDir|coreDir]]</code> specified the directory which contains these files.<br />
<br />
Currently, this parameter is used to compile <code>.less</code> files for every installed theme. This can be disabled by setting <code>[[#skipLess|skipLess]]</code>.<br />
<br />
==== debug ====<br />
Enables a debug build.<br />
<br />
<b>Used by:</b> <code>app</code>, <code>default</code>.<br />
<br />
<b>Default:</b> <code>false</code><br />
<br />
To simplify debugging of OX App Suite, compression of source code<br />
can be disabled by specifying <code>on</code>, <code>yes</code>,<br />
<code>true</code> or <code>1</code>.<br />
<br />
==== description ====<br />
<b>Used by:</b> <code>init-packaging</code>.<br />
<br />
The description of the app to be included in packaging metadata.<br />
<br />
==== destDir ====<br />
Output directory for source archives created by<br />
the <code>dist</code> task.<br />
<br />
<b>Used by:</b> <code>clean</code>, <code>dist</code>.<br />
<br />
<b>Default:</b> <code>tmp/packaging</code><br />
<br />
==== disableStrictMode ====<br />
Removes all <code>"use strict"</code> directives from processed<br />
JavaScript code.<br />
<br />
<b>Used by:</b> <code>app</code>, <code>default</code>.<br />
<br />
<b>Default:</b> <code>false</code><br />
<br />
Some debugging tools which use code instrumentation have problems<br />
when the debugged code uses strict mode. This setting enables code<br />
processing even whe using <code>debug</code> mode, so line numbers<br />
will not match the original source code.<br />
<br />
==== forceDeb ====<br />
Whether an error during the generation of Debian source packages is an error.<br />
<br />
<b>Used by:</b> <code>dist</code>.<br />
<br />
<b>Default:</b> <code>false</code><br />
<br />
This is useful when Debian packages are generated automatically, and a failure of <code>dpkg-source</code> is also a failure of the entire build. By default it merely produces a warning.<br />
<br />
==== from ====<br />
The root of the printed dependency tree between Jake tasks.<br />
<br />
<b>Used by:</b> <code>jakedeps</code>.<br />
<br />
==== helpDir ====<br />
The location of online help files.<br />
<br />
<b>Used by:</b> <code>clean</code>, <code>default</code>,<br />
<code>dist</code>.<br />
<br />
<b>Default:</b> same as <code>builddir</code><br />
<br />
If the value contains the string <code>@lang@</code>, it will be<br />
replaced by the lowercase language code (e.g. <code>en-us</code>) to<br />
allow per-language directories.<br />
<br />
==== l10nDir ====<br />
The location of compiled l10n files.<br />
<br />
<b>Used by:</b> <code>app</code>, <code>clean</code>,<br />
<code>default</code>, <code>dist</code>.<br />
<br />
<b>Default:</b> same as <code>builddir</code><br />
<br />
If the value contains the string <code>@lang@</code>, it will be<br />
replaced by the lowercase language code (e.g. <code>en-us</code>) to<br />
allow per-language directories.<br />
<br />
==== license ====<br />
File name of the full text of the distribution license.<br />
<br />
<b>Used by:</b> <code>init-packaging</code>.<br />
<br />
<b>Default:</b> based on <code>licenseName</code>.<br />
<br />
==== licenseName ====<br />
Name of the distribution license to be included in packaging<br />
metadata.<br />
<br />
<b>Used by:</b> <code>init-packaging</code>.<br />
<br />
<b>Default:</b> <code>CC-BY-NC-SA-3.0</code><br />
<br />
==== manifestDir ====<br />
The location of the combined manifest file.<br />
<br />
<b>Used by:</b> <code>app</code>, <code>clean</code>,<br />
<code>default</code>, <code>dist</code>.<br />
<br />
<b>Default:</b> same as <code>builddir</code><br />
<br />
==== maintainer ====<br />
Name and email address of the package maintainer.<br />
<br />
<b>Used by:</b> <code>init-packaging</code>.<br />
<br />
<b>Format:</b> <code><var>Name</var> &lt;<var>email</var>&gt;</code><br />
<br />
==== package ====<br />
The name of the package for the built app.<br />
<br />
<b>Used by:</b> all tasks.<br />
<br />
<b>Default:</b> the package name in the first line of<br />
<code>debian/changelog</code><br />
<br />
Since the name of the manifest file contains the package name and it<br />
is required to determine build dependencies, the package name must<br />
be always known. This means either <code>debian/changelog</code><br />
must exist and contain at least one entry, or the parameter must be<br />
explicitly specified.<br />
<br />
==== reverse ====<br />
Reverses the direction of printed dependencies.<br />
<br />
<b>Used by:</b> <code>deps</code>.<br />
<br />
When specified, the <code>deps</code> task prints modules which<br />
depend on the specified modules, instead of modules on which<br />
the specified module depends.<br />
<br />
==== revision ====<br />
Revision number of the package for the app.<br />
<br />
<b>Used by:</b> <code>app</code>, <code>default</code>,<br />
<code>dist</code>.<br />
<br />
<b>Default:</b> <code>1</code><br />
<br />
The revision number must increase with each rebuild of the same<br />
version to enable the creation of unique version strings. These are<br />
required in package names and to control content caching in clients.<br />
<br />
==== root ====<br />
Specifies for which module to print the dependencies.<br />
<br />
<b>Used by:</b> <code>deps</code>.<br />
<br />
<b>Default:</b> print all roots<br />
<br />
If specified, only the dependencies of the specified module are<br />
printed. Otherwise, the dependencies of all modules are printed.<br />
<br />
==== skipDeb ====<br />
Whether to skip the generation of Debian source packages.<br />
<br />
<b>Used by:</b> <code>dist</code>.<br />
<br />
<b>Default:</b> <code>false</code><br />
<br />
This is useful when Debian packages are not required and/or<br />
<code>dpkg-source</code> is not available, e.g. on RPM based<br />
systems.<br />
<br />
Even when using this flag, at least the file<br />
<code>debian/changelog</code> is still required, because it is used<br />
to store the package name and version. <br />
<br />
==== skipLess ====<br />
Whether to skip the preprocessing of LessCSS files.<br />
<br />
<b>Used by:</b> <code>app</code>, <code>default</code>.<br />
<br />
<b>Default:</b> <code>false</code><br />
<br />
This flag skips the generation of CSS files in<br />
the <code>apps/themes/*/less</code> directories of all themes.<br />
It is used by the packaging system, where the LessCSS files are<br />
precompiled after installation on the target system instead of<br />
while building the package.<br />
<br />
==== tag ====<br />
The Subversion tag of the CLDR to checkout.<br />
<br />
<b>Used by:</b> <code>update-i18n</code>.<br />
<br />
==== to ====<br />
The leaf task in the printed dependency path between Jake tasks.<br />
<br />
<b>Used by:</b> <code>jakedeps</code>.<br />
<br />
When specified, only a single path from the root to the leaf task is<br />
printed (in reverse order).<br />
<br />
==== version ====<br />
Version number of the app.<br />
<br />
<b>Used by:</b> <code>app</code>, <code>default</code>,<br />
<code>dist</code>, <code>init-packaging</code>.<br />
<br />
<b>Default:</b> <code>0.0.1</code><br />
<br />
The version should consist of a major, minor and patch version<br />
separated by dots.<br />
<br />
=== Tasks ===<br />
<p><br />
An up-to-date list of tasks can be printed using the -T command line option.<br />
<br />
==== app ====<br />
Builds an external app.<br />
<br />
<b>Variables:</b> <code>[[#BASEDIR|BASEDIR]]</code>, <code>[[#builddir|builddir]]</code>, <code>[[#coreDir|coreDir]]</code>, <code>[[#debug|debug]]</code>, <code>[[#disableStrictMode|disableStrictMode]]</code>, <code>[[#l10nDir|l10nDir]]</code>, <code>[[#manifestDir|manifestDir]]</code>, <code>[[#package|package]]</code>, <code>[[#revision|revision]]</code>, <code>[[#version|version]]</code>.<br />
<br />
This is the main task used to build external apps.<br />
<br />
It works without explicitly specifying any variables, but during<br />
development, <code>[[#builddir|builddir]]</code> is usually pointed to<br />
the directory of a locally installed OX App Suite UI to avoid<br />
additional copying steps. For debugging, <code>[[#debug|debug]]</code> is also<br />
often used. Note that <code>[[#clean|clean]]</code> must be called when<br />
changing any of the variables.<br />
<br />
==== clean ====<br />
Removes all generated files.<br />
<br />
<b>Variables:</b> <code>BASEDIR</code>, <code>builddir</code>,<br />
<code>destDir</code>, <code>l10nDir</code>,<br />
<code>manifestDir</code>, <code>package</code>.<br />
<br />
This task should be executed before a normal build using<br />
<code>app</code> or <code>default</code> after changing any build<br />
variables and after a switch between Git branches. Normal<br />
incremental builds can miss changed files if a branch switch<br />
replaces files by older versions.<br />
<br />
==== default ====<br />
Builds OX App Suite.<br />
<br />
<b>Variables:</b> <code>[[#BASEDIR|BASEDIR]]</code>, <code>[[#builddir|builddir]]</code>, <code>[[#debug|debug]]</code>, <code>[[#disableStrictMode|disableStrictMode]]</code>, <code>[[#l10nDir|l10nDir]]</code>, <code>[[#manifestDir|manifestDir]]</code>, <code>[[#package|package]]</code>, <code>[[#revision|revision]]</code>, <code>[[#version|version]]</code>.<br />
<br />
This is the main task to build OX App Suite. Since it is the default<br />
Jake task, it does not need to be specified explicitly on<br />
the command line when it is the only task.<br />
<br />
It works without explicitly specifying any variables, but during<br />
development, <code>[[#builddir|builddir]]</code> is usually pointed to<br />
a directory which is accessible to a local web server. For<br />
debugging, <code>[[#debug|debug]]</code> is also often used. Note that<br />
<code>[[#clean|clean]]</code> must be called when changing any of<br />
the variables.<br />
<br />
==== deps ====<br />
Prints module dependencies.<br />
<br />
<b>Variables:</b> <code>BASEDIR</code>, <code>package</code>,<br />
<code>reverse</code>, <code>root</code>.<br />
<br />
This task visualizes dependencies of RequireJS modules. It prints<br />
a tree of dependencies to <code>stdout</code>.<br />
<br />
If <code>root</code> is specified, then only the dependencies of<br />
that module are printed. Otherwise, the dependencies of all modules,<br />
on which no other module depends are printed in sequence. <br />
<br />
If <code>reverse</code> is specified, then this task prints<br />
dependants instead of dependencies, i.e. modules which depend on<br />
the specified module instead of modules on which the specified<br />
module depends.<br />
<br />
==== dist ====<br />
Creates source packages.<br />
<br />
<b>Variables:</b> <code>BASEDIR</code>, <code>builddir</code>,<br />
<code>destDir</code>, <code>forceDeb</code>, <code>l10nDir</code>,<br />
<code>manifestDir</code>, <code>package</code>,<br />
<code>revision</code>, <code>skipDeb</code>,<br />
<code>version</code>.<br />
<br />
This task cleans the source tree by calling <code>clean</code> and<br />
packs the source into an archive which can be used to create Debian<br />
and RPM packages. The necessary Debian metadata is created alongside<br />
the source archive. All files necessary for Debian packaging are<br />
placed in the directory specified by <code>destDir</code>.<br />
The generated <code>.orig.tar.bz2</code> archive can also be used<br />
together with the <code>.spec</code> file to generate RPM packages.<br />
<br />
Unless the variable <code>skipDeb</code> is set to<br />
<code>true</code>, the program <code>dpkg-source</code> is required<br />
by this task. It is used to generate Debian-specific packaging<br />
metadata.<br />
<br />
==== init-packaging ====<br />
Initializes packaging information for a new app.<br />
<br />
<b>Variables:</b> <code>BASEDIR</code>, <code>copyright</code>,<br />
<code>description</code>, <code>license</code>,<br />
<code>licenseName</code>, <code>maintainer</code>,<br />
<code>package</code>, <code>version</code>.<br />
<br />
This task is the first task called when starting with<br />
the development of a new external app. The directory from which it<br />
is called must already contain at least the <code>apps</code><br />
subdirectory. This is also the only task where<br />
the <code>package</code> variable must be specified explicitly.<br />
Afterwards, the package name is looked up automatically in the file<br />
<code>debian/changelog</code>, which is created by this task.<br />
<br />
The variables <code>version</code>, <code>maintainer</code>,<br />
<code>copyright</code>, <code>licenseName</code>,<br />
<code>license</code>, and <code>description</code> are required to<br />
fill out all necessary packaging metadata. Any of these variables<br />
which are not specified explicitly will cause an interactive prompt.<br />
This avoids the need to remember the list of variables before one<br />
can start developing an app.<br />
<br />
==== jakedeps ====<br />
Shows the dependency chain between two Jake tasks.<br />
<br />
<b>Variables:</b> <code>BASEDIR</code>, <code>from</code>,<br />
<code>package</code>, <code>to</code>.<br />
<br />
This task visualized dependencies between Jake tasks. The variable<br />
<code>from</code> specifies the root of a dependency tree, with all<br />
dependencies of <code>from</code> as inner and leaf nodes. If<br />
<code>to</code> is not specified, then that entire tree is printed.<br />
<br />
If <code>to</code> is also specified, then only the first found<br />
dependency path from <code>from</code> to <code>to</code> is<br />
.printed with <code>to</code> at the top and <code>from</code> at<br />
the bottom.<br />
<br />
==== merge ====<br />
Updates all <code>.po</code> files with the generated<br />
<code>ox.pot</code>.<br />
<br />
<b>Variables:</b> <code>BASEDIR</code>, <code>builddir</code>,<br />
<code>debug</code>, <code>package</code>, <code>revision</code>,<br />
<code>version</code>.<br />
<br />
This task updates the list of extracted i18n strings in<br />
<code>ox.pot</code> and calls the GNU Gettext tool<br />
<code>msgmerge</code> for every language in <code>i18n/*.po</code>.<br />
<br />
<code>i18n/en_US.po</code> is not updated by this task because the original strings are already in the <code>en_US</code> locale. It would only end up with every translation mapping every string to itself. The only entries in that file should be for cases when the <code>en_US</code> text is not a suitable fallback for missing translations. The original string in such a case would be something internationally appropriate (e.&nbsp;g. a date written as "2013-01-01" instead of "01/01/2013") and <code>i18n/en_US.po</code> would contain a translation.<br />
<br />
==== update-i18n ====<br />
Updates CLDR data in the source tree.<br />
<br />
<b>Variables:</b> <code>BASEDIR</code>, <code>branch</code>,<br />
<code>package</code>, <code>tag</code>.<br />
<br />
This task downloads data from the Unicode CLDR and updates date<br />
translations for all languages in <code>i18n/*.po</code>.<br />
<br />
The exact version of CLDR data is specified as Suubversion tag or<br />
branch by the variables <code>tag</code> and <code>branch</code>,<br />
respectively. If neither is specified, then the Subversion trunk is<br />
checked out. If both are specified, <code>tag</code> is used.<br />
<br />
==== verify-doc ====<br />
Generates a documentation skeleton for extension points.<br />
<br />
<b>Variables:</b> <code>BASEDIR</code>, <code>package</code>.<br />
<br />
This task is still under development. Currently, it creates a list of all extension points, which have a constant name in the source code. In the future it is supposed to update an existing list instead of overwriting it, and to handle non-constant extension point names.<br />
<br />
The list of extension points is stored as an HTML snippet in <code>doc/extensionpoints.html</code>.<br />
<br />
<br />
[[Category:AppSuite]]<br />
[[Category:UI]]</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:Dynamic_Theme&diff=21929AppSuite:Dynamic Theme2016-05-17T15:44:07Z<p>Viktor.Pracht: /* Specifying a Theme */</p>
<hr />
<div><!-- !!! --><br />
<!-- PLEASE APPLY CHANGES ONLY TO THE NEW TECHNICAL DOCUMENTATION: wd/frontend/web/documentation --> <br />
<!-- !!! --><br />
<br />
{{Stability-unstable}}<br />
<br />
<div class="title">Dynamic Theming</div><br />
<br />
The dynamic theme plugin allows to have custom colors and logo without creating a real theme for each possible color combination. The customization information is stored in the [[ConfigCascade|Configuration Cascade]] and applied at runtime, immediately after login.<br />
<br />
== Installation ==<br />
<br />
The theme generator consists of the single package <tt>open-xchange-dynamic-theme</tt>, which is installed on the OX middleware.<br />
<br />
Before OX App Suite v7.6.2, the package included the command line tool <tt>/opt/open-xchange/sbin/update-dynamic-theme</tt>, which must be called after every update of other plugins. It is called automatically after the installation and upgrades of <tt>open-xchange-dynamic-theme</tt>. The tool examines all installed <tt>.less</tt> files and computes which CSS rules need to be changed to apply the custom colors everywhere.<br />
<br />
Since v7.6.2, the tool is called automatically whenever necessary, so it is not necessary to call it manually, and therefore it is not installed in the <tt>/opt/open-xchange/sbin/</tt> directory anymore.<br />
<br />
== Configuration ==<br />
<br />
=== Enabling the Plugin ===<br />
<br />
The plugin is enabled or disabled by the [[AppSuite:Capabilities|capability]] <tt>dynamic-theme</tt>, e.g. in a file <tt>/opt/open-xchange/etc/dynamic-theme.properties</tt> set<br />
<br />
com.openexchange.capability.dynamic-theme=true<br />
<br />
When using the plugin, the actual theme should be the built-in <tt>default</tt> theme. To prevent all users from changing it and hide the theme selector in the preferences, set the property <tt>io.ox/core//theme</tt> to read-only. To do this, change the file <tt>/opt/open-xchange/etc/meta/appsuite.yaml</tt> as follows: <br />
<br />
io.ox/core//theme:<br />
protected: true<br />
<br />
If some users won't use dynamic themes, this approach won't work. Instead, the theme selector can be disabled an enabled by controlling the list of available themes. The theme selector is hidden if the list is empty. To be able to do that with the Configuration Cascade, the entire list of themes needs to be specified as a single JSON value, e.g. by changing the file <tt>/opt/open-xchange/etc/settings/appsuite.properties</tt> as follows:<br />
<br />
io.ox/core/settingOptions//themes={"default":"Default Theme"}<br />
<br />
Then, to hide the theme selector for users with a dynamic theme, use the Configuration Cascade to change the value to <tt>{}</tt>.<br />
<br />
=== Specifying a Theme ===<br />
<br />
The package installs the file <tt>/opt/open-xchange/etc/settings/open-xchange-dynamic-theme.properties</tt>, which contains the global defaults for the custom theme settings. Any of the settings contained in that file can be changed per-context or at any other granularity supported by the [[ConfigCascade#UI_Properties|Configuration Cascade]]. The individual settings are as follows:<br />
<br />
<table class="wikitable" style="width:auto"><br />
<tr><th>Prefix</th><br />
<th> Key </th><th> Default value </th></tr><br />
<tr><td rowspan="5" style="vertical-align:middle"><tt>io.ox/dynamic-theme//</tt></td><br />
<td><tt> frameColor </tt></td><td><tt> #333 </tt></td></tr><br />
<tr><td><tt> selectionColor </tt></td><td><tt> #39a9e1 </tt></td></tr><br />
<tr><td><tt> logoWidth </tt></td><td><tt> 60 </tt></td></tr><br />
<tr><td><tt> logoURL </tt></td><td><br />
<tt> apps/themes/default/logo-small.png </tt></td></tr><br />
</table><br />
<br />
The colors can be any CSS color; <tt>logoWidth</tt> is specified in pixels; <tt>logoURL</tt> can be relative (to <tt>/appsuite/</tt>), or absolute. When using absolute URLs to point to different hosts, use the form <tt>//<var>hostname</var>/<var>path</var></tt> to keep the protocol (HTTP or HTTPS) and avoid any unnecessary security warnings.<br />
<br />
== Maintenance ==<br />
<br />
The source file <tt>apps/io.ox/dynamic-theme/definitions.less.in</tt> contains the Less rules for the theme. All keys in the namespace <tt>io.ox/dynamic-theme//</tt> are converted to Less variables by prefixing them with <tt>@io-ox-dynamic-theme-</tt>. The set of keys in the following files must be kept in sync:<br />
* <tt>apps/io.ox/dynamic-themes/definitions.less.in</tt><br />
* <tt>apps/io.ox/dynamic-theme/settings/defaults.js</tt><br />
* <tt>lib/update-dynamic-theme.js</tt><br />
* <tt>conf/settings/open-xchange-dynamic-theme.properties</tt></div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=ConfigCascade&diff=21492ConfigCascade2016-02-17T16:40:31Z<p>Viktor.Pracht: /* Specifying Configuration - Server Scope */</p>
<hr />
<div>= Introduction to the config cascade =<br />
<br />
The config cascade is a configuration system that allows administrators to selectively override configuration parameters on context and user level. This means a configuration option can vary between groups of contexts, specific contexts or users.<br />
<br />
== Who should read this document? ==<br />
<br />
If you are tasked with designing and maintaining the configuration of an OX server or cluster, information contained in this document will acquaint you with options in OX configuration design. <br />
<br />
== Core Concepts - Configuration Scope ==<br />
<br />
The config cascade differentiates between 4 scopes of configuration: '''Server''', '''ContextSet''', '''Context''' and '''User''', with the latter always overriding the configuration of the one before it. To determine the active value of a certain parameter, the config cascade looks whether the parameter is defined in a certain scope before falling back to the next scope to the left to determine if a value is defined there. This means, that a value in the '''User''' scope can override the more general value from the '''Context''' scope, which in turn overrides the value of a context set configuration, which itself overrides a server wide configuration.<br />
<br />
== Core Concepts - Context Taxonomy ==<br />
<br />
When deciding on configuration options it usually makes sense to group contexts according to a certain criterion. Typical uses would be to group contexts by offering ('''webmail''', '''groupware_standard''', '''groupware_plus'''), or country ('''de''', '''fr''', '''es''') or brand ('''coolhosting''', '''supremehosting''') or if they are part of a "friendly users" group you sometimes give access to features to deem whether they are appropriate for rollout ('''beta'''). You can then specify configuration options that only take effect if a context is part of one of these groups. For example, the default hostname varies by both country and brand, with the french coolhosting domain name being "coolhosting.fr", while the spanish one is "coolhosting.es", or, for the second brand "supremehosting.fr" or "supremehosting.es" respectively. How can you go about classifying a context?<br />
<br />
Using the command line tools you can specifiy the taxonomy/types parameter:<br />
<br />
'''createcontext ... -i 12 --taxonomy/types=webmail,coolhosting,de'''<br />
<br />
which would tag context 12 with the types webmail, coolhosting and de. This is also available in "'''changecontext'''". In RMI the equivalent is to call '''Context#setUserAttribute("taxonomy", "types", "webmail,coolhosting,de")'''. We will later see how configuration options can be specified for these types of contexts. <br />
<br />
== Specifying Configuration - Server Scope ==<br />
<br />
The most general scope is the '''Server''' scope. Every value that can be overridden along the config cascade '''MUST''' also be defined with a default value in the Server scope. This is done using the usual configuration methods of the server: .properties files in the config directory (usually /opt/openexchange/etc, or /opt/openexchange/etc/groupware in versions up to 6.20.7). Let's consider the properties "'''com.openexchange.messaging.twitter'''", which governs whether twitter messaging should be available in a given installation. Since we consider this to be a premium feature, we'll disable this on the server level:<br />
<br />
'''twittermessaging.properties:'''<br />
com.openexchange.messaging.twitter=false<br />
<br />
Later we will see how to enable it for certain groups of contexts.<br />
<br />
== Specifying Configuration - Context Set Scope ==<br />
<br />
As we saw, you can classify contexts into groups. These groups will now be used to specify certain configuration options. Let's consider this setup:<br />
<br />
<br />
Context 12: webmail,de,beta<br />
Context 13: groupware_plus,es<br />
Context 14: groupware_plus,fr,beta<br />
<br />
<br />
Let's say, we want to roll out the twitter functionality to those contexts, that have the groupware_plus product and are part of our "friendly users". For this, you can specify a configuration that overrides the server setting like this:<br />
<br />
Create a file called '''/opt/openexchange/etc/contextSets/messaging.yml''' and add the following block:<br />
<br />
experimental_gw_plus:<br />
withTags: groupware_plus & beta<br />
com.openexchange.messaging.twitter: true<br />
<br />
Let's go through this line by line. The first line introduces a configuration block that will be used for certain contexts. The name doesn't matter, only insofar as that it may only be used once per file. Choose a good mnemonic here, so a future you or someone else can guess at what is going on in this configuration block. <br />
<br />
The second line specifies the criterion to use to find out whether a context belongs in this group of contexts. In this case, a context having both the groupware_plus and beta tags will be considered to be a part of this group. In the withTags expression you can use boolean logic (with & for and, | for or and brackets to group the expressions). It's best to not go overboard with this, though. If the boolean expressions here become too complex it's usually an indication that you could use another classification for the contexts. Which tags does a context have? Firstly, and most obviously, those specified as its taxonomy/types list. But that is not the whole story. The /users/ module access permissions are also transformed into tags and applied to the context (at runtime). So if a user has access to the tasks module and the infostore module, the context will be considered to be tagged with ucTask and ucInfostore as well. And last keyword which can be used as a tag is the context name. This is sometimes enough to determine if a context is part of a certain offering, but more explicit tagging of contexts according to the offering keeps things readable. Lastly the configuration parameter "com.openexchange.config.cascade.types" (which is itself config cascade enabled) adds its value to the tag list, so, for example:<br />
<br />
friendly_users:<br />
withTags: groupware_plus & beta<br />
com.openexchange.config.cascade.types: friendly_and_paying<br />
<br />
Would add the friendly_and_paying tag to all contexts already classified as groupware_plus and beta. Also since this value can also be specified on user level, you could classify users irrespective of their contexts, should the need arise. <br />
<br />
The third line then specifies the setting to override. You can specify all properties to override in this block, so if we wanted to enable both twitter and rss messaging for these contexts, we'd use the following configuration:<br />
<br />
experimental_gw_plus:<br />
withTags: groupware_plus & beta<br />
com.openexchange.messaging.twitter: true<br />
com.openexchange.messaging.rss: true<br />
<br />
Most configuration use cases can probably be handled with the context sets system. Only if a configuration is truly unique for just one context or user should the other options be pursued.<br />
<br />
== Specifying Configuration - Context Scope and User Scope ==<br />
<br />
Configuration options can be overridden on user and context level, using a dynamic property. For example:<br />
<br />
$ createcontext [...] --config/com.openexchange.messaging.twitter=true<br />
$ changecontext [...] --config/com.openexchange.messaging.twitter=true<br />
<br />
$ createuser [...] --config/com.openexchange.messaging.twitter=true<br />
$ changeuser [...] --config/com.openexchange.messaging.twitter=true<br />
<br />
Depending on the number of users and contexts in your system, this could pose a problem further down the road when you need to update this value for a large number of users.<br />
<br />
To remove such a setting again the following syntax can be used:<br />
<br />
$ changecontext [...] --remove-config/com.openexchange.messaging.twitter<br />
$ changeuser [...] --remove-config/com.openexchange.messaging.twitter<br />
<br />
== UI Properties ==<br />
<br />
A common use case for the OX configuration system is to allow fine-tuning of the UI by providing configuration data on the backend. All properties defined in properties files below <tt>/opt/open-xchange/etc/groupware/settings</tt> are transported to the UI and are config cascade enabled. So every customization you can specify for the UI using these settings, can also be selectively overridden with the config cascade.<br />
<br />
Since the config cascade only overrides existing settings, whether a property is a UI property or a server property is automatically determined by the directory in which the corresponding <tt>.properties</tt> file is found. For example if <tt>/opt/open-xchange/etc/settings/appsuite.properties</tt> contains the setting<br />
<br />
io.ox/core//theme=default<br />
<br />
Then you can overwrite it for any context (or user, context set, etc.):<br />
<br />
$ changecontext [...] --config/io.ox/core//theme=org.example.theme<br />
<br />
The values are first parsed using [http://json.org/ JSON] syntax. If that fails, they are interpreted as plain strings.<br />
<br />
== Further Reading ==<br />
<br />
[[ConfigCascadeCookbook]] - Collects typical configuration scenarios and how to handle them using the config cascade.</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:Dynamic_Theme&diff=20619AppSuite:Dynamic Theme2015-10-02T10:07:19Z<p>Viktor.Pracht: /* Installation */ redundant "version" in "version OX App Suite v"</p>
<hr />
<div>{{Stability-unstable}}<br />
<br />
<div class="title">Dynamic Theming</div><br />
<br />
The dynamic theme plugin allows to have custom colors and logo without creating a real theme for each possible color combination. The customization information is stored in the [[ConfigCascade|Configuration Cascade]] and applied at runtime, immediately after login.<br />
<br />
== Installation ==<br />
<br />
The theme generator consists of the single package <tt>open-xchange-dynamic-theme</tt>, which is installed on the OX middleware.<br />
<br />
Before OX App Suite v7.6.2, the package included the command line tool <tt>/opt/open-xchange/sbin/update-dynamic-theme</tt>, which must be called after every update of other plugins. It is called automatically after the installation and upgrades of <tt>open-xchange-dynamic-theme</tt>. The tool examines all installed <tt>.less</tt> files and computes which CSS rules need to be changed to apply the custom colors everywhere.<br />
<br />
Since v7.6.2, the tool is called automatically whenever necessary, so it is not necessary to call it manually, and therefore it is not installed in the <tt>/opt/open-xchange/sbin/</tt> directory anymore.<br />
<br />
== Configuration ==<br />
<br />
=== Enabling the Plugin ===<br />
<br />
The plugin is enabled or disabled by the [[AppSuite:Capabilities|capability]] <tt>dynamic-theme</tt>, e.g. in a file <tt>/opt/open-xchange/etc/dynamic-theme.properties</tt> set<br />
<br />
com.openexchange.capability.dynamic-theme=true<br />
<br />
When using the plugin, the actual theme should be the built-in <tt>default</tt> theme. To prevent all users from changing it and hide the theme selector in the preferences, set the property <tt>io.ox/core//theme</tt> to read-only. To do this, change the file <tt>/opt/open-xchange/etc/meta/appsuite.yaml</tt> as follows: <br />
<br />
io.ox/core//theme:<br />
protected: true<br />
<br />
If some users won't use dynamic themes, this approach won't work. Instead, the theme selector can be disabled an enabled by controlling the list of available themes. The theme selector is hidden if the list is empty. To be able to do that with the Configuration Cascade, the entire list of themes needs to be specified as a single JSON value, e.g. by changing the file <tt>/opt/open-xchange/etc/settings/appsuite.properties</tt> as follows:<br />
<br />
io.ox/core/settingOptions//themes={"default":"Default Theme"}<br />
<br />
Then, to hide the theme selector for users with a dynamic theme, use the Configuration Cascade to change the value to <tt>{}</tt>.<br />
<br />
=== Specifying a Theme ===<br />
<br />
The package installs the file <tt>/opt/open-xchange/etc/settings/open-xchange-dynamic-theme.properties</tt>, which contains the global defaults for the custom theme settings. Any of the settings contained in that file can be changed per-context or at any other granularity supported by the [[ConfigCascade#UI_Properties|Configuration Cascade]]. The individual settings are as follows:<br />
<br />
<table class="wikitable" style="width:auto"><br />
<tr><th>Prefix</th><br />
<th> Key </th><th> Default value </th></tr><br />
<tr><td rowspan="5" style="vertical-align:middle"><tt>io.ox/dynamic-theme//</tt></td><br />
<td><tt> frameColor </tt></td><td><tt> #333 </tt></td></tr><br />
<tr><td><tt> iconColor </tt></td><td><tt> #bbb </tt></td></tr><br />
<tr><td><tt> selectionColor </tt></td><td><tt> #39a9e1 </tt></td></tr><br />
<tr><td><tt> logoWidth </tt></td><td><tt> 60 </tt></td></tr><br />
<tr><td><tt> logoURL </tt></td><td><br />
<tt> apps/themes/default/logo-small.png </tt></td></tr><br />
</table><br />
<br />
The colors can be any CSS color; <tt>logoWidth</tt> is specified in pixels; <tt>logoURL</tt> can be relative (to <tt>/appsuite/</tt>), or absolute. When using absolute URLs to point to different hosts, use the form <tt>//<var>hostname</var>/<var>path</var></tt> to keep the protocol (HTTP or HTTPS) and avoid any unnecessary security warnings.<br />
<br />
== Maintenance ==<br />
<br />
The source file <tt>apps/io.ox/dynamic-theme/definitions.less.in</tt> contains the Less rules for the theme. All keys in the namespace <tt>io.ox/dynamic-theme//</tt> are converted to Less variables by prefixing them with <tt>@io-ox-dynamic-theme-</tt>. The set of keys in the following files must be kept in sync:<br />
* <tt>apps/io.ox/dynamic-themes/definitions.less.in</tt><br />
* <tt>apps/io.ox/dynamic-theme/settings/defaults.js</tt><br />
* <tt>lib/update-dynamic-theme.js</tt><br />
* <tt>conf/settings/open-xchange-dynamic-theme.properties</tt></div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:Dynamic_Theme&diff=20617AppSuite:Dynamic Theme2015-10-02T09:55:59Z<p>Viktor.Pracht: Created page with "{{Stability-unstable}} <div class="title">Dynamic Theming</div> The dynamic theme plugin allows to have custom colors and logo without creating a real theme for each possibl..."</p>
<hr />
<div>{{Stability-unstable}}<br />
<br />
<div class="title">Dynamic Theming</div><br />
<br />
The dynamic theme plugin allows to have custom colors and logo without creating a real theme for each possible color combination. The customization information is stored in the [[ConfigCascade|Configuration Cascade]] and applied at runtime, immediately after login.<br />
<br />
== Installation ==<br />
<br />
The theme generator consists of the single package <tt>open-xchange-dynamic-theme</tt>, which is installed on the OX middleware.<br />
<br />
Before version 7.6.2, the package included the command line tool <tt>/opt/open-xchange/sbin/update-dynamic-theme</tt>, which must be called after every update of other plugins. It is called automatically after the installation and upgrades of <tt>open-xchange-dynamic-theme</tt>. The tool examines all installed <tt>.less</tt> files and computes which CSS rules need to be changed to apply the custom colors everywhere.<br />
<br />
Since version 7.6.2, the tool is called automatically whenever necessary, so it is not necessary to call it manually, and therefore it is not installed in the <tt>/opt/open-xchange/sbin/</tt> directory anymore.<br />
<br />
== Configuration ==<br />
<br />
=== Enabling the Plugin ===<br />
<br />
The plugin is enabled or disabled by the [[AppSuite:Capabilities|capability]] <tt>dynamic-theme</tt>, e.g. in a file <tt>/opt/open-xchange/etc/dynamic-theme.properties</tt> set<br />
<br />
com.openexchange.capability.dynamic-theme=true<br />
<br />
When using the plugin, the actual theme should be the built-in <tt>default</tt> theme. To prevent all users from changing it and hide the theme selector in the preferences, set the property <tt>io.ox/core//theme</tt> to read-only. To do this, change the file <tt>/opt/open-xchange/etc/meta/appsuite.yaml</tt> as follows: <br />
<br />
io.ox/core//theme:<br />
protected: true<br />
<br />
If some users won't use dynamic themes, this approach won't work. Instead, the theme selector can be disabled an enabled by controlling the list of available themes. The theme selector is hidden if the list is empty. To be able to do that with the Configuration Cascade, the entire list of themes needs to be specified as a single JSON value, e.g. by changing the file <tt>/opt/open-xchange/etc/settings/appsuite.properties</tt> as follows:<br />
<br />
io.ox/core/settingOptions//themes={"default":"Default Theme"}<br />
<br />
Then, to hide the theme selector for users with a dynamic theme, use the Configuration Cascade to change the value to <tt>{}</tt>.<br />
<br />
=== Specifying a Theme ===<br />
<br />
The package installs the file <tt>/opt/open-xchange/etc/settings/open-xchange-dynamic-theme.properties</tt>, which contains the global defaults for the custom theme settings. Any of the settings contained in that file can be changed per-context or at any other granularity supported by the [[ConfigCascade#UI_Properties|Configuration Cascade]]. The individual settings are as follows:<br />
<br />
<table class="wikitable" style="width:auto"><br />
<tr><th>Prefix</th><br />
<th> Key </th><th> Default value </th></tr><br />
<tr><td rowspan="5" style="vertical-align:middle"><tt>io.ox/dynamic-theme//</tt></td><br />
<td><tt> frameColor </tt></td><td><tt> #333 </tt></td></tr><br />
<tr><td><tt> iconColor </tt></td><td><tt> #bbb </tt></td></tr><br />
<tr><td><tt> selectionColor </tt></td><td><tt> #39a9e1 </tt></td></tr><br />
<tr><td><tt> logoWidth </tt></td><td><tt> 60 </tt></td></tr><br />
<tr><td><tt> logoURL </tt></td><td><br />
<tt> apps/themes/default/logo-small.png </tt></td></tr><br />
</table><br />
<br />
The colors can be any CSS color; <tt>logoWidth</tt> is specified in pixels; <tt>logoURL</tt> can be relative (to <tt>/appsuite/</tt>), or absolute. When using absolute URLs to point to different hosts, use the form <tt>//<var>hostname</var>/<var>path</var></tt> to keep the protocol (HTTP or HTTPS) and avoid any unnecessary security warnings.<br />
<br />
== Maintenance ==<br />
<br />
The source file <tt>apps/io.ox/dynamic-theme/definitions.less.in</tt> contains the Less rules for the theme. All keys in the namespace <tt>io.ox/dynamic-theme//</tt> are converted to Less variables by prefixing them with <tt>@io-ox-dynamic-theme-</tt>. The set of keys in the following files must be kept in sync:<br />
* <tt>apps/io.ox/dynamic-themes/definitions.less.in</tt><br />
* <tt>apps/io.ox/dynamic-theme/settings/defaults.js</tt><br />
* <tt>lib/update-dynamic-theme.js</tt><br />
* <tt>conf/settings/open-xchange-dynamic-theme.properties</tt></div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=Portal:AppSuite_UI/Topics&diff=20595Portal:AppSuite UI/Topics2015-10-02T08:31:13Z<p>Viktor.Pracht: added Dynamic theme</p>
<hr />
<div>== Getting started ==<br />
* [[AppSuite:GettingStarted | Getting started developing an external app]]<br />
* [[AppSuite:Upgrade_app_using_yo | Upgrade your external app to latest App Suite version]]<br />
* [[AppSuite:UI developer primer| Skills needed to develop the UI]]<br />
* [[AppSuite:Getting started developing the UI | Getting started developing the UI]]<br />
* [[AppSuite:UI_Development_Style_Guide | UI Development Style Guide]]<br />
* [[AppSuite:Appserver | Appserver]]<br />
* [[AppSuite:Apache Configuration | Apache Configuration]]<br />
* [[AppSuite:Definition of done|Definition of done]]<br />
* [[Appsuite:UI_FAQ | Frequently asked questions]]<br />
<br />
== Upgrading apps, plugins, and themes to 7.6 ==<br />
* [[AppSuite:Upgrading_to_7_6|Upgrading to 7.6]]<br />
<br />
== Testing ==<br />
* [[AppSuite:Test basics | Lessons learned while testing]]<br />
* [[AppSuite:RunTests | Running ui tests]]<br />
* [[AppSuite:Testing_3rd-party_code | In-depth article on testing]] aimed at external developers<br />
<br />
== How-to articles ==<br />
* [[AppSuite:Action links|Understanding action links]]<br />
** [[AppSuite:Files App Actions|Adding actions to the files app]]<br />
* [[AppSuite:Date_and_time|Date and time]]<br />
* [[AppSuite:i18n | Internationalization (i18n)]]<br />
* [[AppSuite:a11y | Accessibility (a11y)]]<br />
* [[AppSuite:Mediaplayer | Mediaplayer]]<br />
* [[AppSuite:Theming | Theming]]<br />
** [[AppSuite:Dynamic Theme|The Dynamic Theme plugin]]<br />
* [[AppSuite:UI manifests explained | UI manifests explained]]<br />
* [[AppSuite:Upsell | Upsell]]<br />
* [[AppSuite:VGrid | VGrid]]<br />
* [[AppSuite:Mobile | Mobile development]]<br />
* [[AppSuite:Upsell tools| Upsell tools]]<br />
* [[AppSuite:Guided tours| Guided tours]]<br />
* [[AppSuite:Browserdetection | Browser detection with form-login]]<br />
* [[AppSuite:BackboneMiniViews | Backbone mini views]]<br />
<br />
=== Server communication ===<br />
* [[AppSuite:APIs | APIs]]<br />
* [[AppSuite:API_Factory | API Factory]]<br />
* [[AppSuite:http.js | http.js]]<br />
<br />
=== Extension points ===<br />
* [[AppSuite:Extending_the_UI_(Hands-on_introduction)| Hands-on introduction]]<br />
* [[AppSuite:Extending_the_UI | General information on extension points]]<br />
* [[AppSuite:Modifying forms by using extension points | Modifying forms]]<br />
* [[AppSuite:Create custom folderview entries in settings app | Edit folderview entries in settings]]<br />
* [[AppSuite:Extension points for calendar |extension points: Calendar]]<br />
* [[AppSuite:Extension points for contact |extension points: Contact]]<br />
* [[AppSuite:Extension points for core | extension points: Core]]<br />
* [[AppSuite:Extension points for email | extension points: E-Mail]]<br />
* [[AppSuite:Extension points for files |extension points: Files]]<br />
* [[AppSuite:Extension points for tasks |extension points: Tasks]]<br />
* [[AppSuite:Extension points for miscellaneous |extension points: Miscellaneous]]<br />
<br />
=== Writing components ===<br />
* [[AppSuite:Writing a portal plugin | Writing a portal plugin]]<br />
** [[AppSuite:Configuring portal plugins|Configuring a portal plugin]]<br />
** [[AppSuite:Using the Upsell widget|Using the Upsell widget]]<br />
* [[AppSuite:Writing a simple application | Writing a simple application]]<br />
* [[AppSuite:Writing a simple application with embedded iframe | Writing a simple application with embedded iframe and launcher link ]]<br />
* [[AppSuite:Writing a notification area plugin | Writing a plugin for the notification area]]<br />
* [[AppSuite:Writing a wizard | Writing a wizard]]<br />
* [[AppSuite:Capabilities | Capabilities explained]] - if you want to enable or disable your plugin<br />
<br />
== Miscellaneous articles ==<br />
* [[AppSuite:External libraries for the UI | External libraries used by the UI]]<br />
* [[AppSuite:Configuration| Configuration]]<br />
* [[AppSuite:Custom configurations| Custom configurations]]<br />
* [[AppSuite:UI build system| The UI build system]]<br />
* [[AppSuite:Embedding your settings into AppSuite settings|How to embed your own settings into the Appsuite settings page]]<br />
* [[AppSuite:Debugging the UI|Debugging the UI]]<br />
* [[Appsuite:Debugging production servers|Debugging production servers]]<br />
* [[AppSuite:Memory leaks (UI)|Finding memory leaks in the UI]]<br />
* [[AppSuite:Device reference|_.device() reference]]<br />
* [[AppSuite:Paste inline images|Paste inline images]]<br />
* All articles regarding the UI are filed in the category [[:Category:UI]]</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:Debugging_production_servers&diff=20540AppSuite:Debugging production servers2015-09-22T12:35:11Z<p>Viktor.Pracht: Added certificate generation</p>
<hr />
<div>{{Stability-experimental}}<br />
<div class="title">Debugging production servers</div><br />
<br />
A how-to for debugging your local UI plugin in combination with production and staging servers, which use redirects, HTTPS, and other things which break with the auto-generated Grunt configuration.<br />
<br />
== Introduction ==<br />
<br />
Not everybody has access to a dedicated test server. Sometimes, a plugin requires a backend system which is hard to access outside of existing infrastructure. And sometimes, a bug appears only on a production server. There are many reasons why a server which is used by <tt>grunt dev</tt> can not be reconfigured and has to be used as-is.<br />
<br />
The most frequent reason, why debugging with a remote server fails, is a redirect to an external login page. After the login, the browser is usually redirected to the original domain, and all the cookies used for authentication are also set for that domain, not http://localhost:8337, where Grunt listens.<br />
<br />
The solution is to use grunt as an HTTP proxy server, which intercepts all requests to the server's domain.<br />
<br />
In this article, <tt>''example.com''</tt> is user for the server domain, which you should replace by the real domain of the OX server.<br />
<br />
== Configuring Grunt ==<br />
<br />
Following is an example <tt>grunt/local.conf.json</tt> file:<br />
<br />
{<br />
"proxy": true,<br />
"appserver": {<br />
"protocol": "https",<br />
"livereload": false,<br />
"server": "https://''example.com''/''custom-path''/",<br />
"path": "/''custom-path''/",<br />
"rejectUnauthorized": false,<br />
"verbose": [],<br />
"prefixes": [<br />
"build/",<br />
"../../web/ui/build"<br />
],<br />
"manifests": [<br />
"build/manifests/",<br />
"../../web/ui/build/manifests"<br />
]<br />
},<br />
"debug": true,<br />
"coreDir": "../../web/ui/build"<br />
}<br />
<br />
The relevant settings are:<br />
<br />
;<tt>"proxy": true</tt><br />
: instructs Grunt to start an HTTP proxy on port 8080. Note that the value is outside the <tt>"appserver"</tt> section.<br />
;<tt>"protocol": "https"</tt><br />
: to use HTTPS on port 8337.<br />
;<tt>"livereload": false</tt><br />
: because LiveReload can't be proxied.<br />
;<tt>"path": "/''custom-path''/"</tt><br />
: must correspond to the path in the <tt>"server"</tt> entry and can be omitted if it's <tt>"/appsuite/"</tt>.<br />
;<tt>"rejectUnauthorized": false</tt><br />
: is helpful with certificate problems, especially for integration tests of the login mechanism on a POC system with self-signed certificates.<br />
;<tt>"index": "/"</tt><br />
: If the main path uses an HTTP redirect for a custom login page, then the initial request should not be intercepted by Grunt. Adding this entry in the <tt>"appserver"</tt> section disables the interception. This has two side-effects:<br />
:# The main HTML file is always served by the original server, and therefore<br />
:# The timestamps used for cache-busting are not updated by Grunt.<br />
:Unfortunately, this means clearing the cache will be required more often. If that becomes too much overhead, you can log in, then remove the option and restart Grunt.<br />
<br />
== Generating certificates ==<br />
<br />
To avoid unnecessary warnings in the browser, Grunt can use a set of certificates which are trusted by the browser. For local use, a self-created CA should be enough. By default, Grunt looks for the certificates in the subdirectory <tt>ssl</tt>, so you can create them there with the following commands:<br />
<br />
mkdir ssl<br />
cd ssl<br />
openssl req -x509 -newkey rsa:4096 -keyout rootCA.key -days 3650 -out rootCA.crt<br />
openssl req -newkey rsa:4096 -keyout host.key -out host.csr<br />
<br />
While most data entered for the certificates doesn't matter, the Common Name for the certificate signing request in the second <tt>openssl</tt> command must match the domain of the <tt>"server"</tt> setting in <tt>local.conf.json</tt>. Alternatively, it can be a higher domain with a wildcard, e.g. <tt>*.example.com</tt> for <tt>"server": "https://my.example.com/appsuite/"</tt>.<br />
<br />
openssl x509 -req -in host.csr -CA rootCA.crt -CAkey rootCA.key \<br />
-CAcreateserial -out host.crt -days 365<br />
<br />
<tt>host.csr</tt> is only temporary and can be deleted now. Only the files <tt>rootCA.crt</tt>, <tt>host.key</tt> and <tt>host.crt</tt> are used by Grunt. The <tt>rootCA.*</tt> files can be reused to create multiple host certificates. The first <tt>openssl</tt> command then only needs to be executed once. The <tt>host.*</tt> files can also be reused as long as the domain(-wildcard) matches.<br />
<br />
The file <tt>rootCA.crt</tt> needs to be imported into your browser as a trusted certificate authority (only once, if you are going to reuse the <tt>rootCA.*</tt> files). For Firefox, look in Preferences &rarr; Advanced &rarr; Certificates &rarr; View Certificates &rarr; Authorities &rarr; Import...<br />
For Chrome, look in Settings &rarr; Show advanced settings... &rarr; HTTPS/SSL &rarr; Manage certificates... &rarr; Authorities &rarr; Import...<br />
Since the authority can sign certificates for any domain, and its key is not protected much, it's better to not use the browser(-profile) which trusts this authority for normal Internet browsing.<br />
<br />
== Launching the browser ==<br />
<br />
After starting the proxy with <tt>grunt dev</tt>, you just need to use it when debugging your code in the browser. Most browsers have their own proxy settings, which override system-wide settings. They also respect environment variables like <tt>http_proxy</tt>.<br />
<br />
http_proxy=http://localhost:8080 firefox<br />
<br />
Chrome does not have its own settings (it starts the global settings dialog) and it ignores <tt>http_proxy</tt>. Instead, you have to use a command line parameter:<br />
<br />
chromium --proxy-server=http://localhost:8080</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:Debugging_production_servers&diff=20507AppSuite:Debugging production servers2015-09-22T09:30:47Z<p>Viktor.Pracht: Described the new proxy feature of grunt dev</p>
<hr />
<div>{{Stability-experimental}}<br />
<div class="title">Debugging production servers</div><br />
<br />
A how-to for debugging your local UI plugin in combination with production and staging servers, which use redirects, HTTPS, and other things which break with the auto-generated Grunt configuration.<br />
<br />
== Introduction ==<br />
<br />
Not everybody has access to a dedicated test server. Sometimes, a plugin requires a backend system which is hard to access outside of existing infrastructure. And sometimes, a bug appears only on a production server. There are many reasons why a server which is used by <tt>grunt dev</tt> can not be reconfigured and has to be used as-is.<br />
<br />
The most frequent reason, why debugging with a remote server fails, is a redirect to an external login page. After the login, the browser is usually redirected to the original domain, and all the cookies used for authentication are also set for that domain, not http://localhost:8337, where Grunt listens.<br />
<br />
The solution is to use grunt as an HTTP proxy server, which intercepts all requests to the server's domain.<br />
<br />
In this article, <tt>''example.com''</tt> is user for the server domain, which you should replace by the real domain of the OX server.<br />
<br />
== Configuring Grunt ==<br />
<br />
Following is an example <tt>grunt/local.conf.json</tt> file:<br />
<br />
{<br />
"proxy": true,<br />
"appserver": {<br />
"protocol": "https",<br />
"livereload": false,<br />
"server": "https://''example.com''/''custom-path''/",<br />
"path": "/''custom-path''/",<br />
"rejectUnauthorized": false,<br />
"verbose": [],<br />
"prefixes": [<br />
"build/",<br />
"../../web/ui/build"<br />
],<br />
"manifests": [<br />
"build/manifests/",<br />
"../../web/ui/build/manifests"<br />
]<br />
},<br />
"debug": true,<br />
"coreDir": "../../web/ui/build"<br />
}<br />
<br />
The relevant settings are:<br />
<br />
;<tt>"proxy": true</tt><br />
: instructs Grunt to start an HTTP proxy on port 8080. Note that the value is outside the <tt>"appserver"</tt> section.<br />
;<tt>"protocol": "https"</tt><br />
: to use HTTPS on port 8337.<br />
;<tt>"livereload": false</tt><br />
: because LiveReload can't be proxied.<br />
;<tt>"path": "/''custom-path''/"</tt><br />
: must correspond to the path in the <tt>"server"</tt> entry and can be omitted if it's <tt>"/appsuite/"</tt>.<br />
;<tt>"rejectUnauthorized": false</tt><br />
: is helpful with certificate problems, especially for integration tests of the login mechanism on a POC system with self-signed certificates.<br />
;<tt>"index": "/"</tt><br />
: If the main path uses an HTTP redirect for a custom login page, then the initial request should not be intercepted by Grunt. Adding this entry in the <tt>"appserver"</tt> section disables the interception. This has two side-effects:<br />
:# The main HTML file is always served by the original server, and therefore<br />
:# The timestamps used for cache-busting are not updated by Grunt.<br />
:Unfortunately, this means clearing the cache will be required more often. If that becomes too much overhead, you can log in, then remove the option and restart Grunt.<br />
<br />
After the configuration is complete, Grunt is started like always with<br />
<br />
grunt dev<br />
<br />
== Launching the browser ==<br />
<br />
Now that the proxy is running, you just need to use it when debugging your code in the browser. Most browsers have their own proxy settings, which override system-wide settings. They also respect environment variables like <tt>http_proxy</tt>.<br />
<br />
http_proxy=http://localhost:8080 firefox<br />
<br />
Chrome does not have its own settings (it starts the global settings dialog) and it ignores http_proxy. Instead, you have to use a command line parameter:<br />
<br />
chromium --proxy-server=http://localhost:8080</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:Debugging_production_servers&diff=20289AppSuite:Debugging production servers2015-09-01T09:56:17Z<p>Viktor.Pracht: /* Squid */ Added SquidMan link</p>
<hr />
<div>{{Stability-experimental}}<br />
<div class="title">Debugging production servers</div><br />
<br />
A how-to for debugging your local UI plugin in combination with production and staging servers, which use redirects, HTTPS, and other things which break with a simple <tt>grunt dev</tt> command.<br />
<br />
== Introduction ==<br />
<br />
Not everybody has access to a dedicated test server. Sometimes, a plugin requires a backend system which is hard to access outside of existing infrastructure. And sometimes, a bug appears only on a production server. There are many reasons why a server which is used by <tt>grunt dev</tt> can not be reconfigured and has to be used as-is.<br />
<br />
The most frequent reason, why debugging with a remote server fails, are redirects to an external login page. After the login, the browser is usually redirected to the original domain, and all the cookies used for authentication are also set for that domain, not http://localhost:8337, where Grunt listens.<br />
<br />
The solution is to use a proxy server, which redirects all requests to the server's domain to Grunt. Until <tt>grunt dev</tt> can be used as an HTTP proxy directly, a dedicated proxy is required. This proxy needs to support custom hosts files. Any kind of rewriting or forwarding usually ends up in the wrong domain being used, and therefore still breaking cookies and redirects. The global <tt>/etc/hosts</tt> can't be used because Grunt still needs to access the original server, and use the original domain name for that to properly set the <tt>Host</tt> header.<br />
<br />
The usual way to use a custom hosts file is to set it in the <tt>HOSTALIASES</tt> environment variable. Unfortunately, for security reasons, this variable is explicitly cleared when executing setuid processes. And this is exactly what proxy servers tend to do. A proxy server with explicit configuration support for custom hosts files is Squid. So that's what we will use for debugging.<br />
<br />
== HOWTO ==<br />
<br />
All commands are specified for Debian. Commands which need to be run as root start with <tt>#</tt>, commands which can be run as a normal user start with <tt>$</tt>.<br />
<br />
The examples use <tt>''user''</tt> as user name, and all temporary files are stored in <tt>/home/''user''/proxy</tt>. You should use your own directory, and can pick any other directory. For the server domain, we'll use <tt>''example.com''</tt>, which should of course be replaced by the real domain of the OX server.<br />
<br />
=== Squid ===<br />
<br />
Install Squid.<br />
<br />
# apt-get install squid3<br />
<br />
Copy your <tt>/etc/hosts</tt> file to another location.<br />
<br />
$ cp /etc/hosts /home/''user''/proxy/hosts<br />
<br />
Add a line which redirects the target domain to localhost.<br />
<br />
$ echo '127.0.0.1 ''example.com''<nowiki/>' >> /home/''user''/proxy/hosts<br />
<br />
Now this file can be added to Squid's configuration file.<br />
<br />
# echo 'hosts_file /home/''user''/proxy/hosts' >> /etc/squid3/squid.conf<br />
# service squid3 reload<br />
<br />
For Macs, there's [http://squidman.net/squidman/ SquidMan]. It has a preferences item where you can edit the configuration file.<br />
<br />
=== Grunt ===<br />
<br />
Assuming you already have a working <tt>local.conf.json</tt>, add the following entries to the <tt>"appserver"</tt> section:<br />
<br />
"protocol": "https",<br />
"port": 443,<br />
"server": "https://''example.com''/''custom-path''/",<br />
"rejectUnauthorized": false,<br />
"path": "/''custom-path''",<br />
<br />
The entry <tt>"path"</tt> is optional, if the default <tt>/appsuite</tt> is used.<br />
<br />
If the main path uses an HTTP redirect for a custom login page, then the initial request can't be intercepted by Grunt. The following entry disables it:<br />
<br />
"index": "/",<br />
<br />
This has two side-effects:<br />
# The mail HTML file is always served by the original server, and therefore<br />
# The timestamps used for cache-busting are not updated by Grunt.<br />
<br />
This means clearing the cache will be required more often. If that becomes too much overhead, you can log in, then remove the option and restart Grunt.<br />
<br />
=== Running <tt>grunt dev</tt>===<br />
<br />
Since Grunt needs to bind to port 443, it requires additional privileges. There are several options. Running Grunt as root is the quickest, but also least secure way. Better alternatives are <tt>authbind</tt> and <tt>setcap</tt>.<br />
<br />
Don't forget to stop your local web server (e.g. Apache),<br />
<br />
# service apache2 stop<br />
<br />
or at least disable SSL.<br />
<br />
# a2dismod ssl<br />
# service apache2 restart<br />
<br />
==== <tt>authbind</tt> ====<br />
<br />
<tt>authbind</tt> is a program which uses a setuid helper to bind to lower ports. It is usually not installed by default.<br />
<br />
# apt-get install authbind<br />
<br />
The configuration is performed by creating files in <tt>/etc/authbind</tt> and giving execute permissions to the appropriate users.<br />
<br />
# touch /etc/authbind/443<br />
# chown ''user'' /etc/authbind/443<br />
# chmod 544 /etc/authbind<br />
<br />
Now, Grunt can be started using the wrapper.<br />
<br />
$ authbind --deep grunt dev<br />
<br />
==== <tt>setcap</tt> ====<br />
<br />
This option can be used if your file system supports capabilities. It is less secure since it grants the permission to bind to all low ports to any Node program. But if supported, it at least does not require additional tools.<br />
<br />
# setcap "cap_net_bind_service=+ep" "$(readlink -f "$(which node)")"<br />
<br />
On OS X, <tt>greadlink</tt> needs to be used instead of <tt>readlink</tt>. If you don't have it, just find out where the actual <tt>node</tt> binary is installed and use it directly as the second parameter to <tt>setcap</tt>.<br />
<br />
Grunt can then be run as usual.<br />
<br />
$ grunt dev<br />
<br />
=== Launching the browser ===<br />
<br />
Now that everything is running, you only need to use the proxy when debugging your code in the browser. Most browsers have their own proxy settings, which override system-wide settings. They also respect environment variables like <tt>http_proxy</tt>.<br />
<br />
$ http_proxy=http://localhost:3128 firefox<br />
<br />
Chrome does not have its own settings (it starts the global settings dialog) and it ignores http_proxy. Instead, you have to use a command line parameter:<br />
<br />
$ chromium --proxy-server=http://localhost:3128</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=HTTP_API&diff=19995HTTP API2015-07-17T13:31:44Z<p>Viktor.Pracht: /* Get all mails */ Documented the spam flag</p>
<hr />
<div>== Introduction ==<br />
<br />
This document defines the Open-Xchange HTTP API which is used by the new AJAX GUI. The first chapter describes general definitions and conventions which apply to all server modules. All other chapters describe individual server modules.<br />
<br />
=== Low level protocol ===<br />
<br />
The client accesses the server through HTTP GET, POST and PUT requests. HTTP cookies are used for authentication and must therefore be processed and sent back by the client as specified by [http://tools.ietf.org/html/rfc6265 RFC 6265]. The HTTP API is accessible at URIs starting with <code>/ajax</code>. Each server module has a unique name and its own sub-namespace with that name below <code>/ajax</code>, e. g. all access to the module "tasks" is via URIs starting with <code>/ajax/tasks</code>.<br />
<br />
Text encoding is always UTF-8. Data is sent from the server to the client as <code>text/javascript</code> and interpreted by the client to obtain an ECMAScript object. The HTTP API uses only a small subset of the ECMAScript syntax. This subset is roughly described by the following BNF:<br />
<br />
Value ::= "null" | Boolean | Number | String | Array | Object<br />
Boolean ::= "true" | "false"<br />
Number ::= see NumericLiteral in ECMA 262 3rd edition<br />
String ::= \"([^"\n\\]|\\["\n\\])*\"<br />
Array ::= "[]" | "[" Value ("," Value)* "]"<br />
Object ::= "{}" | "{" Name ":" Value ("," Name ":" Value)* "}"<br />
Name ::= [A-Fa-f][0-9A-Fa-f_]*<br />
<br />
Numbers are the standard signed integer and floating point numbers. Strings can contain any character, except double quotes, newlines and backslashes, which must be escaped by a backslash. Control characters in strings (other than newline) are not supported. Whitespace is allowed between any two tokens. See [http://json.org JSON] and [http://www.ecma-international.org/publications/standards/Ecma-262.htm ECMA 262, 3<sup>rd</sup> edition] for the formal definition.<br />
<br />
The response body consists of an object, which contains up to four fields as described in [[#ResponseBody | Response body]]. The field <code>data</code> contains the actual payload which is described in following chapters. The fields <code>timestamp</code>, <code>error</code> and <code>error_params</code> are present when data objects are returned, if an error occurred and if the error message contains conversion specifiers, respectively. Following sections describe the contents of these fields in more detail.<br />
<br />
{| id="ResponseBody" cellspacing="0" border="1"<br />
|+ align="bottom" | Response body<br />
! Name !! Type !! Value<br />
|-<br />
| data || Value || Payload of the response.<br />
|-<br />
| timestamp || Timestamp || The latest timestamp of the returned data (see [[HTTP_API#Updates|Updates]]).<br />
|-<br />
| error || String || The translated error message. Present in case of errors.<br />
|-<br />
| error_params || Array || As o 7.4.2: Empty JSON array. Before that: Parameters for the error message that would need to be replaced in the error string (in a printf-format style).<br />
|-<br />
| error_id || String || Unique error identifier to help finding this error instance in the server logs.<br />
|-<br />
| error_desc || String || The technical error message (always English) useful for debugging the problem. Might be the same as error message if there is no more information available<br />
|-<br />
| code || String || Error code consisting of an upper-case module identifier and a four-digit message number, separated by a dash; e.g. "MSG-0012"<br />
|-<br />
| error_stack || Array || If configured (see "com.openexchange.ajax.response.includeStackTraceOnError" in 'server.properties') this field provides the stack trace of associated Java exception represented as a JSON array<br />
|-<br />
| categories || String OR Array || Either a single (String) or list (Array) of upper-case category identifiers to which the error belongs. E.g.<br />
{| cellspacing="0" border="1"<br />
| "USER_INPUT" || An error resulting from wrong or missing input from front-end (e.g. mandatory field missing).<br />
|-<br />
| "CONFIGURATION" || An error related to user/system configuration which denies requested operation.<br />
|-<br />
| "PERMISSION_DENIED" || An error related to insufficient permission settings.<br />
|-<br />
| "TRY_AGAIN" || A requested operation could not be accomplished because a needed resource is temporary down or missing (e.g. imap server rejects connection because of too many established connections).<br />
|-<br />
| "SERVICE_DOWN" || A subsystem or third party service is down and therefore does not respond (e.g. database is down).<br />
|-<br />
| "CONNECTIVITY" || The underlying socket connection is corrupt, empty or closed. Only a temporary error that does not affect the whole system.<br />
|-<br />
| "ERROR" || A programming error which was caused by incorrect program code.<br />
|-<br />
| "CONFLICT" || A concurrent modification.<br />
|-<br />
| "CAPACITY" || The requested operation could not be performed cause an underlying resource is full or busy (e.g. IMAP folder exceeds quota).<br />
|-<br />
| "TRUNCATED" || The given data could not be stored into the database because an attribute contains a too long value.<br />
|-<br />
| "WARNING" || Action was at least partially successful, but a condition occurred that merited a warning<br />
|}<br />
|-<br />
| category || Number || Maintained for legacy reasons: The numeric representation of the first category:<br />
{| cellspacing="0" border="1"<br />
| 1 || An error resulting from wrong or missing input from front-end (e.g. mandatory field missing).<br />
|-<br />
| 2 || An error strictly related to user configuration which denies requested operation.<br />
|-<br />
| 3 || An error related to insufficient permission settings.<br />
|-<br />
| 4 || A requested operation could not be accomplished because a needed resource is temporary down or missing (e.g. imap server rejects connection because of too many established connections).<br />
|-<br />
| 5 || A subsystem or third party service is down and therefore does not respond (e.g. database is down).<br />
|-<br />
| 6 || The underlying socket connection is corrupt, empty or closed. Only a temporary error that does not affect the whole system.<br />
|-<br />
| 8 || A programming error which was caused by incorrect programm code.<br />
|-<br />
| 9 || A concurrent modification.<br />
|-<br />
| 11 || The requested operation could not be performed cause an underlying resource is full or busy (e.g. IMAP folder exceeds quota).<br />
|-<br />
| 12 || The given data could not be stored into the database because an attribute contains a too long value.<br />
|-<br />
| 13 || Action was at least partially successful, but a condition occurred that merited a warning<br />
|}<br />
|}<br />
<br />
Data from the client to the server can be sent in several formats. Small amounts of data are sent as <code>application/x-www-urlencoded</code> in query parameters in the request URI. For POST requests, some or all parameters may be sent in the request body instead of in the URI using any valid encoding for POST requests. Alternatively, some requests specify that data is sent as <code>text/javascript</code> in the body of a PUT request. The format of the request body for PUT requests is the same as for sending data from the server to the client, except that the payload is sent directly, without being wrapped in another object.<br />
<br />
When updating existing data, the client sends only fields that were modified. To explicitly delete a field, the field is sent with the value <code>null</code>. For fields of type <code>String</code>, the empty string <code>""</code> is equivalent to <code>null</code>.<br />
<br />
=== Error handling ===<br />
<br />
If the session of the user times out, if the client doesn't send a session ID or if the session for the specified session ID can not be found then the server returns the above described response object, that contains an error code and an error message. If the request URI or the request body is malformed or incomplete then the server returns the reponse object with an error message, too. In case of internal server errors, especially Java exceptions, or if the server is down, it returns the HTTP status code 503, Service Unavailable. Other severe errors may return other HTTP status values.<br />
<br />
Application errors, which can be caused by a user and are therefore expected during the operation of the groupware, are reported by setting the field error in the returned object, as described in [[#ResponseBody | Response body]]. Since the error messages are translated by the client, they can not be composed of multiple variable parts. Instead, the error message can contain simplified printf()-style conversion specifications, which are replaced by elements from the array in the field error_params. If error_params is not present, no replacement occurs, even if parts of the error message match the syntax of a conversion specification.<br />
<br />
A simplified conversion specification, as used for error messages, is either of the form %s or %''n''$s, where ''n'' is a 1-based decimal parameter index. The conversion specifications are replaced from left to right by elements from error_params, starting at the first element. %s is replaced by the current element and the current index is incremented. %''n''$s is replaced by the ''n''th element and the current index is set to the (''n'' + 1)th element.<br />
<br />
Some error message contain data sizes which must be expressed in Bytes or Kilobytes etc., depending on the actual value. Since the unit must be translated, this conversion is performed by the client. Unfortunately, standard printf()-style formatting does not have a specifier for this kind of translation. Therefore, the conversion specification for sizes is the same as for normal strings, and the client has to determine which parameters to translate based on the error code. The current error codes and the corresponding size parameters are listed in [[#DataSizeParameters | Data size parameters]]<br />
<br />
{| id="DataSizeParameters" cellspacing="0" border="1"<br />
|+ align="bottom" | Data size parameters<br />
! Error code !! Parameter indices<br />
|-<br />
| CON-0101 || 2, 3<br />
|-<br />
| FLS-0003 || 1, 2, 3<br />
|-<br />
| MSG-0065 || 1, 3<br />
|-<br />
| MSG-0066 || 1<br />
|-<br />
| NON-0005 || 1, 2<br />
|-<br />
|}<br />
<br />
<br />
=== Date and time ===<br />
<br />
Dates without time are transmitted as the number of milliseconds between 00:00 UTC on that date and 1970-01-01 00:00 UTC. Leap seconds are ignored, therefore this number is always an integer multiple of 8.64e7.<br />
<br />
Because ECMAScript Date objects have no way to explicitly specify a timezone for calculations, timezone correction must be performed on the server. Dates with time are transmitted as the number of milliseconds since 1970-01-01 00:00 UTC (again, ignoring leap seconds) plus the offset between the ''user's'' timezone and UTC at the time in question. (See the Java method java.util.TimeZone.getOffset(long)). Unless optional URL parameter <code>'''timezone'''</code> is present. Then dates with time are transmitted as the number of milliseconds since 1970-01-01 00:00 UTC (again, ignoring leap seconds) plus the offset between the ''specified'' timezone and UTC at the time in question.<br />
<br />
For some date and time values, especially timestamps, monotonicity is more important than the actual value. Such values are transmitted as the number of milliseconds since 1970-01-01 00:00 UTC, ignoring leap seconds and without timezone correction. If possible, a unique strictly monotonic increasing value should be used instead, as it avoids some race conditions described below.<br />
<br />
This specification refers to these three interpretations of the type Number as separate data types. The types are described in [[#DateAndTimeTypes | Date and time types]].<br />
<br />
{| id="DateAndTimeTypes" cellspacing="0" border="1"<br />
|+ align="bottom" | Date and time types<br />
! Type !! Time !! Timezone !! Comment<br />
|-<br />
| Date || No || UTC || Date without time.<br />
|-<br />
| Time || Yes || User || Date and time.<br />
|-<br />
| Timestamp || Yes || UTC || Timestamp or unique sequence number.<br />
|-<br />
|}<br />
<br />
=== Updates ===<br />
<br />
To allow efficient synchronization of a client with changes made by other clients and to detect conflicts, the server stores a timestamp of the last modification for each object. Whenever the server transmits data objects to the client, the response object described in [[#ResponseBody | Response body]] includes the field timestamp. This field contains a timestamp value which is computed as the maximum of the timestamps of all transmitted objects.<br />
<br />
When requesting updates to a previously retrieved set of objects, the client sends the last timestamp which belongs to that set of objects. The response contains all updates with timestamps greater than the one specified by the client. The field timestamp of the response contains the new maximum timestamp value.<br />
<br />
If multiple different objects may have the same timestamp values, then a race condition exists when an update is processed between two such objects being modified. The first, already modified object will be included in the update response and its timestamp will be the maximum timestamp value sent in the timestamp field of the response. If the second object is modified later but gets the same timestamp, the client will never see the update to that object because the next update request from the client supplies the same timestamp value, but only modifications with greater timestamp values are returned.<br />
<br />
If unique sequence numbers can't be used as timestamps, then the risk of the race condition can be at least minimized by storing timestamps in the most precise format and/or limiting update results to changes with timestamp values which are measurably smaller than the current timestamp value.<br />
<br />
=== Editing ===<br />
<br />
Editing objects is performed one object at a time. There may be multiple objects being edited by the same client simulataneously, but this is achieved by repeating the steps required for editing a single object. There is no batch edit or upload command.<br />
<br />
To edit an object, a client first requests the entire object from the server. The server response contains the timestamp field described in the previous section. For in-place editing inside a view of multiple objects, where only already retrieved fields can be changed, retrieving the entire object is not necessary, and the last timestamp of the view is used as the timestamp of each object in it.<br />
<br />
When sending the modified object back to the server, only modified fields need to be included in the sent object. The request also includes the timestamp of the edited object. The timestamp is used by the server to ensure that the object was not edited by another client in the meantime. If the current timestamp of the object is greater than the timestamp supplied by the client, then a conflict is detected and the field error is set in the response. Otherwise, the object gets a new timestamp and the response to the client is empty.<br />
<br />
If the client displays the edited object in a view together with other objects, then the client will need to perform an update of that view immediately after successfully uploading an edited object.<br />
<br />
=== File uploads ===<br />
<br />
File uploads are made by sending a POST request that submits both the file and the needed fields as parts of a request of content-type “multipart/form-data” or “multipart/mixed”. The file metadata are stored in a form field “file” (much like an <input type=”file” name=”file” /> would do). In general a call that allows file uploads via POST will have a corresponding call using PUT to send object data. The JSON-encoded object-data that is send as the body of a corresponding PUT call is, when performed as a POST with file uploads, put into the request parameter “json”.<br />
<br />
Since the upload is performed directly by the browser and is not an Ajax call, the normal callback mechanism for asynchronous Javascript calls cannot be used to obtain the result. For this reason the server responds to these POST calls with a complete HTML page that performs the callback and should not be displayed to the user. The HTML response is functionally equivalent to:<br />
<br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html><br />
<head><br />
<META http-equiv="Content-Type" content=\"text/html; charset=UTF-8\"><br />
<script type="text/javascript"><br />
(parent["callback_<b>action</b>"] || window.opener && window.opener["callback_<b>action</b>"])<br />
(<b>{json}</b>)<br />
</script><br />
</head><br />
</html><br />
<br />
The placeholders <code>{json}</code> is replaced by the response with the timestamp that would be expected from the corresponding PUT method. The placeholder <code>action</code> is replaced by the value of the parameter <code>action</code> of the request (except for the import bundle, which is named "import" instead of the action name for legacy purposes). The content-type of the answer is <code>text/html</code>.<br />
<br />
Non-browser clients don't need to interpret HTML or JavaScript. The JSON data can be recognized by the outermost <code>({</code> and <code>})</code>, where the inner braces are part of the JSON value. For example, the regular expression <code>\((\{.*\})\)</code> captures the entire JSON value in its first capturing group.<br />
<br />
=== Documentation conventions ===<br />
<br />
The rest of this document describes all available requests for each module. A module usually supports several different requests, which are differentiated by the used HTTP method, URI path and supplied URI parameters. The description of each method generally contains the following elements:<br />
* the HTTP method followed by the request URI, inclusing the URI parameter action, which is used to differentiate methods,<br />
* a list of URI parameters which can or must be supplied by the client,<br />
* for PUT requests, content of the request body,<br />
* "Response with timestamp:"if the timestamp field is required in the response body or simply "Response:" if not,<br />
* content of the response payload, unless it is supposed to be empty.<br />
<br />
=== Common object data ===<br />
<br />
This table contains common fields which apply for any module's data type and is referenced throughout this document whenever a module's data type is described.<br />
<br />
{| id="CommonObjectData" cellspacing="0" border="1"<br />
|+ align="bottom" | Common object data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 1 || id || String || Object ID<br />
|-<br />
| 2 || created_by || String || User ID of the user who created this object.<br />
|-<br />
| 3 || modified_by || String || User ID of the user who last modified this object.<br />
|-<br />
| 4 || creation_date || Time || Date and time of creation.<br />
|-<br />
| 5 || last_modified || Time || Date and time of the last modification.<br />
|-<br />
| 20 || folder_id || String || Object ID of the parent folder.<br />
|-<br />
| 100 || categories || String || String containing comma separated the categories. Order is preserved. Changing the order counts as modification of the object. Not present in folder objects.<br />
|-<br />
| 101 || private_flag || Boolean || Overrides folder permissions in shared private folders: When true, this object is not visible to anyone except the owner. Not present in folder objects.<br />
|-<br />
| 102 || color_label || Number || Color number used by Outlook to label the object. The assignment of colors to numbers is arbitrary and specified by the client. The numbers are integer numbers between 0 and 10 (inclusive). Not present in folder objects.<br />
|-<br />
| 104 || number_of_attachments || Number || Number of attachments <br />
|-<br />
| 105 || lastModifiedOfNewestAttachmentUTC || Time || Date and time of the newest attachment written with UTC time zone.<br />
|}<br />
<br />
== Module "login" ==<br />
<br />
The login module is used to obtain a session from the user's login credentials. To understand the details of the different login methods, see the article titled "[[Login variations]]".<br />
<br />
=== Login ===<br />
<br />
POST <code>/ajax/login?action=login</code><br />
<br />
Parameters:<br />
* <code>name</code> – The login name.<br />
* <code>password</code> – The password.<br />
* <code>authId</code> (optional) – Identifier for tracing every single login request passed between different systems in a cluster. The value should be some token that is unique for every login request. This parameter must be given as URL parameter and not inside the body of the POST request.<br />
* <code>client</code> (optional) – Identifier of the client using the HTTP/JSON interface. This is for statistic evaluations what clients are used with Open-Xchange.<br />
* <code>version</code> (optional) – Used version of the HTTP/JSON interface client.<br />
* <code>clientIP</code> (optional) – IP address of the client host for that the session is created. If this parameter is not specified the IP address of the HTTP client doing this request is used.<br />
* <code>clientUserAgent</code> (optional) – Value of the User-Agent header of the client host for that the session is created. If this parameter is not specified the User-Agent of the current HTTP client doing this request is used.<br />
<br />
Response: A JSON object containing the session ID used for all subsequent requests. Additionally a random token is contained to be used for the Easy Login method.<br />
<br />
=== Form Login (since 6.20) ===<br />
<br />
POST <code>/ajax/login?action=formlogin</code><br />
<br />
This request implements a possible login to the web frontend by only using a simple HTML form. An example for such a form can be found in the backend's documentation folder (<code>/usr/share/doc/open-xchange-core</code>) under <code>examples/login.html</code>.<br />
<br />
Parameters:<br />
* <code>login</code> – The login name.<br />
* <code>password</code> – The password.<br />
* <code>authId</code> – Identifier for tracing every single login request passed between different systems in a cluster. The value should be some token that is unique for every login request. This parameter must be given as URL parameter and not inside the body of the POST request.<br />
* <code>client</code> – Identifier of the client using the HTTP/JSON interface. This is for statistic evaluations what clients are used with Open-Xchange. If the autologin request should work the client must be the same as the client sent by the UI in the normal login request.<br />
* <code>version</code> – Used version of the HTTP/JSON interface client.<br />
* <code>autologin</code> – True or false. True tells the UI to issue a store request for the session cookie. This store request is necessary if you want the autologin request not to fail.<br />
* <code>uiWebPath</code> (optional) – Defines another path on the web server where the UI is located. If this parameter is not defined the configured default of the backend is used.<br />
* <code>clientIP</code> (optional) – IP address of the client host for that the session is created. If this parameter is not specified the IP address of the HTTP client doing this request is used.<br />
* <code>clientUserAgent</code> (optional) – Value of the User-Agent header of the client host for that the session is created. If this parameter is not specified the User-Agent of the current HTTP client doing this request is used.<br />
<br />
Response: A redirect to the web UI. The URL of the web UI is either taken from the given parameter or from the configured default of the backend.<br />
<br />
For a complete description of the FormLogin-Process please see [[FormLogin|this documentation]]<br />
<br />
=== Token Login (since 7.0.1) ===<br />
<br />
POST <code>/ajax/login?action=tokenLogin</code><br />
<br />
This request allows every possible client to create a very short living session. This session can then be transferred to any other client preferably a browser entering then the normal web interface. Then the sessions life time will be extended equally to every other session.<br />
<br />
Compared to the login mechanism using the random token, this request is more secure because two tokens are used. One of these tokens is only known to the client and one is generated by the server. Only the combination of both tokens allows to use the session. The combination of both tokens must be done by the client creating the session.<br />
<br />
Parameters:<br />
* <code>login</code> – The login information.<br />
* <code>password</code> – The password.<br />
* <code>clientToken</code> – Client side identifier for accessing the session later. The value should be some token that is unique for every login request.<br />
* <code>authId</code> – Identifier for tracing every single login request passed between different systems in a cluster. The value should be some token that is unique for every login request. This parameter must be given as URL parameter and not inside the body of the POST request.<br />
* <code>client</code> – Identifier of the client using the HTTP/JSON interface. This is for statistic evaluations what clients are used with Open-Xchange. If the autologin request should work the client should be the same as the client sent by the UI in the normal login request. For security considerations it can become necessary to define here the correct client that will use the session.<br />
* <code>version</code> – Version of the HTTP/JSON interface client. Only for statistic evaluations.<br />
* <code>autologin</code> – True or false. True tells the UI to issue a store request for the session cookie. This store request is necessary if you want the autologin request not to fail. This must be enabled on the server and a client can test with the autologin request if it is enabled or not.<br />
* <code>uiWebPath</code> (optional) – Defines another path on the web server where the UI is located. If this parameter is not defined the configured default of the backend is used.<br />
* <code>clientIP</code> (optional) – IP address of the client host for that the session is created. If this parameter is not specified the IP address of the HTTP client doing this request is used. Currently the IP address may change when using the session with both tokens. This can be disabled in future releases for security considerations.<br />
* <code>clientUserAgent</code> (optional) – Value of the User-Agent header of the client host for that the session is created. If this parameter is not specified the User-Agent of the current HTTP client doing this request is used. Currently the User-Agent may change when using the session. This can be disabled in future releases for security considerations.<br />
* <code>jsonResponse</code> (optional, since 7.8.0) – true or false (default). Defines the returned data type as JSON. Default 'false' will return a redirect. <br />
<br />
<br />
Response: A redirect to the web UI (or JSON including the redirect url in case jsonResponse=true is set). The URL of the web UI is either taken from the given parameter or from the configured default of the backend. This redirect will only contain the server side token. The client side token sent in the request must be appended by the client creating the session. The final URL must have the form <code style="white-space: nowrap"><var>redirect_URL</var>&amp;clientToken=<var>token</var></code>. Both tokens are necessary to use the session and both tokens must match. Otherwise the session is terminated.<br />
<br />
=== Tokens (since 7.0.1) ===<br />
<br />
POST <code>/ajax/login?action=tokens</code><br />
<br />
This request allows clients to access a session created with the [[#Token_Login_.28since_7.0.1.29 | tokenLogin]] request. When accessing the session its life time is extended equally to every other session.<br />
<br />
Parameters:<br />
* <code>serverToken</code> – Server side identifier for accessing the session. This identifier was created by the server and is contained in the tokenLogin response.<br />
* <code>clientToken</code> – Client side identifier for accessing the session. This identifier was created by the client and passed within the POST data of the tokenLogin request.<br />
* <code>client</code> – Identifier of the client using the HTTP/JSON interface. Currently this request allows to change the client identifier for the session. This eases creating the session because the identifier of the client using the session must not be known. For security considerations it can become necessary to drop this parameter.<br />
<br />
<br />
Response: A JSON object conform to the normal [[#ResponseBody | response body]] contrary to the JSON object of the normal login request. This JSON object contains the session identifier, the login, the identifier and the locale of the user.<br />
<br />
=== Logout ===<br />
<br />
GET <code>/ajax/login?action=logout</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
=== Refresh secret cookie (since 6.18.2) ===<br />
<br />
GET <code>/ajax/login?action=refreshSecret</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
=== Refresh auto-login cookie ===<br />
<br />
GET <code>/ajax/login?action=store</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
=== Redirect ===<br />
<br />
GET <code>/ajax/login;jsessionid=1157370816112.OX1?action=redirect</code><br />
<br />
'''SECURITY WARNING!''' Utilizing this request is '''INSECURE'''! This request allows to access a session with a single one time token. This one time token may be delivered to the wrong client if the protocol has an error or Apache or the load balancer make a mistake. This will cause a wrong user to be in a wrong session. '''IMMEDIATELY''' consider not to use this request anymore. You have been warned. Use instead the FormLogin that does not need to use the redirect request.<br />
<br />
Parameters:<br />
* <code>random</code> – A session random token to jump into the session. This random token is part of the login response. Only a very short configurable time after the login it is allowed to jump into the session with the random token.<br />
* <code>client</code> (optional) – The client can be defined here newly if it is not correct on the login request itself.<br />
* <code>store</code> (optional) – Tells the UI to do a store request after login to be able to use autologin request.<br />
* <code>uiWebPath</code> (optional) – The optional path on the webserver to the UI. If this parameter is not given the configured uiWebPath is used.<br />
<br />
=== Change IP ===<br />
<br />
The following request is especially for integration with systems located in the providers infrastructure. If those systems create a session with the following request the client host IP address in the session can be changed. The IP check for following requests will be done using this newly set client host IP address.<br />
<br />
POST <code>/ajax/login?action=changeip</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>clientIP</code> – New IP address of the client host for the current session.<br />
<br />
Response: A JSON object containing the string "1" as data attribute.<br />
<br />
=== Redeem Token (since 7.4.0)===<br />
<br />
POST <code>/ajax/login?action=redeemToken</code><br />
<br />
Parameters:<br />
* <code>token</code> – The token created with [[#Get_a_login_token | acquireToken]].<br />
* <code>authId</code> – Identifier for tracing every single login request passed between different systems in a cluster. The value should be some token that is unique for every login request. This parameter must be given as URL parameter and not inside the body of the POST request. <br />
* <code>client</code> – Identifier of the client using the HTTP/JSON interface. The client must identifier must be the same for each request after creating the login session. <br />
* <code>secret</code> – The value of the secret string for token logins. This is configured through the tokenlogin-secrets configuration file.<br />
<br />
Response: A JSON object containing the session ID used for all subsequent requests. Additionally a random token is contained to be used for the Easy Login method. If configured within tokenlogin-secrets configuration file even the user password will be returned.<br />
<br />
== Module "config" ==<br />
<br />
The config module is used to retrieve and set user-specific configuration. The configuration is stored in a tree. Each node of the tree has a name and a value. The values of leaf nodes are strings which store the actual configuration data. The values of inner nodes are defined recursively as objects with one field for each child node. The name and the value of each field is the name and the value of the corresponding child node, respectively.<br />
<br />
The namespace looks like the following:<br />
<br />
* <code>/ajax/config/</code><br />
** <code>gui</code> – A string containing GUI-specific settings (currently, it is a huge [[#Low_level_protocol | JSON]] object).<br />
** <code>fastgui</code> - A string containing GUI-specific settings. This is a JSON object that must be kept small for performance.<br />
** <code>context_id</code> - the unique identifier of the context (read-only, added 2008-01-28).<br />
** <code>cookielifetime</code> - the cookie life time in seconds or <code>-1</code> for session cookie (read-only, added 2010-11-16).<br />
** <code>identifier</code> – the unique identifier of the user (read-only).<br />
** <code>contact_id</code> – the unique identifier of the contact data of the user (read-only).<br />
** <code>language</code> – the configured language of the user.<br />
** <code>timezone</code> – the configured timezone of the user.<br />
** <code>availableTimeZones</code> – a JSON object containing all available time zones. The key is the time zone identifier and the value contains its name in users language. (read-only, added 2010-07-08/v6.18).<br />
** <code>calendarnotification</code> - send a mail notification for appointments (deprecated since 2008-12-11)<br />
** <code>tasknotification</code> - send a mail notification for tasks (deprecated since 2008-12-11)<br />
** <code>reloadTimes</code> - Selectable times for GUI reload<br />
** <code>serverVersion</code> - Version string of the server.<br />
** <code>currentTime</code> - User timezone specific long of the current server time.<br />
** <code>maxUploadIdleTimeout</code> - Timeout after that idle uploads are deleted.<br />
** <code>folder/</code> – the standard folder of the user<br />
*** <code>tasks</code> – the standard task folder (read-only)<br />
*** <code>calendar</code> – the standard calendar folder (read-only)<br />
*** <code>contacts</code> – the standard contacts folder (read-only)<br />
*** <code>infostore</code> – the private infostore folder (read-only, since v6.20.1)<br />
*** <code>eas</code> – whether EAS folder selection is enabled (read-only)<br />
** <code>mail/</code> – settings for the email module (deprecated 2008-04-29)<br />
*** <code>addresses</code> – all email addresses of the user including the primary address (read-only, deprecated 2008-04-29)<br />
*** <code>defaultaddress</code> – primary email address of the user (read-only, deprecated 2008-04-29)<br />
*** <code>sendaddress</code> – one email address out of the addresses list that are email sent with. (deprecated 2008-04-29)<br />
*** <code>folder/</code> – the standard email folders (read-only, deprecated 2008-04-29)<br />
**** <code>inbox</code> – identifier of the folder that gets all incoming mails (read-only, deprecated 2008-04-29)<br />
**** <code>drafts</code> – identifier of the folder with the mail drafts (read-only, deprecated 2008-04-29)<br />
**** <code>trash</code> – identifier of the folder with the deleted mails (read-only, deprecated 2008-04-29)<br />
**** <code>spam</code> – identifier of the folder with the spam mails (read-only, deprecated 2008-04-29)<br />
**** <code>sent</code> – identifier of the folder with the sent mails (read-only, deprecated 2008-04-29)<br />
*** <code>htmlinline</code> – activate inlining of HTML attachments. (deprecated 2008-04-29)<br />
*** <code>colorquote</code> – color quoted lines. (deprecated 2008-04-29)<br />
*** <code>emoticons</code> – display emoticons as graphics. (deprecated 2008-04-29)<br />
*** <code>harddelete</code> – delete emails at once. (deprecated 2008-04-29)<br />
*** <code>inlineforward</code> – forward messages as inline or attachment. (deprecated 2008-04-29)<br />
*** <code>vcard</code> – attach vcard when sending mails. (deprecated 2008-04-29)<br />
*** <code>notifyonreadack</code> – notify on read acknowledgement. (deprecated 2008-04-29)<br />
*** <code>msgpreview</code> – show a message preview. (deprecated 2008-04-29)<br />
*** <code>ignorereplytext</code> (deprecated 2008-04-29)<br />
*** <code>nocopytosent</code> – don't put a copy to the sent folder when sending mails. (deprecated 2008-04-29)<br />
*** <code>spambutton</code> - Spam Button should be displayed in GUI or not. (deprecated 2008-04-29)<br />
** <code>participants</code><br />
*** <code>autoSearch</code> - If a search for all users, groups and resources when participant selection dialog is opened. (read-only, added 2008-10-09/SP5)<br />
*** <code>maximumNumberParticipants</code> – Defines the maximum number of participants for appointments and tasks. (read-only, added 2008-10-20/SP5)<br />
*** <code>showWithoutEmail</code> - If external participants without email should be shown.<br />
*** <code>showDialog</code> – Enables participant selection dialog for appointments and tasks. (read-only, added 2008-04-30/SP4)<br />
** <code>availableModules</code> – Contains a JSON array listing all enabled modules for a user. GUI loads Plugins through this list. To get your plugin listed here, create a subtree below <code>modules/</code> without a <code>module</code> subelement or with a subelement containing <code>true</code> (read-only, added 2008-02-25)<br />
** <code>minimumSearchCharacters</code> – Minimum number of characters a search pattern must have to prevent large responses and slow queries. (read-only, added 2008-10-20/SP5)<br />
** <code>modules</code><br />
*** <code>portal</code><br />
**** <code>gui</code> GUI settings for portal module<br />
**** <code>module</code><br />
*** <code>mail</code><br />
**** <code>addresses</code> – all email addresses of the user including the primary address (read-only, added 2008-02-25)<br />
**** <code>appendmailtext</code> – (added 2008-02-25)<br />
**** <code>allowhtmlimages</code> – Alters default setting whether external images contained in HTML content are allowed or not (added 2008-05-27)<br />
**** <code>colorquoted</code> – color quoted lines (added 2008-02-25)<br />
**** <code>contactCollectFolder</code> – contact folder id to save mail addresses from sent mails (added 2008-10-16)<br />
**** <code>contactCollectEnabled</code> – switch contact collection on/off (added 2008-10-16)<br />
**** <code>contactCollectOnMailAccess</code> – enables/disables contact collection for incoming mails. Default is true. (added 2009-09-24)<br />
**** <code>contactCollectOnMailTransport</code> – enables/disables contact collection for outgoing mails. Default is true. (added 2009-09-24)<br />
**** <code>defaultaddress</code> – primary email address of the user (read-only, added 2008-02-25)<br />
**** <code>deletemail</code> – delete emails or move to trash (added 2008-02-25)<br />
**** <code>emoticons</code> – display emoticons as graphics (added 2008-02-25)<br />
**** <code>defaultFolder</code><br />
***** <code>drafts</code> – identifier of the folder with the mail drafts (read-only, added 2008-02-25)<br />
***** <code>inbox</code> – identifier of the folder that gets all incoming mails (read-only, added 2008-02-25)<br />
***** <code>sent</code> – identifier of the folder with the sent mails (read-only, added 2008-02-25)<br />
***** <code>spam</code> – identifier of the folder with the spam mails (read-only, added 2008-02-25)<br />
***** <code>trash</code> – identifier of the folder with the deleted mails (read-only, added 2008-02-25)<br />
**** <code>forwardmessage</code> – forward messages as inline or attachment (added 2008-02-25)<br />
**** <code>gui</code> GUI settings for mail module<br />
**** <code>inlineattachments</code> – activate inlining of HTML attachments (added 2008-02-25)<br />
**** <code>linewrap</code> – (added 2008-02-25)<br />
**** <code>module</code> – if mail module is enabled or not (added 2008-02-25)<br />
**** <code>phishingheaders</code> – header(s) identifying phishing headers (added 2008-05-27)<br />
**** <code>replyallcc</code> – put all recipients on reply all into CC (added 2008-12-16/SP5)<br />
**** <code>sendaddress</code> – one email address out of the addresses list that are email sent with (added 2008-02-25)<br />
**** <code>spambutton</code> – Spam Button should be displayed in GUI or not (added 2008-02-25)<br />
**** <code>vcard</code> – attach vcard when sending mails (added 2008-02-25)<br />
*** <code>calendar</code><br />
**** <code>calendar_conflict</code><br />
**** <code>calendar_freebusy</code><br />
**** <code>calendar_teamview</code><br />
**** <code>gui</code> GUI settings for the calendar module<br />
**** <code>module</code><br />
**** <code>notifyNewModifiedDeleted</code> receive mail notification for new, modified or deleted appointments (added 2008-12-11/SP5)<br />
**** <code>notifyAcceptedDeclinedAsCreator</code> receive mail notification for accepted or declined appointments created by the user (added 2008-12-11/SP5)<br />
**** <code>notifyAcceptedDeclinedAsParticipant</code> receive mail notification for accepted or declined appointments that the user participates (added 2008-12-11/SP5)<br />
**** <code>defaultStatusPrivate</code> Default status for new appointments in private folders, where the user is participant. This does not affect appointments created by this user, which always have the status "accepted". The status are described in [[#UserParticipantObject | User participant object]]. Default is 0:none (added 2009-07-20/6.12)<br />
**** <code>defaultStatusPublic</code> Default status for new appointments in public folders, where the user is participant. This does not affect appointments created by this user, which always have the status "accepted". The status are described in [[#UserParticipantObject | User participant object]]. Default is 0:none (added 2009-07-20/6.12)<br />
*** <code>contacts</code><br />
**** <code>gui</code> GUI settings for the contacts module<br />
**** <code>mailAddressAutoSearch</code> – Define if a search is triggered when the recipient selection dialog is opened or the folder is changed. (read-only, added 2008-10-20/SP5)<br />
**** <code>module</code> True if the contact module is enabled for the current user, false otherwise.<br />
**** <code>singleFolderSearch</code> – True if the current user is allowed to search for contacts only in a single folder. False if contact searches across all folders are allowed. (read-only, added 2009-02-04/SP5 U1)<br />
**** <code>characterSearch</code> – True if the side bar for searching for contacts by a start letter should be displayed. False if the side bar should be hidden. (read-only, added 2009-05-29/6.10)<br />
**** <code>allFoldersForAutoComplete</code> – true if an auto complete search may omit the folder identifier array and search for contacts in all readable folders. This is configured through the contact.properties configuration file. (read-only, added 2010-07-22/v6.18.0)<br />
*** <code>tasks</code><br />
**** <code>gui</code> GUI settings for the tasks module<br />
**** <code>module</code><br />
**** <code>delegate_tasks</code><br />
**** <code>notifyNewModifiedDeleted</code> receive mail notification for new, modified or deleted tasks (added 2008-12-11/SP5)<br />
**** <code>notifyAcceptedDeclinedAsCreator</code> receive mail notification for accepted or declined tasks created by the user (added 2008-12-11/SP5)<br />
**** <code>notifyAcceptedDeclinedAsParticipant</code> receive mail notification for accepted or declined taks that the user participates (added 2008-12-11/SP5)<br />
*** <code>infostore</code><br />
**** <code>gui</code> GUI settings for the infostore module<br />
**** <code>folder</code> – the standard infostore folders (read-only, since 7.6.0)<br />
***** <code>trash</code> – identifier of the default infostore trash folder (read-only, since 7.6.0)<br />
***** <code>pictures</code> – identifier of the default infostore pictures folder (read-only, since 7.8.0)<br />
***** <code>documents</code> – identifier of the default infostore documents folder (read-only, since 7.8.0)<br />
***** <code>music</code> – identifier of the default infostore music folder (read-only, since 7.8.0)<br />
***** <code>videos</code> – identifier of the default infostore videos folder (read-only, since 7.8.0)<br />
***** <code>templates</code> – identifier of the default infostore templates folder (read-only, since 7.8.0)<br />
**** <code>module</code><br />
*** <code>interfaces</code><br />
**** <code>ical</code><br />
**** <code>vcard</code><br />
**** <code>syncml</code><br />
*** <code>folder</code><br />
**** <code>gui</code> UI settings for the folder tree<br />
**** <code>public_folders</code><br />
**** <code>read_create_shared_folders</code><br />
**** <code>tree</code> – Selected folder tree, the user wants to use. Currents trees are 0 for the known OX folder tree and 1 for the new virtual folder tree. (added 2010-04-09/6.18)<br />
*** <code>com.openexchange.extras</code><br />
**** <code>module</code> – Extras link in the configuration (read only, added 2008-04-29)<br />
*** <code>com.openexchange.user.passwordchange</code><br />
**** <code>module</code> – Will load Plug-In which allows to change the Password within the users configuration (read only, added 2008-07-09)<br />
*** <code>com.openexchange.user.personaldata</code><br />
**** <code>module</code> – Will load Plug-In which allows to edit personal contact information within the users configuration (read only, added 2008-07-09)<br />
*** <code>com.openexchange.group</code><br />
**** <code>enabled</code> – Specifies whether the user is allowed to edit groups and loads the corresponding Plug-In. (read only, added 2008-08-08)<br />
*** <code>com.openexchange.resource</code><br />
**** <code>enabled</code> – Specifies whether the user is allowed to edit resources and loads the corresponding Plug-In. (read only, added 2008-08-08)<br />
*** <code>com.openexchange.publish</code><br />
**** <code>enabled</code> – Specifies whether the user is allowed to publish items. (read only, added 2009-05-27)<br />
*** <code>com.openexchange.subscribe</code><br />
**** <code>enabled</code> – Specifies whether the user is allowed to subscribe sources. (read only, added 2009-05-27)<br />
*** <code>olox20</code><br />
**** <code>active</code> – Tells the UI if the user is allowed to use the OXtender for Microsoft Outlook 2. (read only, added 2011-03-15/6.20)<br />
**** <code>module</code> – Is set to false to prevent the UI from trying to load a plugin. (read only, added 2011-03-15/6.20)<br />
***<code>com.openexchange.oxupdater</code><br />
****<code>module</code> – Is true if the OXUpdater package is installed and started. (read only, added 2011-06-01/6.20)<br />
****<code>active</code> – Is true if the user is allowed to download the OXUpdater. Otherwise it's false. (read only, added 2011-06-01/6.20)<br />
***<code>com.openexchange.passwordchange</code><br />
**** <code>showStrength</code> – Show a widget, which displays the current passwort Strength while entering. (default: false)<br />
**** <code>minLength</code> – The minimum length of an entered password. (default: 4)<br />
**** <code>maxLength</code> – The maximum length of an entered password. 0 for unlimited. (default: 0)<br />
**** <code>regexp</code> – Defines the class of allowed special characters as Regular Expression. (default: [^a-z0-9])<br />
**** <code>special</code> – Shows an example of allowed special characters to the user. Should be a subset of "regexp" in a human readable format. (default: $, _, or %) <br />
<br />
=== Get configuration data ===<br />
<br />
GET <code>/ajax/config/path</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: Value of the node specified by path.<br />
<br />
=== Set configuration data ===<br />
<br />
PUT <code>/ajax/config/path</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: The new value of the node specified by path.<br />
<br />
<br />
=== Get a property (since 7.6.2) ===<br />
<br />
GET <code>/ajax/config?action=get_property</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>name</code> – The name of the property to return.<br />
<br />
Response: A JSON response providing the property's name and its value; e.g.<br />
<code><br />
{<br />
"data": {<br />
"name": "com.openexchange.dummy.prop001",<br />
"value": "test1234"<br />
}<br />
}<br />
</code><br />
<br />
=== Set a property (since 7.6.2) ===<br />
<br />
Note: Only allowed for context administrator!<br />
<br />
PUT <code>/ajax/config?action=set_property</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>name</code> – The name of the property to set.<br />
<br />
Request body: A JSON object providing the value to set; e.g<br />
<code><br />
{"value":"test1237"}<br />
</code><br />
<br />
<br />
Response: A JSON response providing the property's name and its new value; e.g.<br />
<code><br />
{<br />
"data": {<br />
"name": "com.openexchange.dummy.prop001",<br />
"value": "test1237"<br />
}<br />
}<br />
</code><br />
<br />
== Module "folders" ==<br />
<br />
The folders module is used to access the OX folder structure.<br />
<br />
=== Special System Folders ===<br />
<br />
Folders with some kind of special.<br />
<br />
{| cellspacing="0" border="1"<br />
! ID !! Type !! Description<br />
|-<br />
| 6 || contacts || System Users<br />
|}<br />
<br />
=== Get root folders ===<br />
<br />
GET <code>/ajax/folders?action=root</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Response: An array with data for all folders at the root level of the folder structure. Each array element describes one folder and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="CommonFolderData" cellspacing="0" border="1"<br />
|+ align="bottom" | Common folder data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 1 || id || String || Object ID<br />
|-<br />
| 2 || created_by || String || User ID of the user who created this object.<br />
|-<br />
| 3 || modified_by || String || User ID of the user who last modified this object.<br />
|-<br />
| 4 || creation_date || Time || Date and time of creation.<br />
|-<br />
| 5 || last_modified || Time || Date and time of the last modification.<br />
|-<br />
| 6 || last_modified_utc || Timestamp || Timestamp of the last modification. Note that the type is Timestamp, not Time. See [[#Date and time]] for details. (added 2008-10-17, with SP5, temporary workaround)<br />
|-<br />
| 20 || folder_id || String || Object ID of the parent folder.<br />
|}<br />
<br />
{| id="DetailedFolderData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed folder data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 300 || title || String || Name of this folder.<br />
|-<br />
| 301 || module || String || Name of the module which implements this folder; e.g. "tasks", "calendar", "contacts", "infostore", or "mail"<br />
|-<br />
| 302 || type || Number || Type of folder:<br />
{| cellspacing="0" border="1"<br />
| 1 || private<br />
|-<br />
| 2 || public<br />
|-<br />
| 3 || shared<br />
|-<br />
| 5 || system folder<br />
|-<br />
| 7 || This type is no more in use (legacy type). Will be removed with a future update!<br />
|-<br />
| 16 || trash<br />
|-<br />
| 20 || pictures<br />
|-<br />
| 21 || documents<br />
|-<br />
| 22 || music<br />
|-<br />
| 23 || videos<br />
|-<br />
| 24 || templates<br />
|}<br />
|-<br />
| 304 || subfolders || Boolean || true if this folder has subfolders.<br />
|-<br />
| 305 || own_rights || Number or String || Permissions which apply to the current user, as described either in [[#PermissionFlags | Permission flags]] or in RFC 2086.<br />
|-<br />
| 306 || permissions || Array || Each element is an object described in [[#PermissionObject | Permission object]].<br />
|-<br />
| 307 || summary || String || Information about contained objects.<br />
|-<br />
| 308 || standard_folder || Boolean || Indicates whether or not folder is marked as a default folder (only OX folder)<br />
|-<br />
| 309 || total || Number || The number of objects in this Folder.<br />
|-<br />
| 310 || new || Number || The number of new objects in this Folder.<br />
|-<br />
| 311 || unread || Number || The number of unread objects in this Folder.<br />
|-<br />
| 312 || deleted || Number || The number of deleted objects in this Folder.<br />
|-<br />
| 313 || capabilities || Number || Bit mask containing information about mailing system capabilites, as described in [[#Capabilities | capabilities]].<br />
|-<br />
| 314 || subscribed || Boolean || Indicates whether this folder should appear in folder tree or not. '''Note:''' Standard folders cannot be unsubscribed.<br />
|-<br />
| 315 || subscr_subflds || Boolean || Indicates whether subfolders should appear in folder tree or not.<br />
|-<br />
| 316 || standard_folder_type || Number || Indicates the default folder type. Zero for non-default folder. See [[#DefaultTypes | Standard folder types]]<br />
|-<br />
| 317 || supported_capabilities || Array || Each element is a String identifying a supported folder capability as described in [[#SupportedCapabilities | supported capabilities]]. Only applicable for non-mail folders. Read Only, Since 7.4.0.<br />
|-<br />
| 3010 || com.openexchange.publish.publicationFlag || Boolean || Indicates whether this folder is published. Read Only, provided by the com.openexchange.publish plugin, since 6.14.<br />
|-<br />
| 3020 || com.openexchange.subscribe.subscriptionFlag || Boolean || Indicates whether this folder has subscriptions storing their content in this folder. Read Only, provided by the com.openexchange.subscribe plugin, since 6.14.<br />
|-<br />
| 3030 || com.openexchange.folderstorage.displayName || String || Provides the display of the folder's owner. Read Only, Since 6.20.<br />
|-<br />
| 3060 || com.openexchange.share.extendedPermissions || Array || Each element is an object described in [[#ExtendedPermissionObject | Extended permission object]]. Read Only, Since 7.8.0.<br />
|}<br />
<br />
<br />
{| id="PermissionFlags" cellspacing="0" border="1"<br />
|+ align="bottom" | Permission flags<br />
! Bits !! Value<br />
|-<br />
| 0-6 || Folder permissions:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || See the folder.<br />
|-<br />
| 2 || Create objects in the folder. '''Note''': '''Does not apply to folders of module ''system'''''.<br />
|-<br />
| 4 || Create subfolders.<br />
|-<br />
| 64 || All permissions. This is currently the same as "Create subfolders" but in the future additional permissions may be added that will be given to the user when using this value.<br />
|}<br />
The values are scalars and not bit sets. Any other than the described values should not be used. If they are used expect an exception from the backend. Every value automatically contains the access rights covered by lower values.<br>'''NOTE''': ''Create objects in the folder'' is not covered by ''Create subfolders'' if folder's module is ''system''.<br />
|-<br />
| 7-13 || Read permissions for objects in the folder:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || Read only own objects.<br />
|-<br />
| 2 || Read all objects.<br />
|-<br />
| 64 || All permissions. This is currently the same as "Read all objects" but in the future additional permissions may be added that will be given to the user when using this value.<br />
|}<br />
The values are scalars and not bit sets. Any other than the described values should not be used. If they are used expect an exception from the backend. Every value automatically contains the access rights covered by lower values.<br />
|-<br />
| 14-20 || Write permissions for objects in the folder:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || Modify only own objects.<br />
|-<br />
| 2 || Modify all objects.<br />
|-<br />
| 64 || All permissions. This is currently the same as "Modify all objects" but in the future additional permissions may be added that will be given to the user when using this value.<br />
|}<br />
The values are scalars and not bit sets. Any other than the described values should not be used. If they are used expect an exception from the backend. Every value automatically contains the access rights covered by lower values.<br />
|-<br />
| 21-27 || Delete permissions for objects in the folder:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || Delete only own objects.<br />
|-<br />
| 2 || Delete all objects.<br />
|-<br />
| 64 || All permissions. This is currently the same as "Delete all objects" but in the future additional permissions may be added that will be given to the user when using this value.<br />
|}<br />
The values are scalars and not bit sets. Any other than the described values should not be used. If they are used expect an exception from the backend. Every value automatically contains the access rights covered by lower values.<br />
|-<br />
| 28 || Admin flag:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || Every operation modifying the folder in some way requires this permission. This are e.g. changing the folder name, modifying the permissions, deleting or moving the folder.<br />
|}<br />
|}<br />
<br />
{| id="PermissionObject" cellspacing="0" border="1"<br />
|+ align="bottom" | Permission object<br />
! Name !! Type !! Value<br />
|-<br />
| bits || Number || For non-mail folders, a number as described in [[#PermissionFlags | Permission flags]].<br />
|-<br />
| rights || String || For mail folders, the rights string as defined in RFC 2086.<br />
|-<br />
| entity || Number || User ID of the user or group to which this permission applies (ignored for type "anonymous" or "guest").<br />
|-<br />
| group || Boolean || true if entity refers to a group, false if it refers to a user (ignored for type "anonymous" or "guest").<br />
|-<br />
| type || String || The recipient type, i.e. one of "guest", "anonymous" (required if no internal "entity" defined).<br />
|-<br />
| password || String || An additional secret / pin number an anonymous user needs to enter when accessing the share (for type "anonymous", optional) .<br />
|-<br />
| email_address || String || The e-mail address of the recipient (for type "guest").<br />
|-<br />
| display_name || String || The display name of the recipient (for type "guest", optional).<br />
|-<br />
| contact_id || String || The object identifier of the corresponding contact entry if the recipient was chosen from the address book (for type "guest", optional).<br />
|-<br />
| contact_folder || String || The folder identifier of the corresponding contact entry if the recipient was chosen from the address book (for type "guest", required if "contact_id" is set).<br />
|-<br />
| expiry_date || Time || The end date / expiration time after which the share link is no longer accessible (for type "guest" or "anonymous", optional).<br />
|}<br />
<br />
{| id="ExtendedPermissionObject" cellspacing="0" border="1"<br />
|+ align="bottom" | Extended permission object<br />
! Name !! Type !! Value<br />
|-<br />
| entity || Number || Identifier of the permission entity (i.e. user-, group- or guest-ID).<br />
|-<br />
| bits || Number || A number as described in [[#PermissionFlags | Permission flags]].<br />
|-<br />
| type || String || "user" for an internal user, "group" for a group, "guest" for a guest, or "anonymous" for an anonymous permission entity.<br />
|-<br />
| display_name || String || A display name for the permission entity.<br />
|-<br />
| contact || Object || A (reduced) set of [[#DetailedContactData | Detailed contact data]] for "user" and "guest" entities.<br />
|-<br />
| share_url || String || The share link for "guest" and "anonymous" entities.<br />
|-<br />
| password || String || The optionally set password for "anonymous" entities.<br />
|-<br />
| expiry_date || Date || The optionally set expiry date for "anonymous" entities.<br />
|}<br />
<br />
{| id="Capabilities" cellspacing="0" border="1"<br />
|+ align="bottom" | Capabilities<br />
! Bit !! Description<br />
|-<br />
| 0 || Mailing system supports permissions.<br />
|-<br />
| 1 || Mailing system supports ordering mails by their thread reference.<br />
|-<br />
| 2 || Mailing system supports quota restrictions.<br />
|-<br />
| 3 || Mailing system supports sorting.<br />
|-<br />
| 4 || Mailing system supports folder subscription.<br />
|}<br />
<br />
'''Note''': Capabilities describe the entire mailing system (mail account), not the specific folder in which they are transmitted. E.g. bit 4 of the capabilities on the user's inbox describes whether subscriptions are supported by the default account, even though the inbox itself cannot be unsubscribed because it's a standard folder.<br />
<br />
{| id="DefaultTypes" cellspacing="0" border="1"<br />
|+ align="bottom" | Standard Folder Types<br />
! Bit !! Description<br />
|-<br />
| 0 || No default folder.<br />
|-<br />
| 1 || Task.<br />
|-<br />
| 2 || Calendar.<br />
|-<br />
| 3 || Contact.<br />
|-<br />
| 7 || Inbox.<br />
|-<br />
| 8 || Infostore.<br />
|-<br />
| 9 || Drafts.<br />
|-<br />
| 10 || Sent.<br />
|-<br />
| 11 || Spam.<br />
|-<br />
| 12 || Trash.<br />
|}<br />
<br />
{| id="SupportedCapabilities" cellspacing="0" border="1"<br />
|+ align="bottom" | Supported Capabilities<br />
! Name !! Description<br />
|-<br />
| permissions || Folder storage supports permissions.<br />
|-<br />
| publication || Folder storage supports folder publication.<br />
|-<br />
| quota || Folder storage supports quota restrictions.<br />
|-<br />
| sort || Folder storage supports sorting.<br />
|-<br />
| subscription || Folder storage supports folder subscription.<br />
|}<br />
<br />
=== Get subfolders ===<br />
<br />
GET <code>/ajax/folders?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>parent</code> – Object ID of a folder, which is the parent folder of the requested folders.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
* <code>all</code> – Set to <code>1</code> to list even not subscribed folders.<br />
* <code>tree</code> – The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
* <code>errorOnDuplicateName</code> – An optional flag to enable or disable (default) check for duplicate folder names within returned folder response (since v6.20.1). If a duplicate folder name is detected, an appropriate error is returned as [[#ResponseBody | response]].<br />
<br />
Response with timestamp: An array with data for all folders, which have the folder with the requested object ID as parent. Each array element describes one folder and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get path ===<br />
<br />
GET <code>/ajax/folders?action=path</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of a folder.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Response with timestamp: An array with data for all parent nodes until root folder. Each array element describes one folder and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get updated folders ===<br />
<br />
GET <code>/ajax/folders?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>parent</code> – Object ID of a folder, which is the parent folder of the requested folders.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested folders.<br />
* <code>ignore</code> (optional) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Response with timestamp: An array with data for new, modified and deleted folders. New and modified folders are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted folders (should the <code>ignore</code> parameter be ever implemented) would be identified by their object IDs as plain strings, without being part of a nested array.<br />
<br />
=== Get a folder ===<br />
<br />
GET <code>/ajax/folders?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested folder.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Response with timestamp: An object containing all data of the requested folder. The fields of the object are listed in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]]. The field id is not present. Since OX access controls are folder-based, the folder object also defines the permissions for the objects it contains. The permissions for a given user or group are defined by the object described in [[#PermissionObject | Permission object]]. The format of the actual permissions depends on the type of the folder. The permissions of mail folders are transmitted as a rights string as defined in section 3 of RFC 2086. Permissions of all other folders are transmitted as a single nonnegative integer number. The permissions for any given action on the folder or on contained objects is defined by a group of bits in the binary representation of this number. Each group of bits is interpreted as a separate number. Zero always means "no permissions". Any other values add new permissions and always include the permissions of all lower values. The individual values are described in [[#PermissionFlags | Permission flags]].<br />
<br />
=== Update a folder ===<br />
<br />
PUT <code>/ajax/folders?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated folder.<br />
* <code>timestamp</code> – Timestamp of the updated folder. If the folder was modified after the specified timestamp, then the update must fail.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
* <code>cascadePermissions</code> – (Optional. Defaults to false) Flag to cascade permissions to all sub-folders. The user must have administrative permissions to all sub-folders subject to change. If one permission change fails, the entire operation fails. (Since 7.8.0)<br />
<br />
Request body: Folder object as described in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]]. Only modified fields are present.<br />
<br />
=== Create a folder ===<br />
<br />
PUT <code>/ajax/folders?action=new</code><br />
<br />
Parameters:<br />
* <code>folder_id</code> – The parent folder of the newly created folder<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Request body: Folder object as described in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]]. The field id should not be present.<br />
<br />
Provided that permission is granted to create a folder, its module is bound to the limitation, that the new folder's module must be equal to parent folder's module except that:<br />
* Parent folder is one of the system folders <code>private</code>, <code>public</code>, or <code>shared</code>. Below these folders task, calendar, and contact modules are permitted.<br />
* Parent folder's module is one of task, calendar, or contact. Below this kind of folders task, calendar, and contact modules are permitted.<br />
<br />
Response: Object ID of the newly created folder.<br />
<br />
=== Delete folders ===<br />
<br />
PUT <code>/ajax/folders?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – The optional timestamp of the last update of the deleted folders.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered. <br />
* <code>hardDelete</code> - Optional, defaults to \"false\". If set to \"true\", the folders are deleted permanently. Otherwise, and if the underlying storage supports a trash folder and the folders are not yet located below the trash folder, they are moved to the trash folder.<br />
<br />
Request body: An array with object IDs of the folders that shall be deleted.<br />
<br />
Response: An array with object IDs of folders that were '''NOT''' deleted. There may be a lot of different causes for a not deleted folder: A folder has been modified in the mean time, the user does not have the permission to delete it or those permissions have just been removed, the folder does not exist, etc.<br />
<br />
=== Clearing a folder's content ===<br />
PUT <code>/ajax/folders?action=clear</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Request body: A JSON array containing the folder ID(s) whose content should be cleared. '''NOTE:''' Although the requests offers to clear multiple folders at once it is recommended to clear only one folder per request since if any exception occurs<br />
(e.g. missing permissions) the complete request is going to be aborted.<br />
<br />
Response: A JSON array containing the IDs of folders that could not be cleared due to a concurrent modification. Meaning you receive an empty JSON array if everything worked well.<br />
<br />
=== Get all visible folder of a certain module (since v6.18.2) ===<br />
PUT <code>/ajax/folders?action=allVisible</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>tree</code> – The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>content_type</code> – The desired content type (either numbers or strings; e.g. "tasks", "calendar", "contacts", "mail")<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
<br />
Request body: None<br />
<br />
Response with timestamp: A JSON object containing three fields: "private", "public, and "shared". Each field is a JSON array with data for all folders. Each folder is itself described by an array.<br />
<br />
=== Get shared folders (Since 7.8.0, Preliminary) ===<br />
<br />
GET <code>/ajax/folders?action=shares</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
* <code>all</code> – Set to <code>1</code> to list even not subscribed folders.<br />
* <code>tree</code> – The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>content_type</code> – The desired content type (either numbers or strings; e.g. \"tasks\", \"calendar\", \"contacts\", \"infostore\"). Note: this action is not implemented for module "mail".<br />
<br />
Response with timestamp: An array with data for all folders that are considered as shared by the user. Each array element describes one folder and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
== Module "tasks" ==<br />
<br />
The tasks module is used to access task information.<br />
<br />
=== Get all tasks ===<br />
<br />
GET <code>/ajax/tasks?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for tasks are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response with timestamp: An array with task data. Each array element describes one task and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedTaskAndAppointmentData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed task and appointment data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 200 || title || String || Short description.<br />
|-<br />
| 201 || start_date || Date or Time || Inclusive start of the event as Date for tasks and whole day appointments and Time for normal appointments. For sequencies, this date must be part of the sequence, i. e. sequencies always start at this date. (deprecated for tasks since v7.6.1, replaced by start_time and full_time)<br />
|-<br />
| 202 || end_date || Date or Time || Exclusive end of the event as Date for tasks and whole day appointments and as Time for normal appointments. (deprecated for tasks since v7.6.1, replaced by end_time and full_time)<br />
|-<br />
| 203 || note || String || Long description.<br />
|-<br />
| 204 || alarm || Number or Time || Specifies when to notify the participants as the number of minutes before the start of the appointment (-1 for "no alarm"). For tasks, the Time value specifies the absolute time when the user should be notified.<br />
|-<br />
| 209 || recurrence_type || Number || Specifies the type of the recurrence for a task sequence:<br />
{| cellspacing="0" border="1"<br />
| 0 || none (single event)<br />
|-<br />
| 1 || daily<br />
|-<br />
| 2 || weekly<br />
|-<br />
| 3 || monthly<br />
|-<br />
| 4 || yearly<br />
|}<br />
|-<br />
| 212 || days || Number || Specifies which days of the week are part of a sequence. The value is a bitfield with bit 0 indicating sunday, bit 1 indicating monday and so on. May be present if recurrence_type > 1. If allowed but not present, the value defaults to 127 (all 7 days).<br />
|-<br />
| 213 || day_in_month || Number || Specifies which day of a month is part of the sequence. Counting starts with 1. If the field "days" is also present, only days selected by that field are counted. If the number is bigger than the number of available days, the last available day is selected. Present if and only if recurrence_type > 2.<br />
|-<br />
| 214 || month || Number || Month of the year in yearly sequencies. 0 represents January, 1 represents February and so on. Present if and only if recurrence_type = 4.<br />
|-<br />
| 215 || interval || Number || Specifies an integer multiplier to the interval specified by recurrence_type. Present if and only if recurrence_type > 0. Must be 1 if recurrence_type = 4.<br />
|-<br />
| 216 || until || Date || Inclusive end date of a sequence. May be present only if recurrence_type > 0. The sequence has no end date if recurrence_type > 0 and this field is not present. Note: since this is a Date, the entire day after the midnight specified by the value is included.<br />
|-<br />
| 217 || notification || Boolean || If true, all participants are notified of any changes to this object. This flag is valid for the current change only, i. e. it is not stored in the database and is never sent by the server to the client.<br />
|-<br />
| 220 || participants || Array || Each element identifies a participant, user, group or booked resource as described in [[#Participant | participant table]].<br />
|-<br />
| 221 || users || Array || Each element represents a participant as described in [[#UserParticipantObject | User participant object]]. User groups are resolved and are represented by their members. Any user can occur only once.<br />
|-<br />
| 222 || occurrences || Number || Specifies how often a recurrence should appear. May be present only if recurrence_type > 0.<br />
|-<br />
| 223 || uid || String || Can only be written when the object is created. Internal and external globally unique identifier of the appointment or task. Is used to recognize appointments within iCal files. If this attribute is not written it contains an automatic generated UUID.<br />
|-<br />
| 224 || organizer || String || Contains the email address of the appointment organizer which is not necessarily an internal user. Not implemented for tasks.<br />
|-<br />
| 225 || sequence || Number || iCal sequence number. Not implemented for tasks. Must be incremented on update. Will be incremented by the server, if not set.<br />
|-<br />
| 226 || confirmations || Array || Each element represents a confirming participant as described in [[#ConfirmingParticipant | confirming participant]]. This can be internal and external user. Not implemented for tasks.<br />
|-<br />
| 227 || organizerId || Number || Contains the userIId of the appointment organizer if it is an internal user. Not implemented for tasks. (Introduced with 6.20.1)<br />
|-<br />
| 228 || principal || String || Contains the email address of the appointment principal which is not necessarily an internal user. Not implemented for tasks. (Introduced with 6.20.1)<br />
|-<br />
| 229 || principalId || Number || Contains the userIId of the appointment principal if it is an internal user. Not implemented for tasks. (Introduced with 6.20.1)<br />
|-<br />
| 401 || full_time || Boolean || True if the event is a whole day appointment or task, false otherwise.<br />
|}<br />
<br />
{| id="Participant" cellspacing="0" border="1"<br />
|+ align="bottom" | Participant identifier<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || User ID<br />
|-<br />
| type || Number || Type of participant:<br />
{|<br />
| 1 || user<br />
|-<br />
| 2 || user group<br />
|-<br />
| 3 || resource<br />
|-<br />
| 4 || resource group<br />
|-<br />
| 5 || external user<br />
|}<br />
|-<br />
| mail || String || mail address of an external participant<br />
|}<br />
<br />
{| id="UserParticipantObject" cellspacing="0" border="1"<br />
|+ align="bottom" | User participant object<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || User ID. Confirming for other users only works for appointments and not for tasks.<br />
|-<br />
| display_name || String || Displayable name of the participant.<br />
|-<br />
| confirmation || Number ||<br />
{| cellspacing="0" border="1"<br />
| 0 || none<br />
|-<br />
| 1 || accepted<br />
|-<br />
| 2 || declined<br />
|-<br />
| 3 || tentative<br />
|}<br />
|-<br />
| confirmmessage || String || Confirm Message of the participant<br />
|}<br />
<br />
{| id="ConfirmingParticipant" cellspacing="0" border="1"<br />
|+ align="bottom" | Confirming participant<br />
! Name !! Type !! Value<br />
|-<br />
| type || Number || Type of participant:<br />
{|<br />
| 1 || user<br />
|-<br />
| 5 || external user<br />
|}<br />
|-<br />
| mail || String || email address of external participant<br />
|-<br />
| display_name || String || display name of external participant<br />
|-<br />
| status || Number ||<br />
{|<br />
| 0 || none<br />
|-<br />
| 1 || accepted<br />
|-<br />
| 2 || declined<br />
|-<br />
| 3 || tentative<br />
|}<br />
|-<br />
| message || String || Confirm Message of the participant<br />
|}<br />
<br />
{| id="DetailedTaskData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed task data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 300 || status || Number || Status of the task:<br />
{| cellspacing="0" border="1"<br />
| 1 || not started<br />
|-<br />
| 2 || in progress<br />
|-<br />
| 3 || done<br />
|-<br />
| 4 || waiting<br />
|-<br />
| 5 || deferred<br />
|}<br />
|-<br />
| 301 || percent_completed || Number || How much of the task is completed. An integer number between 0 and 100.<br />
|-<br />
| 302 || actual_costs|| Number || A monetary attribute to store actual costs of a task. Allowed values must be in the range -9999999999.99 and 9999999999.99.<br />
|-<br />
| 303 || actual_duration<br />
|-<br />
| 304 || after_complete || Date || Deprecated. Only present in AJAX interface. Value will not be stored on OX server.<br />
|-<br />
| 305 || billing_information<br />
|-<br />
| 307 || target_costs|| Number || A monetary attribute to store target costs of a task. Allowed values must be in the range -9999999999.99 and 9999999999.99.<br />
|-<br />
| 308 || target_duration<br />
|-<br />
| 309 || priority || Number || 1 = LOW, 2 = MEDIUM, 3 = HIGH<br />
|-<br />
| 312 || currency<br />
|-<br />
| 313 || trip_meter<br />
|-<br />
| 314 || companies<br />
|-<br />
| 315 || date_completed<br />
|-<br />
| 316 || start_time || Date or Time || Inclusive start as Date for whole day tasks and Time for normal tasks. <br />
|-<br />
| 317 || end_time || Date or Time || Exclusive end as Date for whole day tasks and as Time for normal tasks.<br />
|}<br />
<br />
=== Get a list of tasks ===<br />
<br />
PUT <code>/ajax/tasks?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for tasks are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]].<br />
<br />
Request body: An array of with object IDs of requested tasks.<br />
<br />
Response with timestamp: An array with task data. Each array element describes one task and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get updated tasks ===<br />
<br />
GET <code>/ajax/tasks?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for tasks are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested tasks.<br />
* <code>ignore</code> – Which kinds of updates should be ignored. Omit this parameter or set it to "deleted" to not have deleted tasks identifier in the response. Set this parameter to "false" and the response contains deleted tasks identifier.<br />
<br />
Response with timestamp: An array with new, modified and deleted tasks. New and modified tasks are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted tasks would be identified by their object IDs as plain strings, without being part of a nested array.<br />
<br />
=== Get a task ===<br />
<br />
GET <code>/ajax/tasks?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested task.<br />
* <code>folder</code> – Object ID of the task's folder.<br />
<br />
Response with timestamp: An object containing all data of the requested task. The fields of the object are listed in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]]. The field id is not included.<br />
<br />
=== Update a task ===<br />
<br />
PUT <code>/ajax/tasks?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Folder Identifier through that the task is accessed. This is necessary for checking the permissions.<br />
* <code>id</code> – Object ID of the updated task.<br />
* <code>timestamp</code> – Timestamp of the updated task. If the task was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: Task object as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]]. Only modified fields are present.<br />
<br />
=== Create a task ===<br />
<br />
PUT <code>/ajax/tasks?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Task object as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]]. The field id is not present.<br />
<br />
Response: A json objekt with attribute <code>id</code> of the newly created task.<br />
<br />
=== Delete task ===<br />
<br />
PUT <code>/ajax/tasks?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted tasks.<br />
<br />
Request body: An object in the field “id” and “folder”.<br />
<br />
Response: An array with object IDs of tasks which were modified after the specified timestamp and were therefore not deleted.<br />
<br />
=== Delete tasks (since v6.22) ===<br />
<br />
PUT <code>/ajax/tasks?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted tasks.<br />
<br />
Request body: An array of objects with the fields “id” and “folder”.<br />
<br />
Response: An array with object IDs of tasks which were modified after the specified timestamp and were therefore not deleted.<br />
<br />
=== Confirm task ===<br />
<br />
PUT <code>/ajax/tasks?action=confirm</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the to confirm task.<br />
* <code>folder</code> – ID of the folder through that the task is accessed.<br />
* <code>timestamp</code> – Timestamp of the last update of the to confirm task.<br />
<br />
Request body: An object with the fields "confirmation" and "confirmmessage" as described in [[#UserParticipantObject | User participant object]].<br />
<br />
Response: Nothing, except the standard response object with empty data, the timestamp of the confirmed and thereby updated task, and maybe errors.<br />
<br />
=== Search for tasks ===<br />
<br />
PUT <code>/ajax/tasks?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified , then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Request Body: A JSON object with attributes described in [[#SearchTasks | Search tasks]]<br />
<br />
{| id="SearchTasks" cellspacing="0" border="1"<br />
|+ align="bottom" | Search tasks<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find tasks. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|-<br />
| folder || Number || (optional) Defines the folder to search for tasks in. If this is omitted in all task folders will be searched.<br />
|-<br />
| start || Date or Time || (optional) Inclusive start date for a time range the tasks should end in. If start is omitted end is ignored.<br />
|-<br />
| end || Date or Time || (optional) Exclusive end date for a time range the tasks should end in. If this parameter is omitted the time range has an open end.<br />
|}<br />
<br />
Response with timestamp: An array with matching tasks. Tasks are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
== Module "contacts" ==<br />
<br />
The contacts module is used to access contact information.<br />
<br />
=== Get all contacts ===<br />
<br />
GET <code>/ajax/contacts?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried (optional from 6.22.2 on: If not set, the contents of all visible folders are used instead).<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for contacts are defined in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (preliminary, since 6.20) – allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedContactData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed contact data<br />
! ID !! Displayed name !! Name !! Type !! Value<br />
|-<br />
| 223 || || uid || String || Can only be written when the object is created. Internal and external globally unique identifier of the contact. Is used to recognize contacts within vCard files. If this attribute is not written it contains an automatic generated UUID.<br />
|-<br />
| 500 || Display name || display_name || String<br />
|-<br />
| 501 || Given name || first_name || String || First name.<br />
|-<br />
| 502 || Sur name || last_name || String || Last name.<br />
|-<br />
| 503 || Middle name || second_name || String<br />
|-<br />
| 504 || Suffix || suffix || String<br />
|-<br />
| 505 || Title || title || String<br />
|-<br />
| 506 || Street home || street_home || String<br />
|-<br />
| 507 || Postal code home || postal_code_home || String<br />
|-<br />
| 508 || City home || city_home || String<br />
|-<br />
| 509 || State home || state_home || String<br />
|-<br />
| 510 || Country home || country_home || String<br />
|-<br />
| 511 || Birthday || birthday || Date<br />
|-<br />
| 512 || Marital status || marital_status || String<br />
|-<br />
| 513 || Number of children || number_of_children || String<br />
|-<br />
| 514 || Profession || profession || String<br />
|-<br />
| 515 || Nickname || nickname || String<br />
|-<br />
| 516 || Spouse name || spouse_name || String<br />
|-<br />
| 517 || Anniversary || anniversary || Date<br />
|-<br />
| 518 || Note || note || String<br />
|-<br />
| 519 || Department || department || String<br />
|-<br />
| 520 || Position || position || String<br />
|-<br />
| 521 || Employee type || employee_type || String<br />
|-<br />
| 522 || Room number || room_number || String<br />
|-<br />
| 523 || Street business || street_business || String<br />
|-<br />
| 524 || Internal user id || user_id || Number<br />
|-<br />
| 525 || Postal code business || postal_code_business || String<br />
|-<br />
| 526 || City business || city_business || String<br />
|-<br />
| 527 || State business || state_business || String<br />
|-<br />
| 528 || Country business || country_business || String<br />
|-<br />
| 529 || Number of employee || number_of_employees || String<br />
|-<br />
| 530 || Sales volume || sales_volume || String<br />
|-<br />
| 531 || Tax id || tax_id || String<br />
|-<br />
| 532 || Commercial register || commercial_register || String<br />
|-<br />
| 533 || Branches || branches || String<br />
|-<br />
| 534 || Business category || business_category || String<br />
|-<br />
| 535 || Info || info || String<br />
|-<br />
| 536 || Manager's name || manager_name || String<br />
|-<br />
| 537 || Assistant's name || assistant_name || String<br />
|-<br />
| 538 || Street other || street_other || String<br />
|-<br />
| 539 || City other || city_other || String<br />
|-<br />
| 540 || Postal code other || postal_code_other || String<br />
|-<br />
| 541 || Country other || country_other || String<br />
|-<br />
| 542 || Telephone business 1 || telephone_business1 || String<br />
|-<br />
| 543 || Telephone business 2 || telephone_business2 || String<br />
|-<br />
| 544 || FAX business || fax_business || String<br />
|-<br />
| 545 || Telephone callback || telephone_callback || String<br />
|-<br />
| 546 || Telephone car || telephone_car || String<br />
|-<br />
| 547 || Telephone company || telephone_company || String<br />
|-<br />
| 548 || Telephone home 1 || telephone_home1 || String<br />
|-<br />
| 549 || Telephone home 2 || telephone_home2 || String<br />
|-<br />
| 550 || FAX home || fax_home || String<br />
|-<br />
| 551 || Cellular telephone 1 || cellular_telephone1 || String<br />
|-<br />
| 552 || Cellular telephone 2 || cellular_telephone2 || String<br />
|-<br />
| 553 || Telephone other || telephone_other || String<br />
|-<br />
| 554 || FAX other || fax_other || String<br />
|-<br />
| 555 || Email 1 || email1 || String<br />
|-<br />
| 556 || Email 2 || email2 || String<br />
|-<br />
| 557 || Email 3 || email3 || String<br />
|-<br />
| 558 || URL || url || String<br />
|-<br />
| 559 || Telephone ISDN || telephone_isdn || String<br />
|-<br />
| 560 || Telephone pager || telephone_pager || String<br />
|-<br />
| 561 || Telephone primary || telephone_primary || String<br />
|-<br />
| 562 || Telephone radio || telephone_radio || String<br />
|-<br />
| 563 || Telephone telex || telephone_telex || String<br />
|-<br />
| 564 || Telephone TTY/TDD || telephone_ttytdd || String<br />
|-<br />
| 565 || Instantmessenger 1 || instant_messenger1 || String<br />
|-<br />
| 566 || Instantmessenger 2 || instant_messenger2 || String<br />
|-<br />
| 567 || Telephone IP || telephone_ip || String<br />
|-<br />
| 568 || Telephone assistant || telephone_assistant || String<br />
|-<br />
| 569 || Company || company || String<br />
|-<br />
| 570 || || image1 || String<br />
|-<br />
| 571 || Dynamic Field 1 || userfield01 || String<br />
|-<br />
| 572 || Dynamic Field 2 || userfield02 || String<br />
|-<br />
| 573 || Dynamic Field 3 || userfield03 || String<br />
|-<br />
| 574 || Dynamic Field 4 || userfield04 || String<br />
|-<br />
| 575 || Dynamic Field 5 || userfield05 || String<br />
|-<br />
| 576 || Dynamic Field 6 || userfield06 || String<br />
|-<br />
| 577 || Dynamic Field 7 || userfield07 || String<br />
|-<br />
| 578 || Dynamic Field 8 || userfield08 || String<br />
|-<br />
| 579 || Dynamic Field 9 || userfield09 || String<br />
|-<br />
| 580 || Dynamic Field 10 || userfield10 || String<br />
|-<br />
| 581 || Dynamic Field 11 || userfield11 || String<br />
|-<br />
| 582 || Dynamic Field 12 || userfield12 || String<br />
|-<br />
| 583 || Dynamic Field 13 || userfield13 || String<br />
|-<br />
| 584 || Dynamic Field 14 || userfield14 || String<br />
|-<br />
| 585 || Dynamic Field 15 || userfield15 || String<br />
|-<br />
| 586 || Dynamic Field 16 || userfield16 || String<br />
|-<br />
| 587 || Dynamic Field 17 || userfield17 || String<br />
|-<br />
| 588 || Dynamic Field 18 || userfield18 || String<br />
|-<br />
| 589 || Dynamic Field 19 || userfield19 || String<br />
|-<br />
| 590 || Dynamic Field 20 || userfield20 || String || Contains a UUID if one was assigned (after 6.18.2)<br />
|-<br />
| 592 || || distribution_list || Array || If this contact is a distribution list, then this field is an array of objects. Each object describes a member of the list as defined in [[#DistributionListMember | Distribution list member]].<br />
|-<br />
| 594 || Number of distributionlists || number_of_distribution_list || Number<br />
|-<br />
| 596 || || number_of_images || Number<br />
|-<br />
| 597 || || image_last_modified || Timestamp<br />
|-<br />
| 598 || State other || state_other || String<br />
|-<br />
| 599 || || file_as || String<br />
|-<br />
| 601 || || image1_content_type || String<br />
|-<br />
| 602 || || mark_as_distributionlist || Boolean<br />
|-<br />
| 605 || Default address || default_address || Number<br />
|-<br />
| 606 || || image1_url || String<br />
|-<br />
| 608 || || useCount || Number || In case of sorting purposes the column 609 is also available, which places global address book contacts at the beginning of the result. If 609 is used, the order direction (ASC, DESC) is ignored.<br />
|-<br />
| 610 || || yomiFirstName || String || Kana based representation for the First Name. Commonly used in japanese environments for searchin/sorting issues. (since 6.20)<br />
|-<br />
| 611 || || yomiLastName || String || Kana based representation for the Last Name. Commonly used in japanese environments for searchin/sorting issues. (since 6.20)<br />
|-<br />
| 612 || || yomiCompany || String || Kana based representation for the Company. Commonly used in japanese environments for searchin/sorting issues. (since 6.20)<br />
|-<br />
| 613 || || addressHome || String || Support for Outlook 'home' address field. (since 6.20.1)<br />
|-<br />
| 614 || || addressBusiness || String || Support for Outlook 'business' address field. (since 6.20.1)<br />
|-<br />
| 615 || || addressOther || String || Support for Outlook 'other' address field. (since 6.20.1)<br />
|}<br />
<br />
<br />
{| id="DistributionListMember" cellspacing="0" border="1"<br />
|+ align="bottom" | Distribution list member<br />
! Name !! Type !! Value<br />
|-<br />
| id || String || Object ID of the member's contact if the member is an existing contact.<br />
|-<br />
| folder_id || String || Parent folder ID of the member's contact if the member is an existing contact (preliminary, from 6.22 on).<br />
|-<br />
| display_name || String || Display name<br />
|-<br />
| mail || String || Email address (mandatory before 6.22, afterwards optional if you are referring to an internal contact)<br />
|-<br />
| mail_field || Number || Which email field of an existing contact (if any) is used for the mail field.<br />
{| cellspacing="0" border="1"<br />
| 0 || independent contact<br />
|-<br />
| 1 || default email field (email1)<br />
|-<br />
| 2 || second email field (email2)<br />
|-<br />
| 3 || third email field (email3)<br />
|}<br />
|}<br />
<br />
=== Get a list of contacts ===<br />
<br />
PUT <code>/ajax/contacts?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for contacts are defined in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]].<br />
<br />
Request body: An array with objects. Each object contains fields “id” and “folder” of requested contacts.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a list of users ===<br />
<br />
PUT <code>/ajax/contacts?action=listuser</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for contacts are defined in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]].<br />
<br />
Request body: An array with id<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
Available with SP4<br />
<br />
=== Get updated contacts ===<br />
<br />
GET <code>/ajax/contacts?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for contacts are defined in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested contacts.<br />
* <code>ignore</code> (mandatory - should be set to "deleted") (deprecated) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
<br />
Response with timestamp: An array with new, modified and deleted contacts. New and modified contacts are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted contacts (should the <code>ignore</code> parameter be ever implemented) would be identified by their object IDs as plain strings, without being part of a nested array.<br />
<br />
=== Get a contact ===<br />
<br />
GET <code>/ajax/contacts?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested contact.<br />
* <code>folder</code> – Object ID of the contact's folder.<br />
<br />
Response with timestamp: An object containing all data of the requested contact. The fields of the object are listed in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]]. The field id is not included.<br />
<br />
=== Get contact by user ID ===<br />
<br />
GET <code>/ajax/contacts?action=getuser</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – User ID (not Object ID) of the requested user.<br />
<br />
Response with timestamp: An object containing all data of the requested contact. The fields of the object are listed in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]]. <br />
<br />
Available with SP4 package.<br />
<br />
=== Update a contact ===<br />
<br />
PUT <code>/ajax/contacts?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Folder identifier through that the contact is accessed. This is necessary for checking the permissions.<br />
* <code>id</code> – Object ID of the updated contact.<br />
* <code>timestamp</code> – Timestamp of the updated contact. If the contact was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: Contact object as described in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]]. Only modified fields are present.<br />
<br />
To remove some contact image send the image attribute set to <code>null</code>.<br />
<br />
To change or add some contact image the PUT command must be replaced with a POST command and all data must be provided within a <code>multipart/form-data</code> body. The normal request body must be placed into a form field named <code>json</code> while the image file must be placed in a file field named <code>file</code>. The response is then an HTML page as described in section [[#File_uploads | File uploads]].<br />
<br />
=== Create a contact ===<br />
<br />
PUT <code>/ajax/contacts?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Contact object as described in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]]. The field id is not included.<br />
<br />
Response: A json objekt with attribute <code>id</code> of the newly created contact.<br />
<br />
To add some contact image the PUT command must be replaced with a POST command and all data must be provided within a <code>multipart/form-data</code> body. The normal request body must be placed into a form field named <code>json</code> while the image file must be placed in a file field named <code>file</code>. The response is then an HTML page as described in section [[#File uploads | File uploads]].<br />
<br />
=== Delete a contact ===<br />
<br />
PUT <code>/ajax/contacts?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted contacts.<br />
<br />
Request body: An object with the fields “id” and “folder”.<br />
<br />
=== Delete contacts (since v6.22)===<br />
<br />
PUT <code>/ajax/contacts?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted contacts.<br />
<br />
Request body: An array of objects with the fields “id” and “folder”.<br />
<br />
=== Search contacts ===<br />
<br />
PUT <code>/ajax/contacts?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified. In case of use of column 609 (use count depending order for collected contacts with global address book) the parameter "order" ist NOT necessary and will be ignored.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (preliminary, since 6.20) – allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Request body: An Object as described in [[#SearchContacts | Search contacts]].<br />
<br />
{| id="SearchContacts" cellspacing="0" border="1"<br />
|+ align="bottom" | Search contacts<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find contacts. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves. Matching is performed against any substring of the field <code>display_name</code>.<br />
|-<br />
| startletter || String || Search contacts with the given startletter. If this field is present, the pattern is matched against the contact field which is specified by the property contact_first_letter_field on the server (default: last name). Otherwise, the pattern is matched against the display name.<br />
|-<br />
| folder || Array of Number || If a list of folder identifiers or at least a single folder identifier is given, only in that folders will be searched for contacts. This paramenter is optional but searching in all contact folders that are viewable and where objects can be read in is more expensive on that database than searching in a dedicated number of them. The possibility to provide here an array of folder identifier has been added with 6.10.<br />
|}<br />
<br />
Alternative request body: An Object as described in [[#SearchContactsAlternative | Search contacts alternative]].<br />
<br />
{| id="SearchContactsAlternative" cellspacing="0" border="1"<br />
|+ align="bottom" | Search contacts alternative<br />
! Name !! Type !! Value<br />
|-<br />
| last_name || String || Searches contacts where the last name match with the given last name.<br />
|-<br />
| first_name || String || Searches contacts where the first name match with the given first name.<br />
|-<br />
| display_name || String || Searches contacts where the display name match with the given display name.<br />
|-<br />
| email1 || String || Searches contacts where the email1 address match with the given search pattern. (requires version >= 6.12)<br />
|-<br />
| email2 || String || Searches contacts where the email2 address match with the given search pattern. (requires version >= 6.12)<br />
|-<br />
| email3 || String || Searches contacts where the email3 address match with the given search pattern. (requires version >= 6.12)<br />
|-<br />
| company || String || Searches contacts where the company match with the given search pattern. (requires version >= 6.12)<br />
|-<br />
| categories || String || Searches contacts where the categories match with the given search pattern. <br />
|-<br />
| orSearch || Boolean || If set to true, a contact is returned if any specified pattern matches at the start of the corresponding field. Otherwise, a contact is returned if all specified patterns match any substring of the corresponding field.<br />
|-<br />
| emailAutoComplete || Boolean || If set to true, results are guaranteed to contain at least one email adress and the search is performed as if orSearch were set to true. The actual value of orSearch is ignored.<br />
|-<br />
| exactMatch || Boolean || If set to true, contacts are returned where the specified patterns match the corresponding fields exactly. Otherwise, a 'startsWith' or 'substring' comparison is used based on the 'orSearch' parameter. (requires version > 6.22.1)<br />
|}<br />
<br />
Response: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Search contacts by filter (since 6.20) ===<br />
<br />
PUT <code>/ajax/contacts?action=advancedSearch</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified. <br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (preliminary, since 6.20) – allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Request body: An Object as described in [[#Module_.22search.22_.28alternative_suggestion.2C_still_preliminary.29 | Search Filter]]<br />
<br />
Response: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Search contacts by anniversary (Since 6.22.1, Preliminary) ===<br />
<br />
Find contacts whose anniversary falls into a timerange.<br />
<br />
GET <code>/ajax/contacts?action=anniversaries</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>start</code> – The lower (inclusive) limit of the requested time-range.<br />
* <code>end</code> – The upper (exclusive) limit of the requested time-range.<br />
* <code>columns</code> – The requested fields.<br />
* <code>folder</code> (optional) – Object ID of the parent folder that is searched. If not set, all visible folders are used.<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If not specified, the results are sorted ascending by their anniversary in the supplied timerange. If this parameter is specified, then the parameter order must be also specified. <br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (optional) – Allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Search contacts by birthday (Since 6.22.1, Preliminary) ===<br />
<br />
Find contacts whose birthday falls into a timerange.<br />
<br />
GET <code>/ajax/contacts?action=birthdays</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>start</code> – The lower (inclusive) limit of the requested time-range.<br />
* <code>end</code> – The upper (exclusive) limit of the requested time-range.<br />
* <code>columns</code> – The requested fields.<br />
* <code>folder</code> (optional) – Object ID of the parent folder that is searched. If not set, all visible folders are used.<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If not specified, the results are sorted ascending by their birthday in the supplied timerange. If this parameter is specified, then the parameter order must be also specified. <br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (optional) – Allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Auto-complete contacts (Since 7.6.1, Preliminary) ===<br />
<br />
Find contacts based on a prefix, usually used to auto-complete e-mail recipients while the user is typing.<br />
<br />
GET <code>/ajax/contacts?action=autocomplete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>query</code> – The query to search for.<br />
* <code>folder</code> (optional) – Object ID of the parent folder that is searched. If not set, all visible folders are used.<br />
* <code>email</code> (optional) – Whether to only include contacts with at least one e-mail address. Defaults to "true".<br />
* <code>columns</code> – The requested fields.<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is <br />
* <code>collation</code> (optional) – Allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
* <code>left_hand_limit</code> (optional) – A positive integer number to specify the "left-hand" limit of the range to return.<br />
* <code>right_hand_limit</code> (optional) – A positive integer number to specify the "right-hand" limit of the range to return.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
== Module "calendar" ==<br />
<br />
The calendar module is used to access calendar data.<br />
<br />
=== Get all appointments ===<br />
<br />
GET <code>/ajax/calendar?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> (optional) – Object ID of the folder, whose contents are queried. If not specified, defaults to all calendar folders.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]].<br />
* <code>start</code> – Lower inclusive limit of the queried range as a Date. Only appointments which start on or after this date are returned.<br />
* <code>end</code> – Upper exclusive limit of the queried range as a Date. Only appointments which end before this date are returned.<br />
* <code>recurrence_master</code> – Extract the recurrence to several appointments. The default value is false so every appointment of the recurrence will be calculated.<br />
* <code>showPrivate</code> (optional) – only works in shared folders: When enabled, shows private appointments of the folder owner. Such appointments are anonymized by stripping away all information except start date, end date and recurrence information (since 6.18)<br />
<br />
Response with timestamp: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Appointment sequencies are broken up into individual appointments and each occurrence of a sequence in the requested range is returned separately. The appointments are sorted in ascending order by the field start_date.<br />
<br />
{| id="DetailedAppointmentData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed appointment data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 206 || recurrence_id || Number || Object ID of the entire appointment sequence. Present on series and change exception appointments. Equals to object identifier on series appointment and is different to object identifier on change exceptions.<br />
|-<br />
| 207 || recurrence_position || Number || 1-based position of an individual appointment in a sequence. Present if and only if recurrence_type > 0.<br />
|-<br />
| 208 || recurrence_date_position || Date || Date of an individual appointment in a sequence. Present if and only if recurrence_type > 0.<br />
|-<br />
| 210 || change_exceptions || Array || An array of Dates, representing all change exceptions of a sequence.<br />
|-<br />
| 211 || delete_exceptions || Array || An array of Dates, representing all delete exceptions of a sequence.<br />
|-<br />
| 400 || location || String || Location<br />
|-<br />
| 402 || shown_as || Number || Describes, how this appointment appears in availability queries:<br />
{| cellspacing="0" border="1"<br />
| 1 || reserved<br />
|-<br />
| 2 || temporary<br />
|-<br />
| 3 || absent<br />
|-<br />
| 4 || free<br />
|}<br />
|-<br />
| 408 || timezone || String || Timezone<br />
|-<br />
| 410 || recurrence_start || Date || Start of a sequence without time<br />
|-<br />
| || ignore_conflicts || Boolean || Ignore soft conflicts for the new or modified appointment. This flag is valid for the current change only, i. e. it is not stored in the database and is never sent by the server to the client. <br />
|}<br />
<br />
=== Get appointment information ===<br />
<br />
GET <code>/ajax/calendar?action=has</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>start</code> – Lower inclusive limit of the queried range as a Date. Only appointments which end on or after this date are returned.<br />
* <code>end</code> – Upper exclusive limit of the queried range as a Date. Only appointments which start before this date are returned.<br />
<br />
Response is an array of booleans. Array length is the number of days. Each entry in the array corresponds with one day in the range that was queried, explaining whether there is an appointment on this day or not.<br />
<br />
=== Get a list of appointments ===<br />
<br />
PUT <code>/ajax/calendar?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]].<br />
* <code>recurrence_master</code> – Extract the recurrence to several appointments. The default value is false so every appointment of the recurrence will be calculated.<br />
<br />
Request body: An array with full object IDs (folder, id and optionally either recurrence_position or recurrence_date_position) of requested appointments.<br />
<br />
Response with timestamp: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="FullIdentifierForAnAppointment" cellspacing="0" border="1"<br />
|+ align="bottom" | Full identifier for an appointment<br />
! Name !! Type !! Value<br />
|-<br />
| id || String || Object ID<br />
|-<br />
| pos || Number || Value of the field recurrence_position, if present in the appointment.<br />
|}<br />
<br />
=== Get updated appointments ===<br />
<br />
GET <code>/ajax/calendar?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]].<br />
* <code>timestamp</code> – Timestamp of the last update of the requested appointments.<br />
* <code>start</code> (optional) – Lower inclusive limit of the queried range as a Date. Only appointments which end on or after this date are returned.<br />
* <code>end</code> (optional) – Upper exclusive limit of the queried range as a Date. Only appointments which start before this date are returned.<br />
* <code>ignore</code> (mandatory - should be set to "deleted") (deprecated) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
* <code>recurrence_master</code> – Extract the recurrence to several appointments. The default value is false so every appointment of the recurrence will be calculated.<br />
* <code>showPrivate</code> (optional) – only works in shared folders: When enabled, shows private appointments of the folder owner. Such appointments are anonymized by stripping away all information except start date, end date and recurrence information (since 6.18)<br />
<br />
Response with timestamp: An array with new, modified and deleted appointments. New and modified appointments are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted appointments (should the <code>ignore</code> parameter be ever implemented) would be identified by objects described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]] instead of arrays. Appointment sequencies are broken up into individual appointments and each modified occurrence of a sequence in the requested range is returned separately. The appointments are sorted in ascending order by the field start_date.<br />
<br />
=== Get an appointment ===<br />
<br />
GET <code>/ajax/calendar?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested appointment.<br />
* <code>folder</code> – Folder ID of the requested appointment.<br />
* <code>recurrence_position</code> (optional) – Recurrence Position requested appointment.<br />
<br />
Response with timestamp: An object containing all data of the requested appointment. The fields of the object are listed in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]]. The field id is not included.<br />
<br />
=== Update an appointment ===<br />
<br />
PUT <code>/ajax/calendar?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated appointment.<br />
* <code>folder</code> - Object ID of the appointment's folder.<br />
* <code>timestamp</code> – Timestamp of the updated appointment. If the appointment was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: Appointment object as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]]. The field recurrence_id is always present if it is present in the original appointment. The field recurrence_position is present if it is present in the original appointment and only this single appointment should be modified. The field id is not present because it is already included as a parameter. Other fields are present only if modified.<br />
<br />
=== Create an appointment ===<br />
PUT <code>/ajax/calendar?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Appointment object as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]]. The field id is not present.<br />
<br />
Response: If the appointment was created successfully, an object with the attribute <code>id</code> of the newly created appointment. If the appointment could not be created due to conflicts, the response body is an object with the field <code>conflicts</code>, which is an array of appointment objects which caused the conflict. Each appointment object which represents a resource conflict contains an additional field <code>hard_conflict</code> with the Boolean value true. If the user does not have read access to a conflicting appointment, only the fields <code>id</code>, <code>start_date</code>, <code>end_date</code>, <code>shown_as</code> and <code>participants</code> are present and the field <code>participants</code> contains only the participants which caused the conflict.<br />
<br />
=== Delete an appointment ===<br />
<br />
PUT <code>/ajax/calendar?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted appointments.<br />
<br />
Request body: The appointment object to delete. The fields for the object are described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]]. <br />
<br />
Response: An array of objects identifying the appointments which were modified after the specified timestamp and were therefore not deleted. The fields of each object are described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]].<br />
<br />
=== Delete appointments (since v6.22) ===<br />
<br />
PUT <code>/ajax/calendar?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted appointments.<br />
<br />
Request body: An array of appointment objects to delete. The fields for the object are described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]]. <br />
<br />
Response: An array of objects identifying the appointments which were modified after the specified timestamp and were therefore not deleted. The fields of each object are described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]].<br />
<br />
=== Confirm appointment ===<br />
<br />
PUT <code>/ajax/calendar?action=confirm</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the appointment to confirm.<br />
* <code>occurrence</code> – The numeric identifier of the occurrence to which the confirmation applies (in case "id" denotes a series appointment). Available with v7.6.0<br />
* <code>folder</code> – ID of the folder through which the appointment is accessed.<br />
* <code>timestamp</code> – Timestamp of the last update of the to confirmed appointment.<br />
<br />
Request body: An object with the fields "confirmation", "confirmmessage" and "id" (optional) as described in [[#UserParticipantObject | User participant object]].<br />
<br />
Response: Nothing, except the standard response object with empty data, the timestamp of the confirmed and thereby updated task, and maybe errors.<br />
<br />
=== Free & Busy ===<br />
<br />
GET <code>/ajax/calendar?action=freebusy</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> - Internal user id. Must be obtained from the contact module.<br />
* <code>type</code> - Constant for user or resource (1 for users, 3 for resources)<br />
* <code>start</code> – Lower inclusive limit of the queried range as a Date. Only appointments which end on or after this date are returned.<br />
* <code>end</code> – Upper exclusive limit of the queried range as a Date. Only appointments which start before this date are returned.<br />
<br />
Response: An array of objects identifying the appointments which lie between start and end as described.<br><br />
This objects consist of:<br />
{| id="FreeAndBusyAppointment" cellspacing="0" border="1"<br />
! Name !! Type !! Value<br />
|-<br />
| shown_as || Number || Describes, how this appointment appears in availability queries:<br />
{| cellspacing="0" border="1"<br />
| 1 || reserved<br />
|-<br />
| 2 || temporary<br />
|-<br />
| 3 || absent<br />
|-<br />
| 4 || free<br />
|}<br />
|-<br />
| start_date || Date or Time || see [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]]<br />
|- <br />
| end_date || Date or Time || see [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]]<br />
|-<br />
| id || String || Object ID<br />
|-<br />
| folder_id || String || Folder ID. Only set, if the user has the right to see the object. (added 2009-08-18/6.12) <br />
|-<br />
| full_time || Boolean || True if the appointment is a whole day appointment, not present otherwise.<br />
|}<br />
<br />
=== Search appointments ===<br />
<br />
PUT <code>/ajax/calendar?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
<br />
Request body: An Object as described in [[#SearchAppointments | Search appointments]].<br />
<br />
{| id="SearchAppointments" cellspacing="0" border="1"<br />
|+ align="bottom" | Search appointments<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find appointments. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|-<br />
| startletter || String || Search appointments with the given starting letter.<br />
|}<br />
<br />
Request body: An Object as described in [[#SearchAppointments | Search appointments]].<br />
<br />
Response: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get new appointments ===<br />
<br />
GET <code>/ajax/calendar?action=newappointments</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
* <code>start</code> – Lower inclusive limit of the queried range as a Date. Only appointments which end on or after this date are returned.<br />
* <code>end</code> – Upper exclusive limit of the queried range as a Date. Only appointments which start before this date are returned.<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified and holds a column number, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>limit</code> – limits the number of returned object to the given value.<br />
<br />
Response: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Resolve UID ===<br />
<br />
GET <code>/ajax/calendar?action=resolveuid</code><br />
<br />
Parameters<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>uid</code> – The UID to be resolved.<br />
<br />
Response: An object object with the field "id" containing the ox-object id, if existing, an error message otherwise.<br />
<br />
=== Get all Change Exceptions (Since v7.2.0) ===<br />
<br />
GET <code>/ajax/calendar?action=getChangeExceptions</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object id of the appointment series.<br />
* <code>folder</code> – Folder ID of the requested appointments. <br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier.<br />
<br />
Response with timestamp: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
== Module "mail" ==<br />
<br />
The mail module is used to access mail data.<br />
<br />
When mails are stored on an IMAP server, some functionality is not available due to restrictions of the IMAP protocol. Such functionality is marked with "not IMAP".<br />
<br />
=== Get mail count ===<br />
<br />
GET <code>/ajax/mail?action=count</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder whose mail count is queried<br />
<br />
Response (not IMAP: with timestamp): An integer value representing folder's mail count<br />
<br />
=== Get all mails ===<br />
<br />
GET <code>/ajax/mail?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#DetailedMailData | Detailed mail data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response or the string “thread” to return thread-sorted messages. If this parameter is specified and holds a column number, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>left_hand_limit</code> - A positive integer number to specify the "right-hand" limit of the range to return<br />
* <code>right_hand_limit</code> - A positive integer number to specify the "left-hand" limit of the range to return<br />
* <code>limit</code> - A positive integer number to specify how many items shall be returned according to given sorting; overrides <code>left_hand_limit</code>/<code>right_hand_limit</code> parameters and is equal to <code>left_hand_limit=0</code> and <code>right_hand_limit=&lt;limit&gt;</code><br />
<br />
Response (not IMAP: with timestamp): An array with mail data. Each array element describes one mail and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedMailData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed mail data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 102 || color_label || Number || Color number used by Outlook to label the object. The assignment of colors to numbers is arbitrary and specified by the client. The numbers are integer numbers between 0 and 10 (inclusive).<br />
|-<br />
| 600 || id || String || Object ID<br />
|-<br />
| 601 || folder_id || String || Object ID of the parent folder<br />
|-<br />
| 602 || attachment || Boolean || Specifies whether this mail has attachments.<br />
|-<br />
| 603 || from || Array || Each element is a two-element array specifying one sender. The first element of each address is the personal name, the second element is the email address. Missing address parts are represented by <code>null</code> values.<br />
|-<br />
| 604 || to || Array || Each element is a two-element array (see the from field) specifying one receiver.<br />
|-<br />
| 605 || cc || Array || Each element is a two-element array (see the from field) specifying one carbon-copy receiver.<br />
|-<br />
| 606 || bcc || Array || Each element is a two-element array (see the from field) specifying one blind carbon-copy receiver.<br />
|-<br />
| 607 || subject || String || Subject line.<br />
|-<br />
| 608 || size || Number || Size of the mail in bytes.<br />
|-<br />
| 609 || sent_date || Time || Date and time as specified in the mail by the sending client.<br />
|-<br />
| 610 || received_date || Time || Date and time as measured by the receiving server.<br />
|-<br />
| 611 || flags || Number || Various system flags. A sum of zero or more of following values:<br />
{| cellspacing="0" border="1"<br />
| 1 || answered<br />
|-<br />
| 2 || deleted<br />
|-<br />
| 4 || draft<br />
|-<br />
| 8 || flagged<br />
|-<br />
| 16 || recent<br />
|-<br />
| 32 || seen<br />
|-<br />
| 64 || user<br />
|-<br />
| 128 || spam<br />
|-<br />
| 256 || forwarded<br />
|}<br />
See javax.mail.Flags.Flag for details.<br />
|-<br />
| 612 || level || Number || Zero-based nesting level in a thread.<br />
|-<br />
| 613 || disp_notification_to || String || Content of message's header “Disposition-Notification-To”<br />
|-<br />
| 614 || priority || Number || Value of message's “X-Priority” header:<br />
{| cellspacing="0" border="1"<br />
| 0 || No priority<br />
|-<br />
| 5 || Very Low<br />
|-<br />
| 4 || Low<br />
|-<br />
| 3 || Normal<br />
|-<br />
| 2 || High<br />
|-<br />
| 1 || Very High<br />
|}<br />
|-<br />
| 615 || msg_ref || String || Message reference on reply/forward.<br />
|-<br />
| 651 || flag_seen || String || Special field to sort mails by seen status<br />
|-<br />
| 652 || account_name || String || Message's account name.<br />
|-<br />
| 653 || account_id || int || Message's account identifier. Since v6.20.2<br />
|-<br />
| || user || Array || An array with user-defined flags as strings.<br />
|-<br />
| || headers || Object || An object with a field for every non-standard header. The header name is the field name. The header value is the value of the field as string.<br />
|-<br />
| || attachments || Array || Each element is an attachment as described in [[#Attachment | Attachment]]. The first element is the mail text. If the mail has multiple representations (multipart-alternative), then the alternatives are placed after the mail text and have the field disp set to alternative.<br />
|-<br />
| || nested_msgs || Array || Each element is a mail object as described in this table, except for fields id, folder_id and attachment.<br />
|-<br />
| || truncated || boolean || true/false if the mail content was trimmed. Since v7.6.1<br />
|-<br />
| || source || String || RFC822 source of the mail. Only present for <tt>action=get&attach_src=true</tt><br />
|}<br />
<br />
{| id="Attachment" cellspacing="0" border="1"<br />
|+ align="bottom" | Attachment<br />
! Name !! Type !! Value<br />
|-<br />
| id || String || Object ID (unique only inside the same message)<br />
|-<br />
| content_type || String || MIME type<br />
|-<br />
| content || String || Content as text. Present only if easily convertible to text.<br />
|-<br />
| filename || String || Displayed filename (mutually exclusive with content).<br />
|-<br />
| size || Number || Size of the attachment in bytes.<br />
|-<br />
| disp || String || Attachment's disposition: null, inline, attachment or alternative.<br />
|}<br />
<br />
=== Get all mail conversations (since v7.x) ===<br />
<br />
GET <code>/ajax/mail?action=threadedAll</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#DetailedMailData | Detailed mail data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response or the string “thread” to return thread-sorted messages. If this parameter is specified and holds a column number, then the parameter order must be also specified. <b>Note</b>: Applies only to root-level messages.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified. <b>Note</b>: Applies only to root-level messages.<br />
* <code>includeSent</code> - A boolean value to signal that conversations also include messages taken from special "sent" aka "sent items" folder<br />
* <code>left_hand_limit</code> - A positive integer number to specify the "right-hand" limit of the range to return. <b>Note</b>: Applies only to root-level messages.<br />
* <code>right_hand_limit</code> - A positive integer number to specify the "left-hand" limit of the range to return. <b>Note</b>: Applies only to root-level messages.<br />
* <code>limit</code> - A positive integer number to specify how many items shall be returned according to given sorting; overrides <code>left_hand_limit</code>/<code>right_hand_limit</code> parameters and is equal to <code>left_hand_limit=0</code> and <code>right_hand_limit=&lt;limit&gt;</code>. <b>Note</b>: Applies only to root-level messages.<br />
<br />
Response (not IMAP: with timestamp): An JSON array consisting of JSON objects, each representing a conversation's root message along with its message thread. The root message's JSON object is filled according to specified columns and is enhanced by special <code>"thread"</code> JSON field representing the full message thread (including the root message itself). The <code>"thread"</code> JSON field is a JSON array of JSON objects; each representing a message in the conversation sorted by time-line, also filled with specified columns. E.g.<br />
<br />
<pre><br />
{<br />
"flags":32,<br />
"color_label":0,<br />
"unreadCount":0,<br />
"id":"263852",<br />
"folder_id":"default0/INBOX",<br />
"thread":[<br />
{<br />
"id":"263852",<br />
"folder_id":"default0/INBOX",<br />
"flags":32,<br />
"color_label":0<br />
},<br />
{<br />
"id":"263853",<br />
"folder_id":"default0/INBOX",<br />
"flags":32,<br />
"color_label":0<br />
},<br />
{<br />
"id":"26323",<br />
"folder_id":"default0/Sent",<br />
"flags":32,<br />
"color_label":0<br />
},<br />
{<br />
"id":"263854",<br />
"folder_id":"default0/INBOX",<br />
"flags":32,<br />
"color_label":0<br />
}<br />
]<br />
}<br />
</pre><br />
<br />
=== Search mails ===<br />
<br />
PUT <code>/ajax/mail?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#DetailedMailData | Detailed mail data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response or the string “thread” to return thread-sorted messages. If this parameter is specified and holds a column number, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Request Body: A JSON array of JSON objects each containing the search field and its search pattern: e.g.:<br />
<code>[{"col": 612, "pattern": "Joe"}, {"col": 614, "pattern": "Tuesday"}]</code> Supported values for <code>col</code> are 603 to 607 (from, to, cc, bcc and subject) and -1 for full text search.<br />
<br />
Response (not IMAP: with timestamp): An array with mail data. Each array element describes one mail and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a list of mails ===<br />
<br />
PUT <code>/ajax/mail?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for mails are defined in [[#DetailedMailData | Detailed mail data]].<br />
* <code>headers</code> - (preliminary) A comma-separated list of header names. Each name requests denoted header from each mail<br />
<br />
Request body: An array with one object for each requested mail. Each object contains the fields <code>folder</code> and <code>id</code>.<br />
<br />
Response (not IMAP: with timestamp): An array with mail data. Each array element describes one mail and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter followed by requested headers.<br />
<br />
=== Copy mails ===<br />
<br />
PUT <code>/ajax/mail?action=copy</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested mail.<br />
* <code>folder</code> – Object ID of the source folder.<br />
<br />
Request Body: A JSON object containing the id of the destination folder inside the "folder_id" field: e.g.:<br />
<code>{"folder_id": 1376}</code><br />
<br />
Response: A JSON array containing the ID of the copied mail<br />
<br />
=== Move mails ===<br />
<br />
PUT <code>/ajax/mail?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested mail.<br />
* <code>folder</code> – Object ID of the source folder.<br />
<br />
Request Body: A JSON object containing the id of the destination folder inside the "folder_id" field: e.g.:<br />
<code>{"folder_id": 1376}</code><br />
<br />
<br />
Response: A JSON array containing the ID of the moved mail<br />
<br />
=== Update mails ===<br />
<br />
PUT <code>/ajax/mail?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested mail.<br />
* <code>message_id</code> – (Preliminary) The value of "Message-Id" header of the requested mail. This parameter is a substitute for "id" parameter.<br />
* <code>folder</code> – Object ID of the folder.<br />
<br />
'''Note''': If neither parameter "<code>id</code>" nor parameter "<code>message_id</code>" is specified, all folder's messages are updated accordingly. Available with v6.20.<br />
<br />
Request Body: A JSON object which carries the new values that ought to be applied to mail as described in [[#UpdateMail | Update mail]] or [[#UpdateMailExtended | Update mail extended]] (available with SP6 v6.10).<br />
<br />
Response: A JSON object containing the Object ID of the updated mail and its folder.<br />
<br />
{| id="UpdateMail" cellspacing="0" border="1"<br />
|+ align="bottom" | Update mail<br />
! Name !! Type !! Value<br />
|-<br />
| color_label || Number || The color number between 0 and 10.<br />
|-<br />
| flags || Number || A set of flags to add or remove. Note: Flags for "recent" (8) and "user" (64) are ignored.<br />
|-<br />
| value || Boolean || <code>true</code> to add the flags specified by <code>flags</code> (logical OR), <code>false</code> to remove them (logical AND with the inverted value).<br />
|}<br />
<br />
<br />
<br />
{| id="UpdateMailExtended" cellspacing="0" border="1"<br />
|+ align="bottom" | Update mail extended (available with SP6 v6.10)<br />
! Name !! Type !! Value<br />
|-<br />
| set_flags || Number || A set of flags to add. Note: Flags for "recent" (8) and "user" (64) are ignored.<br />
|-<br />
| clear_flags || Number || A set of flags to remove. Note: Flags for "recent" (8) and "user" (64) are ignored.<br />
|}<br />
<br />
<br />
=== Mark all mails as seen (available with v7.6.0) ===<br />
<br />
PUT <code>/ajax/mail?action=all_seen</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder.<br />
<br />
Request Body: n.a.<br />
<br />
Response: <code>true</code><br />
<br />
=== Not IMAP: Get updated mails ===<br />
<br />
GET <code>/ajax/mail?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: Just an empty JSON array is going to be returned since this action cannot be applied to IMAP.<br />
<br />
=== Get a mail ===<br />
<br />
GET <code>/ajax/mail?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested mail.<br />
* <code>message_id</code> – (Preliminary) The value of "Message-Id" header of the requested mail. This parameter is a substitute for "id" parameter.<br />
* <code>folder</code> – Object ID of the mail's folder.<br />
* <code>edit</code> (optional) – 1 indicates that this request should fill the message compose dialog to edit a message and thus display-specific date is going to be withheld.<br />
* <code>hdr</code> (optional) – 1 to let the response contain only the (formatted) message headers as plain text<br />
* <code>src</code> (optional) – 1 to let the response contain the complete message source as plain text<br />
* <code>save</code> (optional) – 1 to write the complete message source to output stream. '''NOTE:''' This parameter will only be used if parameter <code>src</code> is set to 1.<br />
* <code>view</code> (optional - available with SP4)<br />
** "raw" returns the content as it is, meaning no preparation are performed and thus no guarantee for safe contents is given (available with SP6 v6.10).<br />
** "text" forces the server to deliver a text-only version of the requested mail's body, even if content is HTML.<br />
** "textNoHtmlAttach" is the same as "text", but does not deliver the HTML part as attachment in case of multipart/alternative content.<br />
** "html" to allow a possible HTML mail body being transferred as it is (but white-list filter applied).<br />
** "noimg" to allow a possible HTML content being transferred but without original image src attributes which references external images: Can be used to prevent loading external linked images (spam privacy protection).<br />
** '''NOTE:''' if set, the corresponding gui config setting will be ignored.<br />
* <code>unseen</code> (optional) – "1" or "true" to leave an unseen mail as unseen although its content is requested<br />
* <code>max_size</code> (optional - available since v7.6.1) A positive integer number (greater than 10000) to specify how many characters of the message content will be returned. If the number is smaller than 10000 the value will be ignored and 10000 used.<br />
* <code>attach_src</code> (optional - available since v7.6.1) 1 to let the JSON mail representation being extended by <code>"source"</code> field containing the mail raw RFC822 source data<br />
<br />
Response (not IMAP: with timestamp): An JSON object containing all data of the requested mail. The fields of the object are listed in [[#DetailedMailData | Detailed mail data]]. The fields id and attachment are not included. '''NOTE:''' Of course response is not a JSON object if either parameter <code>hdr</code> or parameter <code>src</code> are set to "1". Then the response contains plain text. Moreover if optional parameter <code>save</code> is set to "1" the complete message source is going to be directly written to output stream to open browser's save dialog.<br />
<br />
=== Get multiple mails as a ZIP file ===<br />
<br />
GET <code>/ajax/mail?action=zip_messages</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – The folder identifier.<br />
* <code>id</code> – A comma-separated list of Object IDs of the requested mails<br />
<br />
Response body: The raw byte data of the ZIP file.<br />
<br />
=== Get a mail attachment ===<br />
<br />
GET <code>/ajax/mail?action=attachment</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – The folder identifier.<br />
* <code>id</code> – Object ID of the mail which contains the attachment.<br />
* <code>attachment</code> – ID of the requested attachment '''OR'''<br />
* <code>cid</code> – Value of header 'Content-ID' of the requested attachment<br />
* <code>save</code> – 1 overwrites the defined mimetype for this attachment to force the download dialog, otherwise 0.<br />
* <code>filter</code> (optional) – 1 to apply HTML white-list filter rules if and only if requested attachment is of MIME type <code>text/htm*</code> '''AND''' parameter <code>save</code> is set to 0.<br />
<br />
Response body: The raw byte data of the document. The response type for the HTTP Request is set accordingly to the defined mimetype for this attachment, except the parameter save is set to 1.<br />
<br />
=== Get multiple mail attachments as a ZIP file ===<br />
<br />
GET <code>/ajax/mail?action=zip_attachments</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – The folder identifier.<br />
* <code>id</code> – Object ID of the mail which contains the attachments.<br />
* <code>attachment</code> – A comma-separated list of IDs of the requested attachments<br />
<br />
Response body: The raw byte data of the ZIP file.<br />
<br />
=== Send a mail ===<br />
<br />
POST <code>/ajax/mail?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request Body: This method uses the encoding multipart/form-data or multipart/mixed.<br />
* The form filed <code>json_0</code> contains the rudimentary mail as JSON object as described in [[#DetailedMailData | Detailed mail data]] with just its message body (as html content) defined in nested JSON array "attachments" and its header data (from, to, subject, etc.). The field "content_type" defines whether the mail ought to be sent as plain text ("text/plain"), as html ("text/html") or as multipart/alternative ("ALTERNATIVE"). Sending a mail requires some special fields inside JSON mail object. The field "infostore_ids" defines a JSON array of infostore document ID(s) that ought to be appended to this mail as attachments. The field "msgref" indicates the ID of the referenced original mail. Moreover the field "sendtype" indicates the type of the message:<br />
** 0 - A normal new mail (optional)<br />
** 1 - A reply mail. The field "msgref" must be present<br />
** 2 - A forward mail. The field "msgref" must be present<br />
** 3 - A draft edit operation. The field "msgref" must be present in order to delete previous draft message since e.g. IMAP does not support changing/replacing a message but requires a delete-and-insert sequence<br />
** 4 - Transport of a draft mail. The field "msgref" must be present<br />
** 6 - This type signals that user intends to send out a saved draft message and expects the draft message (referenced by "msgref" field) being deleted after successful transport<br />
Example of a normal new mail which appends user's VCard and requests a read receipt from receiver:<br />
<br />
<code>Content-Disposition: form-data; name="json_0"....{"from":"\u0022Muster, Karl\u0022 <karl.muster@somewhere.com>","to":"someone@somewhere.com","cc":"","bcc":"",<br />
"subject":"Mail Subject","priority":"3","disp_notification_to":true,"vcard":1,<br />
"attachments":[{"content_type":"ALTERNATIVE","content":"Simple Mail Text!&lt;br&gt;&lt;br&gt;\u000a\u000a"}]}</code><br />
* The request accepts file fields in upload form that denote referenced files that are going to be appended as attachments<br />
* For "text/plain" mail bodies, the JSON boolean field "raw" may be specified inside the body's JSON representation to signal that the text content shall be kept as-is; meaning to keep all formatting intact<br />
<br />
==== Attach data sources ====<br />
Moreover the JSON representation may contain data sources which should be appended as file attachments to the mail. Then the mail contains the <code>"datasources"</code> key which is expected to be a JSON array of data source descriptions.<br />
<br />
A data source description follows the [[#Module_.22conversion.22_.28preliminary.29 | conversion specification]].<br />
<br />
For example to attach a file through an URL the field looks like this (available with v6.18.2):<br />
<br />
<pre><br />
{<br />
"from": "someone@somewhere.com,<br />
...<br />
"datasources"<br />
[<br />
{<br />
"identifier": "com.openexchange.url.mail.attachment",<br />
"args":<br />
{<br />
"url": <url-string>,<br />
"timeout": <optional-timeout-millis-int, default is 2500msec>,<br />
"contentType": <optional-content-type-string>,<br />
"charset": <optional-charset-string>,<br />
"size": <optional-size-int>,<br />
"disposition": <optional-disposition-string>,<br />
"fileName": <optional-file-name-string>,<br />
}<br />
}<br />
]<br />
}<br />
</pre><br />
<br />
Response: Object ID of the newly created mail.<br />
<br />
=== Send/Save mail as MIME data block (RFC822) (added in SP5) ===<br />
<br />
PUT <code>/ajax/mail?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> - A session ID previously obtained from the login module.<br />
* <code>folder</code> (optional) - In case the mail should not be sent out, but saved in a specific folder, the "folder" parameter can be used. If the mail should be sent out to the recipient, the "folder" parameter must not be included and the mail is stored in the folder "Sent Items". Example "folder=default.INBOX/Testfolder"<br />
* <code>flags</code> (optional) - In case the mail should be stored with status "read" (e.g. mail has been read already in the client inbox), the parameter "flags" has to be included. If no "folder" parameter is specified, this parameter must not be included. For infos about mail flags see [[#DetailedMailData | Detailed mail data]] spec.<br />
<br />
Request Body: The MIME Data Block<br />
<br />
Response: Object ID of the newly created/moved mail.<br />
<br />
=== Import of mails as MIME data block (RFC822) (added with 6.18) ===<br />
<br />
This request can be used to store a single or a lot of mails in the OX mail storage backend. This action should be used instead of <code>action=new</code> because it is faster and tolerant to 8bit encoded emails.<br />
<br />
<code>POST /ajax/mail?action=import</code><br />
<br />
Parameters:<br />
* <code>session</code> - A session ID previously obtained from the login module.<br />
* <code>folder</code> - For the import this parameter is required to specify the folder into that the emails should be imported. Example "folder=default.INBOX/Testfolder"<br />
* <code>flags</code> (optional) - In case the mail should be stored with status "read" (e.g. mail has been read already in the client inbox), the parameter "flags" has to be included. For infos about mail flags see [[#DetailedMailData | Detailed mail data]] spec.<br />
*<code>force</code> (optional) - If this parameter is set to true, the server skips checking the valid From-address<br />
<br />
Request Body: A multipart/form-data with a single or multiple file parts each having a different name and containing the RFC822 encoded email as binary data like in a file upload.<br />
<br />
Response: A JSON object containing the folder identifier and the object identifier of the imported mail or a JSON array of those JSON objects if multiple mails are imported.<br />
<br />
=== Reply/Forward a mail ===<br />
<br />
GET <code>/ajax/mail?action=reply</code><br><br />
GET <code>/ajax/mail?action=replyall</code><br><br />
GET <code>/ajax/mail?action=forward</code><br><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested Message.<br />
* <code>folder</code> - Object ID of the folder, whose contents are queried.<br />
* <code>view</code> (optional - available with SP6) - "text" forces the server to deliver a text-only version of the requested mail's body, even if content is HTML. "html" to allow a possible HTML mail body being transferred as it is (but white-list filter applied).'''NOTE:''' if set, the corresponding gui config setting will be ignored.<br />
* <code>setFrom</code> (optional - available since v7.6.0) A flag ("true"/"false") that signals if "From" header shall be pre-selected according to a suitable recipient address that matches one of user's E-Mail address aliases; only supported for <code>/ajax/mail?action=replyall</code> and <code>/ajax/mail?action=reply</code><br />
* <code>max_size</code> (optional - available since v7.6.1) A positive integer number (greater than 10000) to specify how many characters of the message content will be returned. If the number is smaller than 10000 the value will be ignored and 10000 used.<br />
<br />
Response (not IMAP: with timestamp): An object containing all data of the requested mail. The fields of the object are listed in [[#DetailedMailData | Detailed mail data]]. The fields id and attachment are not included.<br />
<br />
=== Delete mails ===<br />
<br />
PUT <code>/ajax/mail?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* Not IMAP: <code>timestamp</code> – Timestamp of the last update of the deleted mails.<br />
<br />
Request body: An array of objects providing folder IDs and object IDs of the deleted mails.<br />
<code><br><br />
[<br><br />
&nbsp;{&nbsp;&quot;folder&quot;:&quot;default0/INBOX&quot;,&nbsp;&quot;id&quot;:&quot;123&quot;&nbsp;}<br><br />
&nbsp;...<br><br />
&nbsp;{&nbsp;&quot;folder&quot;:&quot;default0/MyFolder&quot;,&nbsp;&quot;id&quot;:&quot;134&quot;&nbsp;}<br><br />
]<br><br />
</code><br />
<br />
Not IMAP: Response: An array with object IDs of mails which were modified after the specified timestamp and were therefore not deleted.<br />
<br />
=== Clear mail folder(s) ===<br />
<br />
PUT <code>/ajax/mail?action=clear</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* Not IMAP: <code>timestamp</code> – Timestamp of the last update of the deleted mails.<br />
<br />
Request body: An array with IDs of the mail folders to clear<br />
<br />
Response: An array with IDs of mail folder that could not be cleared; meaning the response body is an empty JSON array if everything went well.<br />
<br />
== Module "groups" ==<br />
<br />
The group module allows to query available groups. It is mainly used by the dialog for the selection of participants.<br />
<br />
=== Get a group ===<br />
<br />
GET <code>/ajax/group?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The group id.<br />
<br />
Response: A group object as described in [[#GroupData | Group data]].<br />
<br />
=== List groups ===<br />
<br />
PUT <code>/ajax/group?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An array with group identifiers.<br />
<br />
Response: An array of group objects as described in [[#GroupData | Group data]].<br />
<br />
=== Search for groups ===<br />
<br />
PUT <code>/ajax/group?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An object with search parameters as described in [[#GroupSearch | Group search]].<br />
<br />
{| id="GroupSearch" cellspacing="0" border="1"<br />
|+ align="bottom" | Group search<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find groups. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|}<br />
<br />
Response with timestamp: An array of group objects as described in [[#GroupData | Group data]].<br />
<br />
{| id="GroupData" cellspacing="0" border="1"<br />
|+ align="bottom" | Group data<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || ID<br />
|-<br />
| display_name || String || Display name<br />
|-<br />
| name || String || Name with character restrictions<br />
|-<br />
| members || Array || The array contains identifier of users that are member of the group.<br />
|}<br />
<br />
=== Create a group ===<br />
<br />
introduced 2008-06-12<br />
<br />
PUT <code>/ajax/group?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Group object as described in [[#GroupData | Group data]]. The field id is not present.<br />
<br />
Response: A json objekt with attribute <code>id</code> of the newly created group.<br />
<br />
=== Delete a group ===<br />
<br />
introduced 2008-06-12<br />
<br />
PUT <code>/ajax/group?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the group to delete.<br />
<br />
Request body: An object with the field “id” containing the unique identifier of the group.<br />
<br />
Response: An empty json array if the group was deleted successfully.<br />
<br />
=== Change a group ===<br />
<br />
introduced 2008-06-12<br />
<br />
PUT <code>/ajax/group?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the group to update.<br />
* <code>timestamp</code> – Time stamp of the group to update. If the group was modified after the specified time stamp, then the update must fail. <br />
<br />
Request body: Group object as described in [[#GroupData | Group data]]. Only modified fields are present and the field id is omitted.<br />
<br />
=== Get updates (since v6.18.1) ===<br />
<br />
introduced 2010-09-13<br />
<br />
GET <code>/ajax/group?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested groups.<br />
<br />
Response with timestamp: An array with new, modified and deleted groups. New, modified and deleted groups are represented by JSON objects as described in [[#GroupData | Group data]].<br />
<br />
== Module "resource" ==<br />
<br />
The resource module allows to query available resources. It is mainly used by the dialog for the selection of participants.<br />
<br />
=== Get all resources ===<br />
<br />
GET <code>/ajax/resource?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: An array of resource identifier.<br />
<br />
=== List resources ===<br />
<br />
PUT <code>/ajax/resource?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
<br />
Request body: An array with resources ids.<br />
<br />
Response: An array of resource objects as described in [[#ResourceResponse | Resource response]].<br />
<br />
=== Get a resource ===<br />
<br />
GET <code>/ajax/resource?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The resource id.<br />
<br />
Response: An array of resource objects as described in [[#ResourceResponse | Resource response]].<br />
<br />
=== Search for resources ===<br />
<br />
PUT <code>/ajax/resource?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An object with search parameters as described in [[#ParticipantSearch | Participant search]].<br />
<br />
{| id="ParticipantSearch" cellspacing="0" border="1"<br />
|+ align="bottom" | Participant search<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find resources. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|}<br />
<br />
Response: An array of resource objects as described in [[#ResourceResponse | Resource response]].<br />
<br />
{| id="ResourceResponse" cellspacing="0" border="1"<br />
|+ align="bottom" | Resource Response<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || ID<br />
|-<br />
| display_name || String || Display name<br />
|-<br />
| name || String || internal name<br />
|-<br />
| mailaddress || String || email address<br />
|-<br />
| availability || Boolean || can be false to mark the resource currently unavailable<br />
|-<br />
| description || String || description of the resource<br />
|-<br />
| last_modified || Time || Date and time of the last modification.<br />
|-<br />
| last_modified_utc || Timestamp || Date and time of the last modification.<br />
|}<br />
<br />
=== Create a resource ===<br />
<br />
PUT <code>/ajax/resource?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Resource object as described in [[#ResourceResponse | Resource response]]. The field id is not present.<br />
<br />
Response: An object with attribute <code>id</code> of the newly created resource.<br />
<br />
=== Delete a resource ===<br />
<br />
PUT <code>/ajax/resource?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the resource to delete.<br />
<br />
Request body: An object with the field “id” containing the unique identifier of the resource.<br />
<br />
Response: An empty json array if the resource was deleted successfully.<br />
<br />
=== Delete resources (since v6.22) ===<br />
<br />
PUT <code>/ajax/resource?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the resource to delete.<br />
<br />
Request body: An array of objects with the field “id” containing the unique identifier of the resource.<br />
<br />
Response: An empty json array if the resources were deleted successfully.<br />
<br />
=== Change a resource ===<br />
<br />
PUT <code>/ajax/resource?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the resource to update.<br />
* <code>timestamp</code> – Time stamp of the resource to update. If the resource was modified after the specified time stamp, then the update must fail. <br />
<br />
Request body: Resource object as described in [[#ResourceResponse | Resource response]]. Only modified fields are present and the field id is omitted.<br />
<br />
=== Get updates (since v6.18.1) ===<br />
<br />
introduced 2010-09-13<br />
<br />
GET <code>/ajax/resource?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested resources.<br />
<br />
Response with timestamp: An array with new, modified and deleted resources. New, modified and deleted resources are represented by JSON objects as described in [[#ResourceResponse | Resource response]].<br />
<br />
== Module "infostore" or "Filestore" or "Files" or "Drive" ==<br />
This module has been renamed quite often. Whatever its name, it combines the knowledge database, bookmarks and document storage.<br />
<br />
=== Get all infoitems ===<br />
<br />
GET <code>/ajax/infostore?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for infoitems are defined in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response with timestamp: An array with infoitem data. Each array element describes one infoitem and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedInfoitemData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed infoitem data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 108 || object_permissions || Array || Each element is an object described in [[#ObjectPermissionObject | Object Permission object]] (preliminary, available with 7.8.0).<br />
|-<br />
| 109 || shareable || Boolean || (read-only) Indicates if the item can be shared (preliminary, available with 7.8.0).<br />
|-<br />
| 700 || title || String || Title<br />
|-<br />
| 701 || url || String || Link/URL<br />
|-<br />
| 702 || filename || String || Displayed filename of the document.<br />
|-<br />
| 703 || file_mimetype || String || MIME type of the document. The client converts known types to more readable names before displaying them.<br />
|-<br />
| 704 || file_size || Number || Size of the document in bytes.<br />
|-<br />
| 705 || version || Number || Version number of the document. New documents start at 1. Every update increments the version by 1.<br />
|-<br />
| 706 || description || String || Description<br />
|-<br />
| 707 || locked_until || Time || The time until which this item will presumably be locked. Only set if the docment is currently locked, 0 otherwise.<br />
|-<br />
| 708 || file_md5sum || String || MD5Sum of the document. Not yet implemented, so this is currently always empty.<br />
|-<br />
| 709 || version_comment || String || A version comment is used to file a changelog for the file.<br />
|-<br />
| 710 || current_version || Boolean || “true” if this version is the current version “false” otherwise. Note: This is not writeable<br />
|-<br />
| 711 || number_of_versions || Number || The number of all versions of the infoitem. Note: This is not writeable.<br />
|-<br />
| 7010 || com.openexchange.share.extendedObjectPermissions || Array || Each element is an object described in [[#ExtendedObjectPermissionObject | Extended object permission object]]. Read Only, Since 7.8.0.<br />
|}<br />
<br />
{| id="ObjectPermissionObject" cellspacing="0" border="1"<br />
|+ align="bottom" | Object Permission object<br />
! Name !! Type !! Value<br />
|-<br />
| bits || Number || A number as described in [[#ObjectPermissionFlags | Object Permission flags]].<br />
|-<br />
| entity || Number || User ID of the user or group to which this permission applies.<br />
|-<br />
| group || Boolean || true if entity refers to a group, false if it refers to a user.<br />
|-<br />
| type || String || The recipient type, i.e. one of "guest", "anonymous" (required if no internal "entity" defined).<br />
|-<br />
| password || String || An additional secret / pin number an anonymous user needs to enter when accessing the share (for type "anonymous", optional) .<br />
|-<br />
| email_address || String || The e-mail address of the recipient (for type "guest").<br />
|-<br />
| display_name || String || The display name of the recipient (for type "guest", optional).<br />
|-<br />
| contact_id || String || The object identifier of the corresponding contact entry if the recipient was chosen from the address book (for type "guest", optional).<br />
|-<br />
| contact_folder || String || The folder identifier of the corresponding contact entry if the recipient was chosen from the address book (for type "guest", required if "contact_id" is set).<br />
|-<br />
| expiry_date || Time || The end date / expiration time after which the share link is no longer accessible (for type "guest" or "anonymous", optional).<br />
|}<br />
<br />
{| id="ExtendedObjectPermissionObject" cellspacing="0" border="1"<br />
|+ align="bottom" | Extended object permission object<br />
! Name !! Type !! Value<br />
|-<br />
| entity || Number || Identifier of the permission entity (i.e. user-, group- or guest-ID).<br />
|-<br />
| bits || Number || A number as described in [[#ObjectPermissionFlags | Object Permission flags]].<br />
|-<br />
| type || String || "user" for an internal user, "group" for a group, "guest" for a guest, or "anonymous" for an anonymous permission entity.<br />
|-<br />
| display_name || String || A display name for the permission entity.<br />
|-<br />
| contact || Object || A (reduced) set of [[#DetailedContactData | Detailed contact data]] for "user" and "guest" entities.<br />
|-<br />
| share_url || String || The share link for "guest" and "anonymous" entities.<br />
|-<br />
| password || String || The optionally set password for "anonymous" entities.<br />
|-<br />
| expiry_date || Date || The optionally set expiry date for "anonymous" entities.<br />
|}<br />
<br />
{| id="ObjectPermissionFlags" cellspacing="0" border="1"<br />
|+ align="bottom" | Object Permission flags<br />
! Bits !! Value<br />
|-<br />
| 0 || The numerical value indicating no object permissions.<br />
|-<br />
| 1 || The numerical value indicating read object permissions.<br />
|-<br />
| 2 || The numerical value indicating write object permissions. This implicitly includes the “read” permission (this is no bitmask).<br />
|-<br />
| 4 || The numerical value indicating delete object permissions. This implicitly includes the “read” and “write” permission (this is no bitmask).<br />
|}<br />
<br />
=== Get a list of infoitems ===<br />
<br />
PUT <code>/ajax/infostore?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for infoitems are defined in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
<br />
Request body: An array with object IDs of requested infoitems.<br />
<br />
Response with timestamp: An array with infoitem data. Each array element describes one infoitem and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get updated infoitems ===<br />
<br />
GET <code>/ajax/infostore?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for infoitems are defined in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested infoitems.<br />
* <code>ignore</code> (optional) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
<br />
Response with timestamp: An array with new, modified and deleted infoitems. New and modified infoitems are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted infoitems (should the <code>ignore</code> parameter be ever implemented) would be identified by their object IDs as plain strings, without being part of a nested array.<br />
<br />
=== Get an infoitem ===<br />
<br />
GET <code>/ajax/infostore?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested infoitem.<br />
* <code>version</code> (optional) – If present the infoitem data describes the given version. Otherwise the current version is returned <br />
<br />
Response with timestamp: An object containing all data of the requested infoitem. The fields of the object are listed in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. The field id is not included.<br />
<br />
=== Search infoitems ===<br />
<br />
PUT <code>/ajax/infostore?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields as per tables [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>start</code> (optional) – The start index (inclusive) in the ordered search, that is requested.<br />
* <code>end</code> (optional) – The last index (inclusive) from the ordered search, that is requested.<br />
<br />
Request body: An Object as described in [[#SearchContacts | Search contacts]].<br />
<br />
=== Get an infoitem document ===<br />
<br />
GET <code>/ajax/infostore/[filename]?action=document</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested infoitem.<br />
* <code>folder</code> – Object ID of the infoitem's folder.<br />
* <code>version</code> (optional) – If present the infoitem data describes the given version. Otherwise the current version is returned <br />
* <code>content_type</code>(optional) – If present the response declares the given content_type in the Content-Type header.<br />
<br />
Response body: The raw byte data of the document. The response type for the HTTP Request is set accordingly to the defined mimetype for this infoitem or the content_type given.<br />
<br />
Note: The Filename may be added to the customary infostore path to suggest a filename to a Save-As dialog.<br />
<br />
=== Get a ZIP archive containing the infoitems of a denoted folder (available with v7.6.1) ===<br />
<br />
GET <code>/ajax/infostore/[filename]?action=zipfolder</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the infoitem's folder.<br />
* <code>recursive</code> – <code>true</code> to also include subfolders and their infoitems respectively; otherwise <code>false</code> to only consider the infoitems of specified folder<br />
<br />
Response body: The raw byte data of the ZIP archive. The response type for the HTTP Request is set to <code>application/zip</code>.<br />
<br />
=== Get all versions ===<br />
<br />
GET <code>/ajax/infostore?action=versions</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the infoitem whose versions are requested.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for infoitems are defined in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response with timestamp: An array with infoitem data. Each array element describes one infoitem and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. The timestamp is the timestamp relating to the requested infostore item.<br />
<br />
=== Get multiple documents as a ZIP archive (available with v7.4.0) ===<br />
<br />
GET <code>/ajax/infostore?action=zipdocuments</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>body</code> – A URL-encoded JSON array; see below for details<br />
<br />
Parameter <code>body</code>: A JSON array of JSON object tuples specifying the documents' versions to include in the requested ZIP archive; e.g<br><br />
<pre><br />
[{"id":"61820","folder":"70303"},{"id":"61821","folder":"70303", "version": "1"}]<br />
</pre><br />
The field <code>"version"</code> is optional; if missing it refers to latest/current version.<br><br />
So, a valid parameter would look like:<br />
<pre><br />
...&body=%5B%7B%22id%22%3A%2261820%22%2C%22folder%22%3A%2270303%22%7D%2C%7B%22id%22%3A%2261821%22%2C%22folder%22%3A%2270303%22%2C%22version%22%3A%221%22%7D%5D<br />
</pre><br />
<br />
Response: The download offer for the requested ZIP archive containing specified document versions<br />
<br />
=== Update an infoitem via PUT ===<br />
<br />
PUT <code>/ajax/infostore?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated infoitem.<br />
* <code>timestamp</code> – Timestamp of the updated infoitem. If the infoitem was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. Only modified fields are present.<br />
<br />
=== Update an infoitem via POST ===<br />
<br />
POST <code>/ajax/infostore?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated infoitem.<br />
* <code>timestamp</code> – Timestamp of the updated infoitem. If the infoitem was modified after the specified timestamp, then the update must fail.<br />
* <code>json</code> - Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. Only modified fields are present.<br />
* <code>file</code> – File Metadata as per <input type=”file” /><br />
<br />
Request Body: Body of content-type “multipart/form-data” or “multipart/mixed” containing the above mentioned fields and file-data.<br />
<br />
Response: The response is sent as a HTML document (see introduction).<br />
<br />
=== Create an infoitem via PUT ===<br />
<br />
PUT <code>/ajax/infostore?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. The field id is not included.<br />
<br />
Response: Object ID of the newly created infoitem.<br />
<br />
=== Create an infoitem via POST ===<br />
<br />
POST <code>/ajax/infostore?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>json</code> - Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. The field id is not included.<br />
* <code>file</code> – File metadata as per <input type=”file” /><br />
<br />
Request Body: Body of content-type “multipart/form-data” or “multipart/mixed” containing the above mentioned fields and file-data.<br />
<br />
Response: Object ID of the newly created infoitem. The response is sent as a HTML document (see introduction).<br />
<br />
=== Save an attachment in the infostore ===<br />
<br />
PUT <code>/ajax/infostore?action=saveAs</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>attached</code> – The Object ID of the Object with the attachment<br />
* <code>folder</code> – The Folder ID of the Object with the attachment<br />
* <code>module</code> – The Module type of the Object with the attachment.<br />
* <code>Attachment</code> – The id of the attachement to save.<br />
<br />
Request body: Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. The field id is not included. The fields in this infoitem object override values from the attachment. The folder_id must be given.<br />
<br />
Response: Object ID of the newly created infoitem.<br />
<br />
=== Delete infoitems ===<br />
<br />
PUT <code>/ajax/infostore?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted infoitems.<br />
* <code>hardDelete</code> - Optional, defaults to \"false\". If set to \"true\", the file is deleted permanently. Otherwise, and if the underlying storage supports a trash folder and the file is not yet located below the trash folder, it is moved to the trash folder.<br />
<br />
Request body: An array with objects to delete. The fields for the object are described in [[#FullIdentifierForAnInfostoreDocument|Full identifier for an infostore document]].<br />
<br />
Response: An array with [[]]. <br />
<br />
{| id="FullIdentifierForAnInfostoreDocument" cellspacing="0" border="1"<br />
|+ align="bottom" | Full identifier for an infostore document<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || Object ID<br />
|-<br />
| folder || Number || Folder ID<br />
|}<br />
<br />
=== Delete versions of infostore documents ===<br />
<br />
PUT <code>/ajax/infostore?action=detach</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the base Object<br />
* <code>folder</code> – The Folder of the Object<br />
* <code>timestamp</code> - Timestamp of the infostore object<br />
<br />
Request body: A List of arrays with the version numbers of the infoitems to detach.<br />
<br />
Response: An array with version numbers that were not deleted.<br />
<br />
Note: When the current version of a document is deleted the new current version will be the newest version.<br />
<br />
=== Delete all versions of infostore documents ===<br />
<br />
PUT <code>/ajax/infostore?action=revert</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the base Object<br />
* <code>folder</code> – The Folder of the Object<br />
* <code>timestamp</code> - Timestamp of the infostore object<br />
<br />
Removes all versions of the infostore document leaving only the base object.<br />
<br />
=== Copy an infostore document via PUT ===<br />
<br />
PUT <code>/ajax/infostore?action=copy</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the base Object<br />
* <code>folder</code> – The Folder of the Object<br />
* <code>timestamp</code> - Timestamp of the infostore object<br />
<br />
Request body: Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. Only modified fields are present.<br />
<br />
Response: The id of the newly created object<br />
<br />
Note: Only the fields (and the file) of the current document will be copied. Those fields present in the request are modified accordingly.<br />
<br />
=== Copy an infostore document via POST ===<br />
<br />
POST <code>/ajax/infostore?action=copy</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated infoitem.<br />
* <code>timestamp</code> – Timestamp of the updated infoitem. If the infoitem was modified after the specified timestamp, then the update must fail.<br />
* <code>json</code> - Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. Only modified fields are present.<br />
* <code>file</code> – File Metadata as per <input type=”file” /><br />
<br />
Request Body: Body of content-type “multipart/form-data” or “multipart/mixed” containing the above mentioned fields and file-data.<br />
<br />
Response: The response is sent as a HTML document (see introduction).<br />
<br />
Note: Only the fields (and the file) of the current document will be copied. Those fields present in the request are modified accordingly.<br />
<br />
=== Lock an infoitem ===<br />
<br />
GET <code>/ajax/infostore?action=lock</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the infoitem that should be locked.<br />
* <code>diff</code> (optional) – If present the value is added to the current time on the server (both in ms). The document will be locked until that time. If this parameter is not present, the document will be locked for a duration as configured on the server.<br />
<br />
Response with timestamp: Can only include errors.<br />
<br />
=== Unlock an infoitem ===<br />
<br />
GET <code>/ajax/infostore?action=unlock</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the infoitem that should be unlocked.<br />
<br />
Response with timestamp: Can only contain errors.<br />
<br />
=== Get shared infoitems (Since 7.8.0, Preliminary) ===<br />
<br />
GET <code>/ajax/infostore?action=shares</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for infoitems are defined in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response: An array with infoitem data. Each array element describes one infoitem and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
== Module "Attachments" ==<br />
<br />
The Attachment Module allows file attachments to arbitrary objects. An Attachment always belongs to an object (called 'attached') in a certain folder of a certain module. <br />
<br />
=== Get All Attachments for an Object ===<br />
<br />
GET <code>/ajax/attachment?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>attached</code> – The Object ID of the Object<br />
* <code>folder</code> – The Folder ID of the Object<br />
* <code>module</code> – The Module type of the Object<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for attachment's are defined in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response: An array with attachment data. Each array element describes one attachment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a list of attachments ===<br />
<br />
PUT <code>/ajax/attachment?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for attachments are defined in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]].<br />
* <code>attached</code> – The Object ID of the Object<br />
* <code>folder</code> – The Folder ID of the Object<br />
* <code>module</code> – The Module type of the Object<br />
<br />
Request body: An array of with object IDs of requested tasks.<br />
<br />
Response with timestamp: An array with attachment data. Each array element describes one attachment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Create an Attachment ===<br />
<br />
POST <code>/ajax/attachment?action=attach</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>json_[index]</code> – The JSON representation of an attachment object as described in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]].<br />
* <code>file_[index]</code> – The file metadata as per <input type=file /> upload.<br />
<br />
Note: The JSON Object and file fields describe the corresponding attachment. For ex.: json_0 contains metadata for file_0, json_1 for file_1 and so on. Indexes start with 0.<br />
<br />
Request body: multipart/form-data or multipart/mixed containing the file data of the attached file and the above fields.<br />
<br />
Response: HTML page with javascript callback as per introduction. Contains a JSON-Array of ids of the newly created attachments. The order of the ids corresponds to the indexes in the request.<br />
<br />
{| id="AttachmentObject" cellspacing="0" border="1"<br />
|+ align="bottom" | Attachment Object<br />
! ID !! Name !! Type !! Description<br />
|-<br />
| 800 || folder || Number || The ID of the first Folder in which the attached object resides.<br />
|-<br />
| 801 || attached || Number || The object id of the object this attachement is attached to.<br />
|-<br />
| 802 || module || Number || The Module of this Object Possible Values:<br />
{| cellspacing="0" border="1"<br />
| 1 || Appointment<br />
|-<br />
| 4 || Task<br />
|-<br />
| 7 || Contact<br />
|-<br />
| 137 || Infostore<br />
|}<br />
|-<br />
| 803 || filename || String || The filename of the attached file.<br />
|-<br />
| 804 || file_size || Number || The file size (in bytes) of the attached file.<br />
|-<br />
| 805 || file_mimetype || String || The MIME-Type of the attached file<br />
|-<br />
| 806 || rft_flag || Boolean || If the attachment is a RTF Attachment of Outlook. (Outlook descriptions can be stored as RTF Documents).<br />
|}<br />
<br />
=== Delete Attachment ===<br />
<br />
PUT <code>/ajax/attachment?action=detach</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>attached</code> – The ID of the base Object<br />
* <code>module</code> – The type of the Object<br />
* <code>folder</code> – The Folder of the Object<br />
<br />
Request body: An array with the ids of the attachments to delete.<br />
<br />
=== Get updated attachments ===<br />
<br />
GET <code>/ajax/attachment?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>attached</code> – Object ID of the object to which the attachments are attached.<br />
* <code>module</code> – Module ID (as per [[#AttachmentObject | Attachment object]]) of the attached object.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for attachments are defined in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested infoitems.<br />
ignore (optional) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
<br />
Response with timestamp: An array with new and deleted attachments for the specified object. New attachments are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted attachments (should the <code>ignore</code> parameter be ever implemented) would be identified by their object IDs as plain numbers, without being part of a nested array.<br />
<br />
=== Get an attachment ===<br />
<br />
GET <code>/ajax/attahment?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>attached</code> – Object ID of the object to which the attachments are attached.<br />
* <code>module</code> – Module ID (as per [[#AttachmentObject | Attachment object]]) of the attached object.<br />
* <code>id</code> – Object ID of the requested attachment.<br />
<br />
Response with timestamp: An object containing all data of the requested attachment. The fields of the object are listed in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]]. <br />
<br />
=== Get an attachments filedata ===<br />
<br />
GET <code>/ajax/attachment/[filename]?action=document</code><br />
<br />
Parameters:<br />
<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>attached</code> – Object ID of the object to which the attachments are attached.<br />
* <code>module</code> – Module ID (as per [[#AttachmentObject | Attachment object]]) of the attached object.<br />
* <code>id</code> – Object ID of the requested attachment.<br />
* <code>content_type</code> (optional) – If set the responses Content-Type header is set to this value, not the attachements file mime type.<br />
<br />
Response body: The raw byte data of the document. The response type for the HTTP Request is set accordingly to the defined mimetype for this infoitem.<br />
Note: The Filename may be added to the customary infostore path to suggest a filename to a Save-As dialog.<br />
<br />
== Module "reminder" ==<br />
<br />
The reminder module provides the ability to fetch all active reminders for a user between two dates.<br />
<br />
=== Get reminder range ===<br />
<br />
GET <code>/ajax/reminder?action=range</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>end</code> – The End date of the reminder range<br />
<br />
Response: An Array with all reminders which are scheduled until the specified time. Each reminder is described in [[#ReminderResponse | Reminder response]].<br />
<br />
{| id="ReminderResponse" cellspacing="0" border="1"<br />
|+ align="bottom" | Reminder response<br />
! Field !! Type !! Description<br />
|-<br />
| id || Number || The ID of the reminder.<br />
|-<br />
| target_id || Number || The target_id where this reminder is attached to<br />
|-<br />
| alarm || Time || The time of the alarm<br />
|-<br />
| module || Number || The module of the reminder<br />
|-<br />
| servertime || Time || The time on the server<br />
|-<br />
| user_id || Number || The ID of the user.<br />
|-<br />
| last_modified || Time || The last modification timestamp of the reminder<br />
|-<br />
| recurrence_position || Number || The recurrence position for series appointments or 0 if no series<br />
|-<br />
| folder || Number || The ID of the folder through that the object can be read<br />
|-<br />
|}<br />
<br />
=== Delete a Reminder===<br />
<br />
PUT <code>/ajax/reminder?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An object with the field “id”.<br />
<br />
Response body: An JSON array with the id that was not deleted.<br />
<br />
=== Delete Reminders (since v6.22)===<br />
<br />
PUT <code>/ajax/reminder?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An array of objects with the field “id”.<br />
<br />
Response body: An JSON array with the ids that were not deleted.<br />
<br />
=== Remind again (since v6.18.1) ===<br />
<br />
PUT <code>/ajax/reminder?action=remindAgain</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the reminder whose date shall be changed.<br />
<br />
Request body: The JSON representation of the reminder; mainly containing the field “alarm” which provides the new reminder date.<br><br />
E.g. <code>{ "alarm": 1283418027381 }</code><br />
<br />
Response body: The JSON representation of the updated reminder.<br />
<br />
== Module "multiple" ==<br />
<br />
The multiple module allows to bundle multiple requests to most other modules in a single request. Not supported are:<br />
* modules login and multiple,<br />
* POST requests with a multipart encoding (uploads),<br />
* GET requests which do not use an object as described in [[#ResponseBody | Response body]] as response body (downloads).<br />
<br />
=== Multiple requests ===<br />
<br />
PUT <code>/ajax/multiple</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>continue</code> – Specifies whether processing of requests should stop when an error occurs, or whether all request should be processed regardless of errors.<br />
<br />
Request body: An array with request objects. Each request object contains all URI parameters of the "normal" request as fields. The module name of the "normal" request is included in the field module. The parameter session is not included. If the "normal" request has a request body, the object which is represented by that request body is includes as the value of the field data.<br />
<br />
Response: An array with reply objects as described in [[#ResponseBody | Response body]]. The order of reply objects corresponds to the order of requests in the request body. Unlike with all other modules, this response is itself not part of a response object as described in [[#ResponseBody | Response body]].<br />
<br />
== Module "quota" ==<br />
<br />
The filestore module allows accesssing information about the use and quota of the filestore.<br />
<br />
=== Get quota information (Since 7.6.1, Preliminary) ===<br />
<br />
GET <code>/ajax/quota?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>module</code> (optional) – The module identifier to get quota information for, required if <code>account</code> is set.<br />
* <code>account</code> (optional) – The account identifier within the module to get quota information for.<br />
<br />
Response: A JSON object containing the requested quota information. If no <code>module</code> was specified, all defined [[#ModuleQuota | module quotas]] are set in the JSON object, each one mapped to it's module identifier. If the quota from a <code>module</code> was requested, a JSON array containing all [[#AccountQuota | account quotas]] of this module are returned. If both a <code>module</code> and <code>account</code> were requested, a JSON object representing this specific [[#AccountQuota | account auota]] is returned. <br />
<br />
Note: In case there is no quota limitation defined for a module or account, no corresponding JSON object is included in the response. <br />
<br />
<br />
{| id="ModuleQuota" cellspacing="0" border="1"<br />
|+ align="bottom" | Module Quota<br />
! Field !! Type !! Description<br />
|-<br />
| display_name || String || The display name of the module<br />
|-<br />
| accounts|| Array || Each element identifies an account quota within the module, as described in [[#AccountQuota | Account Quota]]<br />
|-<br />
|}<br />
<br />
<br />
{| id="AccountQuota" cellspacing="0" border="1"<br />
|+ align="bottom" | Account Quota<br />
! Field !! Type !! Description<br />
|-<br />
| account_id || String || Identifier of the account<br />
|-<br />
| account_name || String || Name of the account<br />
|-<br />
| countquota || Number || The account's quota limit for the number of items, or not set if not defined<br />
|-<br />
| countuse || Number || The account's actual usage for the number of items, or not set if no count quota defined<br />
|-<br />
| quota || Number || The account's quota limit for the storage in bytes, or not set if not defined<br />
|-<br />
| use || Number || The account's actual usage for the storage in bytes, or not set if no storage quota defined<br />
|-<br />
|}<br />
<br />
<br />
=== Get the filestore usage data ===<br />
<br />
GET <code>/ajax/quota?action=filestore</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: A JSON Object containing the fields “use” and “quota”. “use” represents the uploaded files sizes sum and the field “quota” represents the maximum.<br />
<br />
=== Get the mail usage data ===<br />
<br />
GET <code>/ajax/quota?action=mail</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: A JSON Object containing the fields “use” and “quota”. “use” represents the use mail quota and the field “quota” represents the maximum. -1 represents an unlimited quota.<br />
<br />
== Module "import"==<br />
The module import allows to import specific module data (like Contacts, Tasks or Appointments) in several formats (iCal, vCard, CSV) into a folder. Please note: The callback for all actions of this bundle is callback_import, not callback_$actionname for legacy purposes.<br />
<br />
=== Import CSV ===<br />
POST <code>/ajax/import?action=CSV</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder into which data should be imported. This must be a Contact folder.<br />
* <code>charset</code> (preliminary, since 7.6.2) – Optional. A fixed character encoding to use when parsing the uploaded file, overriding the built-in defaults, following the conventions documented in RFC 2278.<br />
<br />
Request body: A "multipart/form-data" encoded .CSV file. The field name for the file is "file". The column titles of the table are those used within the OX, see column ''Displayed Name'' in [[#DetailedContactData]].<br />
<br />
Response: An array of JSON-Objects, one for each entry in the list, containing: The Object ID of the entry, the Object ID of the folder the data was written into, a timestamp of the modification (in case of error, of modification attempt) and an error in case the data could not be entered.<br />
<br />
=== Import Outlook CSV ===<br />
POST <code>/ajax/import?action=OUTLOOK_CSV</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder into which data should be imported. This must be a Contact folder.<br />
* <code>charset</code> (preliminary, since 7.6.2) – Optional. A fixed character encoding to use when parsing the uploaded file, overriding the built-in defaults, following the conventions documented in RFC 2278.<br />
<br />
Request body: An .CSV file with Windows' default encoding Windows-1252. The column titles of the table may be those used by the English, French or German version of Outlook.<br />
<br />
Response: An array of JSON-Objects, one for each entry in the list, containing: The Object ID of the entry, the Object ID of the folder the data was written into, a timestamp of the modification (in case of error, of modification attempt) and an error in case the data could not be entered.<br />
<br />
=== Import iCAL ===<br />
POST <code>/ajax/import?action=ICAL</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder into which data should be imported. This may be an Appointment or a Task folder. May even be a list containing both.<br />
* <code>suppressNotification</code> – This optional parameter can be used to disable the notifications for new appointments that are imported through the given iCal file. This help keeping the Inbox clean if a lot of appointments need to be imported. The value of this parameter does not matter because only for the existence of the parameter is checked.<br />
* <code>ignoreUIDs</code> – Optional. When set to "true", UIDs are partially ignored during import of tasks and appointments from iCal. Internally, each UID is replaced statically by a random one to preserve possibly existing relations between recurring appointments in the same iCal file, but at the same time to avoid collisions with already existing tasks and appointments.<br />
<br />
Request body: An iCalendar file.<br />
<br />
Response: An array of JSON-Objects, one for each entry in the list, containing: The Object ID of the entry, the Object ID of the folder the data was written into, a timestamp of the modification (in case of error, of modification attempt) and an error in case the data could not be entered, and warnings (under the key "warnings") containing an Array of objects with the warning data, containing all customary error fields.<br />
<br />
=== Import vCard ===<br />
POST <code>/ajax/import?action=VCARD</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder into which data should be imported. This must be a Contact folder.<br />
<br />
Request body: An vCard file, maybe of the formats: vCard 2.1, vCard 3.0 or vCalendar 1.0<br />
<br />
Response: An array of JSON-Objects, one for each entry in the list, containing: The Object ID of the entry, the Object ID of the folder the data was written into, a timestamp of the modification (in case of error, of modification attempt) and an error in case the data could not be entered.<br />
<br />
== Module "export" ==<br />
The module export allows to export specific module data (like Contacts, Tasks or Appointments) from a folder in several formats (iCal, vCard, CSV).<br />
<br />
=== Exporting CSV ===<br />
GET <code>/ajax/export?action=CSV</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder whose contents are to be exported. This must be a Contact folder.<br />
* <code>columns</code> – (optional) Columns to be imported from the given file, given as an array of column numbers. See [[#DetailedContactData | Detailed contact data]] for numbers.<br />
* <code>export_dlists</code> – (optional) toggles whether distribution lists are exported, too. Default is false. Option exists since 7.4.1.<br />
Response: An InputStream containing the file of the MIME type <code>text/csv</code>.<br />
<br />
=== Exporting iCAL ===<br />
GET <code>/ajax/export?action=ICAL</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder whose contents are to be exported. This must be a Calendar folder.<br />
<br />
Response: An InputStream containing the file, of the MIME type <code>text/calendar</code>.<br />
<br />
=== Exporting vCard ===<br />
GET <code>/ajax/export?action=VCARD</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder whose contents are to be exported. This must be a Contact folder.<br />
<br />
Response: An InputStream containing the file, of the MIME type <code>text/x-vcard</code>.<br />
<br />
== Module "sync" ==<br />
The module sync delivers several core API extensions to support common operations used in a mobile synchronization environment.<br />
<br />
=== Clearing a folder's content ===<br />
PUT <code>/ajax/sync?action=refresh_server</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON array containing the folder ID(s) whose content should be cleared. '''NOTE:''' Although the requests offers to clear multiple folders at once it is recommended to clear only one folder per request since if any exception occurs<br />
(e.g. missing permissions) the complete request is going to be aborted.<br />
<br />
Response: A JSON array containing the IDs of folders that could not be cleared due to a concurrent modification. Meaning you receive an empty JSON array if everything worked well.<br />
<br />
== Module "token" (since 7.4.0) ==<br />
The module token delivers several core API extensions to support token based logins.<br />
<br />
=== Get a login token ===<br />
GET <code>/ajax/token?action=acquireToken</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response:<br />
A JSON object with the timestamp of the creation date and a token which can be used to create a new session.<br />
<br />
== Module "mailfilter" ==<br />
The module mailfilter describes how to add, update or delete mail filter rules or to check which actions are supported by the underlying system.<br />
<br />
A detailed description can be found here [[ HTTP_API_MailFilter | Mail Filter HTTP API]]<br />
<br />
== Module "ajax file upload" ==<br />
This module offers to store files in server's dedicated download directory for a configureable amount of time. The files are then accessible for further operations like inline images in (html) mails<br />
<br />
=== Uploading a file ===<br />
POST <code>/ajax/file?action=new</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>module</code> – The module for which the file is uploaded to determine proper upload quota constraints (e.g. "mail", "infostore", etc.).<br />
* <code>type</code> – The file type filter to define which file types are allowed during upload. Currently supported filters are: <code>file=all, text=text/*, media=image OR audio OR video, image=image/*, audio=audio/*, video=video/*, application=application/*</code><br />
<br />
Request body: A common POST request body of MIME type "multipart/*" which holds the file(s) to upload<br />
<br />
Response: A JSON array containing the IDs of the uploaded files. The files are accessible through the returned IDs for future use.<br />
<br />
=== Updating a file's last access timestamp (keep alive) ===<br />
By updating the last access timestamp it's prevented from being deleted from both session and disk storage.<br />
<br />
GET <code>/ajax/file?action=keepalive</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the uploaded file whose timestamp should be updated<br />
<br />
Response: The string "null" in response's data element<br />
<br />
=== Requesting a formerly uploaded file ===<br />
GET <code>/ajax/file?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the uploaded file<br />
<br />
Response: The content of the requested file is directly written into output stream<br />
<br />
== Module "image" ==<br />
This module allows to download images from Open-Xchange server without providing a session ID in request's URL parameters.<br />
<br />
=== Requesting an image ===<br />
Open-Xchange Server supports multiple image sources that are identified through request's path identifier<br />
<br />
* Inline images from mails<br />
** Request path needs to be <code>"/mail/picture"</code><br><br><br />
* Contact profile image<br />
** Request path needs to be <code>"/contact/picture"</code><br><br><br />
* User profile image<br />
** Request path needs to be <code>"/user/picture"</code><br><br><br />
* MP3 cover image<br />
** Request path needs to be <code>"/file/mp3cover"</code><br><br><br />
* Fetch a previously uploaded image using <code>"/ajax/file"</code> interface<br />
** Request path needs to be <code>"/mfile/picture"</code><br><br><br />
<br />
Each image source requires an individual set of required parameters<br />
<br />
==== Inline images from mails ====<br />
GET <code>/mail/picture</code> <br />
<br />
Parameters:<br />
* <code>accountId</code> – The mail account identifier<br />
* <code>folder</code> – The identifier of the folder in which the mail resides<br />
* <code>id</code> – The mail identifier<br />
* <code>uid</code> – The identifier of the image inside the referenced mail<br />
<br />
Response: The content of the requested image is directly written into output stream<br />
<br />
<br />
==== Contact profile images ====<br />
GET <code>/contact/picture</code> <br />
<br />
Parameters:<br />
* <code>folder</code> – The identifier of the folder in which the contact resides<br />
* <code>id</code> – The contact identifier<br />
<br />
Response: The content of the requested image is directly written into output stream<br />
<br />
<br />
==== User profile images ====<br />
GET <code>/user/picture</code> <br />
<br />
Parameters:<br />
* <code>id</code> – The user identifier<br />
<br />
Response: The content of the requested image is directly written into output stream<br />
<br />
<br />
==== MP3 cover image ====<br />
GET <code>/file/mp3cover</code> <br />
<br />
Parameters:<br />
* <code>id</code> – The identifier of the uploaded image<br />
<br />
Response: The content of the requested image is directly written into output stream<br />
<br />
<br />
==== Managed Image File ====<br />
GET <code>/image/mfile/picture</code> <br />
<br />
Parameters:<br />
* <code>uid</code> – The identifier of the uploaded image<br />
<br />
Response: The content of the requested image is directly written into output stream<br />
<br />
== Module "conversion" (preliminary) ==<br />
<br />
A generic module to request data from a data source and to process obtained/submitted data with a data handler. Thus data is converted from a data source by a data handler.<br />
<br />
=== Converting data ===<br />
PUT <code>/ajax/conversion?action=convert</code><br><br />
or<br><br />
POST <code>/ajax/conversion?action=convert</code> <br />
<br />
Parameters: &lt;no parameters required&gt;<br />
<br />
Request body: A [[#ConversionRequest | conversion request]] JSON object containing nested JSON objects for [[#DataSource | data source]] and [[#DataHandler | data handler]]<br />
<br />
<br />
{| id="ConversionRequest" cellspacing="0" border="1"<br />
|+ align="bottom" | Conversion request object<br />
! Field !! Type !! Description<br />
|-<br />
| datasource || JSON object || The data source object.<br />
|-<br />
| datahandler || JSON object || The data handler object.<br />
|-<br />
|}<br />
<br />
<br />
{| id="DataSource" cellspacing="0" border="1"<br />
|+ align="bottom" | Data source object<br />
! Field !! Type !! Description<br />
|-<br />
| identifier || String || The identifier of the data source.<br />
|-<br />
| args || JSON array or JSON object || The '''optional''' name-value-pairs as a single JSON object or a JSON object for each kept inside a JSON array for data source<br />
|-<br />
|}<br />
<br />
<br />
{| id="DataHandler" cellspacing="0" border="1"<br />
|+ align="bottom" | Data handler object<br />
! Field !! Type !! Description<br />
|-<br />
| identifier || String || The identifier of the data handler.<br />
|-<br />
| args || JSON array or JSON object || The '''optional''' name-value-pairs as a single JSON object or a JSON object for each kept inside a JSON array for data handler<br />
|-<br />
|}<br />
<br />
Response: The result of converted data ready as an appropriate JSON response<br />
<br />
==== Saving an ICal email attachment ====<br />
<br />
If an ICal file is attached to an email, its content can be saved as appointments and tasks into given calendar and task folder.<br />
If the fields "com.openexchange.groupware.calendar.confirmstatus" and "com.openexchange.groupware.calendar.confirmmessage" are set, the data handler inserts the appointment with the given status for the user, if the appointment does not exist. If it is already existing, the handler just updates the participant status.<br />
<br />
Data source's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.mail.ical&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.fullname&quot;:&quot;&lt;folder-fullname&gt;&quot;},<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.mailid&quot;:&quot;&lt;mail-id&gt;&quot;},<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.sequenceid&quot;:&quot;&lt;attachment-sequence-id&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Data handler's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.ical&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.groupware.calendar.folder&quot;:&quot;&lt;calendar-folder-id&gt;&quot;},<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.task.folder&quot;:&quot;&lt;task-folder-id&gt;&quot;},<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.calendar.confirmstatus&quot;:&quot;&lt;status&gt;&quot;},<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.calendar.confirmmessage&quot;:&quot;&lt;message&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Response: A JSON array of JSON objects each providing folder and object ID of added appointment/task; e.g. <code>[{&quot;folder_id&quot;:2567, &quot;id&quot;:7689}, ...]</code><br />
<br />
==== Converting an ICal email attachment into JSON objects ====<br />
<br />
If an ICal file is attached to an email, its content can converted to JSON appointments and tasks.<br />
<br />
Data source's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.mail.ical&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.fullname&quot;:&quot;&lt;folder-fullname&gt;&quot;}<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.mailid&quot;:&quot;&lt;mail-id&gt;&quot;}<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.sequenceid&quot;:&quot;&lt;attachment-sequence-id&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Data handler's JSON object.<br><br />
'''Note''' that all arguments are optional: Default is user time zone and zero recurrence position<br><br />
"com.openexchange.groupware.calendar.searchobject" triggers a search for the uid, and replaces the object_id and folder_id with the data of the corresponding ox-object id, if existing. The returned objects are still the ical objects and NOT the ox-objects.<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.ical.json&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.groupware.calendar.timezone&quot;:&quot;&lt;timezone-id&gt;&quot;}<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.calendar.recurrencePosition&quot;:&quot;&lt;recurrence-position&gt;&quot;}<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.calendar.searchobject&quot;:&quot;&lt;true|false&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Response: A JSON array of JSON objects for each appointment/task as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]]/[[##DetailedAppointmentData | Detailed appointment data]]<br />
<br />
==== Saving a VCard email attachment ====<br />
<br />
If a VCard file is attached to an email, its content can be saved as contacts into given contact folder.<br />
<br />
Data source's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.mail.vcard&quot;,<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.fullname&quot;:&quot;&lt;folder-fullname&gt;&quot;},<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.mailid&quot;:&quot;&lt;mail-id&gt;&quot;},<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.sequenceid&quot;:&quot;&lt;attachment-sequence-id&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Data handler's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.contact&quot;,<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.groupware.contact.folder&quot;:&quot;&lt;contact-folder-id&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Response: A JSON array of JSON objects each providing folder and object ID of added contact; e.g. <code>[{&quot;folder_id&quot;:2567, &quot;id&quot;:7689}, ...]</code><br />
<br />
==== Contact(s) attached to a new email as a VCard file ====<br />
<br />
Obtain VCard data from specified contact object(s).<br />
<br />
Data source's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.contact&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;folder&quot;:&quot;&lt;folder-id1&gt;&quot;,&quot;id&quot;:&quot;&lt;id1&gt;&quot;}<br><br />
&nbsp;&nbsp;&nbsp;...<br><br />
&nbsp;&nbsp;&nbsp;{&quot;folder&quot;:&quot;&lt;folder-idn&gt;&quot;,&quot;id&quot;:&quot;&lt;idn&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Get a new email's JSON object with specified VCard data source attached.<br />
<br />
Data handler's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.mail.vcard&quot;<br><br />
&nbsp;&quot;args&quot;:[]<br><br />
}<br><br />
</code><br />
<br />
Response: A [[#DetailedMailData | mail]] JSON object.<br />
<br />
== Module "search" (preliminary) ==<br />
<br />
The search module is an enhancement to each search request as an optional JSON object via PUT method to filter elements; e.g.<br />
<br />
<code><br />
PUT /ajax/contacts?action=all&...<br />
<br />
{"filter":{search-term-object}}<br />
</code><br />
<br />
This section describes the syntax of the optional JSON object representing the search term.<br><br />
In general the structure of a search term is in prefix notation; meaning the operator is written before its operands:<br />
<br />
<code>{"operation":"equals","operands":[...]}</code><br />
<br />
Moreover there are two different types of a search terms:<br />
* A single search term<br />
* A composite search term<br />
<br />
A single search term reflects an operation which cannot hold nested search terms as operands; e.g. "equals". In opposite to this a composite search term holds one or more nested search terms as operands; e.g. "not" or the logical junctors "and"/"or".<br />
<br />
By now the following operations are supported:<br />
* composite operations<br />
** "and" - The AND junctor<br />
** "or" - The OR junctor<br />
** "not" - Negation<br />
* single operations<br />
** "equals" - Equals comparison<br />
** "lt" - Less-than comparison<br />
** "gt" - Greater-than comparison<br />
<br />
Furthermore following operand types are supported for single search terms:<br />
* Column - Providing a name referring to a field/column<br />
* Constant - A constant<br />
<br />
Example of an EQUALS search term:<br><br />
<code><br />
{"operation":"equals","operands":[{"type":"column","value":"first_name"},"Jane"]}<br />
</code><br />
<br />
Example of an OR search term:<br><br />
<code><br />
{"operation":"or","operands":<br><br />
&nbsp;[<br><br />
&nbsp;&nbsp;{"operation":"equals","operands":[{"type":"column","value":"first_name"},"Jane"]},<br><br />
&nbsp;&nbsp;{"operation":"gt","operands":[{"type":"column","value":"birthday"},"1975-05-01"]}<br><br />
&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
<br />
Refer to object data tables introduced by different modules to know which field names are supported; e.g. for tasks it is [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]], and [[#DetailedTaskData | Detailed task data]].<br />
<br />
== Module "search" (alternative suggestion, still preliminary) ==<br />
<br />
The search module is an enhancement to each search request as an optional JSON object via PUT method to filter elements; e.g.<br />
<br />
<code><br />
PUT /ajax/contacts?action=all&...<br />
<br />
{"filter":<i>[search term]</i>}<br />
</code><br />
<br />
This section describes the syntax of the optional JSON object representing the search term.<br />
In general the structure of a search term is in prefix notation; meaning the operator is written before its operands:<br />
<br />
<code>[">", 5, 2]</code><br />
<br />
The available operators are:<br />
* Comparison operators ">", "<", "=", "<=", ">=", "<>"<br />
* logic operators "not", "and", "or"<br />
<br />
Comparison operators have exactly two operands. Each operand can be either a field name or a constant. A field name is an object with the member "field" specifying the field name, e.g. <code>{ field: "first_name" }</code>. The available field names depend on the searched module. Primitive JSON types are interpreted as constants. Arrays are not valid operands for comparison operators.<br />
<br />
The logic operator "not" has exactly one operand, the other logic operators can have any number of operands. Each operand must be an array representing a nested search expression.<br />
<br />
== Module "mail account" (available with v6.12) ==<br />
<br />
The mail account module is used to manage multiple mail accounts held by a user.<br />
<br />
=== Get All mail accounts ===<br />
<br />
GET <code>/ajax/account?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for mail account's are defined in [[#MailAccountData | mail account data]].<br />
<br />
Response: An array with attachment data. Each array element describes one mail account and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a mail account ===<br />
<br />
GET <code>/ajax/account?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the account to return.<br />
<br />
Response: A JSON object representing the desired mail account. See [[#MailAccountData | mail account data]].<br />
<br />
{| id="MailAccountData" cellspacing="0" border="1"<br />
|+ align="bottom" | Mail account data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 1001 || id || Number || Account ID<br />
|-<br />
| 1002 || login || String || The login.<br />
|-<br />
| 1003 || password || String || The (optional) password.<br />
|-<br />
| 1004 || mail_url || String || The mail server URL; e.g. "imap://imap.somewhere.com:143". '''URL is preferred over single fields''' (like mail_server, mail_port, etc.)<br />
|-<br />
| 1005 || transport_url || String || The transport server URL; e.g. "smtp://smtp.somewhere.com:25". '''URL is preferred over single fields''' (like transport_server, transport_port, etc.)<br />
|-<br />
| 1006 || name || String || Account's display name.<br />
|-<br />
| 1007 || primary_address || String || User's primary address in account; e.g. "someone@somewhere.com"<br />
|-<br />
| 1008 || spam_handler || String || The name of the spam handler used by account.<br />
|-<br />
| 1009 || trash || String || The name of the default trash folder.<br />
|-<br />
| 1010 || sent || String || The name of the default sent folder.<br />
|-<br />
| 1011 || drafts || String || The name of the default drafts folder.<br />
|-<br />
| 1012 || spam || String || The name of the default spam folder.<br />
|-<br />
| 1013 || confirmed_spam || String || The name of the default confirmed-spam folder.<br />
|-<br />
| 1014 || confirmed_ham || String || The name of the default confirmed-ham folder.<br />
|-<br />
| 1015 || mail_server || String || The mail server's hostname or IP address.<br />
|-<br />
| 1016 || mail_port || Number || The mail server's port.<br />
|-<br />
| 1017 || mail_protocol || String || The mail server's protocol. '''Always use basic protocol name.''' E.g. use "imap" instead of "imaps"<br />
|-<br />
| 1018 || mail_secure || Boolean || Whether to establish a secure connection to mail server (SSL, TLS).<br />
|-<br />
| 1019 || transport_server || String || The transport server's hostname or IP address.<br />
|-<br />
| 1020 || transport_port || Number || The transport server's port.<br />
|-<br />
| 1021 || transport_protocol || String || The transport server's protocol. '''Always use basic protocol name.''' E.g. use "smtp" instead of "smtps"<br />
|-<br />
| 1022 || transport_secure || Boolean || Whether to establish a secure connection to transport server (SSL, TLS).<br />
|-<br />
| 1023 || transport_login || String || The transport login. '''Please see "transport_auth" for the handling of this field.'''<br />
|-<br />
| 1024 || transport_password || String || The transport password. '''Please see "transport_auth" for the handling of this field.'''<br />
|-<br />
| 1025 || unified_inbox_enabled || Boolean || If enabled for Unified INBOX<br />
|-<br />
| 1026 || trash_fullname || String || Path to default trash folder. Preferred over "trash"<br />
|-<br />
| 1027 || sent_fullname || String || Path to default sent folder. Preferred over "sent"<br />
|-<br />
| 1028 || drafts_fullname || String || Path to default drafts folder. Preferred over "drafts"<br />
|-<br />
| 1029 || spam_fullname || String || Path to default spam folder. Preferred over "spam"<br />
|-<br />
| 1030 || confirmed_spam_fullname || String || Path to default confirmed-spam folder. Preferred over "confirmed_spam"<br />
|-<br />
| 1031 || confirmed_ham_fullname || String || Path to default confirmed-ham folder. Preferred over "confirmed_ham"<br />
|-<br />
| 1032 || pop3_refresh_rate || Number || The interval in minutes the POP3 account is refreshed<br />
|-<br />
| 1033 || pop3_expunge_on_quit || Boolean || Whether POP3 messages shall be deleted on actual POP3 account after retrieval or not<br />
|-<br />
| 1034 || pop3_delete_write_through || Boolean || If option "pop3_expunge_on_quit" is disabled, this property defines whether a delete in local INBOX also deletes affected message in actual POP3 account<br />
|-<br />
| 1035 || pop3_storage || String || The name of POP3 storage provider, default is "mailaccount"<br />
|-<br />
| 1036 || pop3_path || String || Path to POP3's virtual root folder in storage, default is name of the POP3 account beside default folders<br />
|-<br />
| 1037 || personal || String || The customizable personal part of email address<br />
|-<br />
| 1038 || reply_to || String || The customizable reply-to email address<br />
|-<br />
| 1039 || addresses || String || The comma-separated list of available E-Mail addresses including aliases. !! Only available for primary mail account !!<br />
|-<br />
| 1040 || meta || JSON data || Stores arbitrary JSON data as specified by client associated with the mail account<br />
|-<br />
| 1041 || archive || String || The name of the archive folder. Currently not functional!<br />
|-<br />
| 1042 || archive_fullname || String || The full name of the archive folder. Currently not functional!<br />
|-<br />
| 1043 || transport_auth || String || '''Available since v7.6.1''' Specifies the source for mail transport (SMTP) credentials. Possible values: "mail", "custom", and "none".<br>- "mail" signals to use the same credentials as given in associated mail store (IMAP, POP3).<br>- "custom" signals that individual credentials are supposed to be used (fields "transport_login" and "transport_password" are considered).<br>- "none" means the mail transport does not support any authentication mechanism (rare case!)<br />
|}<br />
<br />
=== Create a new mail account ===<br />
<br />
PUT <code>/ajax/account?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request: A JSON object describing the new account to create. See [[#MailAccountData | mail account data]].<br />
<br />
Response: A JSON object representing the inserted mail account. See [[#MailAccountData | mail account data]].<br />
<br />
=== Update a mail account ===<br />
<br />
PUT <code>/ajax/account?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request: A JSON object identifiying (field ID is present) and describing the account to update. See [[#MailAccountData | mail account data]].<br />
<br />
Response: A JSON object representing the updated mail account. See [[#MailAccountData | mail account data]].<br />
<br />
=== Delete a mail account ===<br />
<br />
PUT <code>/ajax/account?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An array with the ID of the mail account to delete.<br />
<br />
=== Validate a mail account (which shall be created) ===<br />
<br />
PUT <code>/ajax/account?action=validate</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>tree</code> - An optional boolean parameter which indicates whether on successful validation the folder tree shall be returned (NULL on failure) or if set to "false" or missing only a boolean is returned which indicates validation result<br />
<br />
Request: A JSON object describing the new account to validate. See [[#MailAccountData | mail account data]].<br />
<br />
Response: Dependent on optional "tree" parameter a JSON folder object or a boolean value indicating the validation result<br />
<br />
The JSON folder object corresponding to [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
Additionally a field "subfolder_array" is added which contains possible subfolders. This field is missing if a folder contains no subfolders.<br />
<br />
[[Category: OX6]]<br />
<br />
== Module Auto Configuration (since 6.22) ==<br />
<br />
=== Get Auto Configuration ===<br />
<br />
GET <code>/ajax/autoconfig?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>email</code> – Email Adress for which a mail configuration will be discovered.<br />
* <code>password</code> – Corresponding password for the mail account (optional)<br />
<br />
Response: A JSON Object containing the best available settings for an appropriate mail Server for the given email address. The fields are described in [[#MailAccountData | mail account data]]. The Data may be incomplete or even empty.<br />
<br />
== Module "user" (available with v6.14) ==<br />
<br />
The user module is used to access user information.<br />
<br />
=== Get all users ===<br />
<br />
GET <code>/ajax/user?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for users are defined in [[#CommonObjectData | Common object data]], [[#DetailedContactData | Detailed contact data]] and [[#DetailedUserData | Detailed user data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response with timestamp: An array with user data. Each array element describes one user and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedUserData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed user data<br />
! ID !! Displayed name !! Name !! Type !! Value<br />
|-<br />
| 610 || Aliases || aliases || Array || The user's aliases<br />
|-<br />
| 611 || Time zone || timezone || String || The time zone ID.<br />
|-<br />
| 612 || Locale || locale || String || The name of user's entire locale, with the language, country and variant separated by underbars. E.g. "en", "de_DE"<br />
|-<br />
| 613 || Groups || groups || Array || The IDs of user's groups<br />
|-<br />
| 614 || Contact ID || contact_id || Number || The contact ID of the user<br />
|-<br />
| 615 || Login info || login_info || String || The user's login information<br />
|-<br />
| 616 || Guest Created By || guest_created_by || Number || The ID of the user who has created this guest in case this user represents a guest user; it is 0 for regular users (preliminary, available with v7.8.0)<br />
|}<br />
<br />
=== Get a list of users ===<br />
<br />
PUT <code>/ajax/user?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for users are defined in [[#CommonObjectData | Common object data]], [[#DetailedContactData | Detailed contact data]] and [[#DetailedUserData | Detailed user data]].<br />
<br />
Request body: An array of numbers. Each number is the ID of requested user. Since v6.18.1, a <code>null</code> value in the array is interpreted as the currently logged in user.<br />
<br />
Response with timestamp: An array with user data. Each array element describes one user and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a user ===<br />
<br />
GET <code>/ajax/user?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested user. Since v6.18.1, this parameter is optional: the default is the currently logged in user.<br />
<br />
Response with timestamp: An object containing all data of the requested user. The fields of the object are listed in [[#CommonObjectData | Common object data]], [[#DetailedContactData | Detailed contact data]] and [[#DetailedUserData | Detailed user data]].<br />
<br />
=== Update a user ===<br />
<br />
PUT <code>/ajax/user?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated user.<br />
* <code>timestamp</code> – Timestamp of the updated user. If the user was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: User object as described in [[#CommonObjectData | Common object data]], [[#DetailedContactData | Detailed contact data]] and [[#DetailedUserData | Detailed user data]]. Only modified fields are present.<br />
<br />
'''Note''': "timezone" and "locale" are the only fields from [[#DetailedUserData | Detailed user data]] which are allowed to be updated.<br />
<br />
Response with timestamp: An empty object.<br />
<br />
=== Search users ===<br />
<br />
PUT <code>/ajax/user?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified. In case of use of column 609 (use count depending order for collected users with global address book) the parameter "order" ist NOT necessary and will be ignored.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Request body: An Object as described in [[#SearchUsers | Search users]].<br />
<br />
{| id="SearchUsers" cellspacing="0" border="1"<br />
|+ align="bottom" | Search users<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find users. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|-<br />
| startletter || String || Search users with the given startletter. If this field is present, the pattern is matched against the user field which is specified by the property contact_first_letter_field on the server (default: last name). Otherwise, the pattern is matched against the display name.<br />
|}<br />
<br />
Alternative request body: An Object as described in [[#SearchUsersAlternative | Search users alternative]].<br />
<br />
{| id="SearchUsersAlternative" cellspacing="0" border="1"<br />
|+ align="bottom" | Search users alternative<br />
! Name !! Type !! Value<br />
|-<br />
| last_name || String || Searches users where the last name match with the given last name.<br />
|-<br />
| first_name || String || Searches users where the first name match with the given first name.<br />
|-<br />
| display_name || String || Searches users where the display name match with the given display name.<br />
|-<br />
| orSearch || Boolean || If set to true, the fields are connected through an OR search habit.<br />
|-<br />
| emailAutoComplete || Boolean || If set to true, results are guaranteed to contain at least one email adress and the search is performed by connecting the relevant fields through an OR search habit.<br />
|}<br />
<br />
Response: An array with user data. Each array element describes one user and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get user attribute (available with v6.20) ===<br />
<br />
GET <code>/ajax/user?action=getAttribute</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – ID of the user. <br />
* <code>name</code> – The attribute name. <br />
<br />
Response without timestamp: A JSON object providing name and value of the requested attribute<br />
<pre><br />
{ "name":"somename", "value":"somevalue"}<br />
</pre><br />
<br />
=== Set user attribute (available with v6.20) ===<br />
<br />
PUT <code>/ajax/user?action=setAttribute</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – ID of the user. <br />
* <code>setIfAbsent</code> - Set to "true" to put the value only if the specified name is not already associated with a value, otherwise "false" to put value in any case<br />
<br />
Request body: A JSON object providing name and value of the attribute. If the <code>"value"</code> field id missing or NULL, the attribute is removed.<br />
<pre><br />
{ "name":"somename", "value":"somevalue"}<br />
</pre><br />
<br />
Response: The boolean value "true" if PUT was successful; otherwise "false"<br />
<br />
== Module "user/me" (available with v7.6.2) ==<br />
<br />
The user/me module is used to access formal information about current user.<br />
<br />
=== Get user information ===<br />
<br />
GET <code>/ajax/user/me</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response with timestamp: A JSON object providing information for current user<br />
<br />
<code><br />
{<br />
"data": {<br />
"context_id": 1234,<br />
"user_id": 5,<br />
"is_context_admin": false,<br />
"login_name": "user5",<br />
"display_name": "User Five"<br />
},<br />
"timestamp": 1400855683800<br />
}<br />
</code><br />
<br />
== Module "OAuth" ==<br />
<br />
The Open-Xchange server can act as an OAuth client (starting with v6.20) or be an OAuth provider itself (starting with v7.8.0). The OAuth module supports both aspects:<br />
<br />
* Manage multiple OAuth accounts for certain online services for a user. The OAuth mechanism allows the Open-Xchange application to act as behalf of this user using previously obtained access tokens granted by user. The according interface is divided into two parts: Account access and service's meta data access.<br />
* Manage granted accesses of external services that can access a users data on his behalf, called "grants".<br />
<br />
=== OAuth account access (available with v6.20) ===<br />
<br />
The OAuth service account access description.<br />
<br />
<br />
==== Get all OAuth accounts ====<br />
<br />
GET <code>/ajax/oauth/accounts?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – The <b>optional</b> service meta data identifier. If missing all accounts of all services are returned; otherwise all accounts of specified service are returned<br />
<br />
Response: An array with account data. Each array element is a JSON object describing an OAuth account as specified in [[#OAuthAccountData | OAuth account data]].<br />
<br />
==== Get an OAuth account ====<br />
<br />
GET <code>/ajax/oauth/accounts?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The account identifier.<br />
<br />
Response: A JSON object describing an OAuth account as specified in [[#OAuthAccountData | OAuth account data]].<br />
<br />
{| id="OAuthAccountData" cellspacing="0" border="1"<br />
|+ align="bottom" | OAuth account<br />
! Field !! Type !! Description<br />
|-<br />
| id || Number || The numeric identifier of the OAuth account.<br />
|-<br />
| displayName || String || The account display name<br />
|-<br />
| serviceId || String || The identifier of the associated service meta data; e.g. <code>"com.openexchange.oauth.twitter"</code><br />
|-<br />
| token || String || The token<br />
|-<br />
| secret || String || The token secret<br />
|-<br />
|}<br />
<br />
==== Delete an OAuth account ====<br />
<br />
PUT <code>/ajax/oauth/accounts?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The account identifier.<br />
<br />
Response: The boolean value "true" if successful<br />
<br />
==== Update an OAuth account ====<br />
<br />
PUT <code>/ajax/oauth/accounts?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The account identifier. May also be provided in request body's JSON OAuth account representation by <code>"id"</code> field.<br />
<br />
Request body: A JSON object providing the OAuth account fields to update. See [[#OauthAccountData | OAuth account data]]. Currently the only values which make sende being updated are <code>"displayName"</code> and the <code>"token"</code>-<code>"secret"</code>-pair.<br />
<br />
Response: The boolean value "true" if successful<br />
<br />
==== Initialize creation of an OAuth account ====<br />
<br />
GET <code>/ajax/oauth/accounts?action=init</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – The service meta data identifier; e.g. <code>"com.openexchange.oauth.twitter"</code><br />
<br />
Response: An JSON representation of the resulting interaction providing needed information to complete account creation. See [[#OauthInteractionData | OAuth interaction data]].<br />
<br />
{| id="OauthInteractionData" cellspacing="0" border="1"<br />
|+ align="bottom" | OAuth interaction<br />
! Field !! Type !! Description<br />
|-<br />
| authUrl || String || The numeric identifier of the OAuth account.<br />
|-<br />
| type || String || The interaction type name; <code>"outOfBand"</code> or <code>"callback"</code><br />
|-<br />
| token || String || The token<br />
|-<br />
| uuid || String || The UUID for this OAuth interaction<br />
|-<br />
|}<br />
<br />
==== Create an OAuth account ====<br />
<br />
Note: This action is typically called by provided call-back URL and is ony intended for manual invocation if "outOfBand" interaction is returned by preceeding <code>/ajax/oauth/account?action=init</code> step.<br />
<br />
PUT <code>/ajax/oauth/accounts?action=create</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module<br />
* <code>oauth_token</code> – The request token from preceeding OAuth interaction<br />
* <code>uuid</code> – The UUID of the preceeding OAuth interaction<br />
* <code>oauth_verfifier</code> – The verifier string which confirms that user granted access<br />
* <code>displayName</code> – The display name for the new account<br />
<br />
Response: A JSON object describing the newly created OAuth account as specified in [[#OAuthAccountData | OAuth account data]].<br />
<br />
=== OAuth service meta data access (available with v6.20) ===<br />
<br />
The OAuth service meta data access description.<br />
<br />
<br />
==== Get all OAuth services' meta data ====<br />
<br />
GET <code>/ajax/oauth/services?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: An array with service data. Each array element is a JSON object describing an OAuth service's meta data as specified in [[#OAuthServiceMetaData | OAuth service meta data]].<br />
<br />
==== Get an OAuth service's meta data ====<br />
<br />
GET <code>/ajax/oauth/services?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The service's identifier.<br />
<br />
Response: A JSON object describing an OAuth service's meta data as specified in [[#OAuthServiceMetaData | OAuth service meta data]].<br />
<br />
{| id="OAuthServiceMetaData" cellspacing="0" border="1"<br />
|+ align="bottom" | OAuth service meta data<br />
! Field !! Type !! Description<br />
|-<br />
| id || Number || The numeric identifier of the OAuth account.<br />
|-<br />
| displayName || String || The account display name<br />
|-<br />
|}<br />
<br />
=== Manage OAuth grants (available with v7.8.0) ===<br />
<br />
==== Get all grants ====<br />
<br />
GET <code>/ajax/oauth/grants?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: A JSON array containing one object for every granted access as specified in [[#OAuthGrants | OAuth grants]].<br />
<br />
{| id="OAuthGrants" cellspacing="0" border="1"<br />
|+ align="bottom" | OAuth grants<br />
! Field !! Type !! Description<br />
|-<br />
| client || Object || A JSON object describing the external service as in [[#OAuthClient | OAuth client]].<br />
|-<br />
| scopes || Object || A JSON object with mappings from scope tokens to translated, human-readable descriptions for every scope that was granted to the external service. Example: {"read_contacts":"See all your contacts."}<br />
|-<br />
| date || Time || The time when the access was granted.<br />
|-<br />
|}<br />
<br />
{| id="OAuthClient" cellspacing="0" border="1"<br />
|+ align="bottom" | OAuth client<br />
! Field !! Type !! Description<br />
|-<br />
| id || String || The clients ID.<br />
|-<br />
| name || String || The clients/services name.<br />
|-<br />
| description || String || A description of the client.<br />
|-<br />
| website || String || A URL to the clients website.<br />
|-<br />
| icon || String || A URL or path to obtain the clients icon via the "image" module.<br />
|-<br />
|}<br />
<br />
==== Revoke access ====<br />
<br />
GET <code>oauth/grants?action=revoke</code><br />
<br />
Parameters:<br />
* <code>client</code> - The ID of the client whose access shall be revoked.<br />
<br />
Response: Nothing.<br />
<br />
== Module "JSlob" (available with v6.22) ==<br />
<br />
The JSlob module is used to store&retrieve arbitrary JSON-structured configuration for a single user.<br />
<br />
<br />
=== Get all JSLobs ===<br />
<br />
GET <code>/ajax/jslob?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
<br />
<br />
Response: An array with JSON configurations. Each array element is a JSON object representing a certain configuration consisting if a "id" and "jslob" field. See [[#JSlobData | JSlob data ]]<br />
<br />
{| id="JSlobData" cellspacing="0" border="1"<br />
|+ align="bottom" | JSlob data<br />
! Field !! Type !! Description<br />
|-<br />
| id || String or Number || The identifier of the JSlob.<br />
|-<br />
| jslob || JSON object || The JSON configuration.<br />
|-<br />
|}<br />
<br />
=== List denoted JSLobs ===<br />
<br />
PUT <code>/ajax/jslob?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
<br />
<br />
Request body: A JSON array of JSlob identifiers; e.g. <code>[ "1", "2", … ]</code><br />
<br />
Response: An array with JSON configurations. Each array element is a JSON object representing a certain configuration consisting if a "id" and "jslob" field. See [[#JSlobData | JSlob data ]]<br />
<br />
=== Delete a JSlob ===<br />
<br />
PUT <code>/ajax/jslob?action=set</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
* <code>id</code> – The JSlob identifier.<br />
<br />
<br />
Request body: An empty request body<br />
<br />
Response: Nothing<br />
<br />
=== Store a JSlob ===<br />
<br />
PUT <code>/ajax/jslob?action=set</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
* <code>id</code> – The identifier for the new JSlob to create<br />
<br />
<br />
Request body: A JSON object containing the "path" and "value" of the JSON configuration to store. If "path" is missing the current configuration<br />
is merged with given JSON object.<br />
<br />
Response: Nothing<br />
<br />
=== Update a single value inside a JSlob ===<br />
<br />
PUT <code>/ajax/jslob?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
* <code>id</code> – The identifier for the new JSlob to create<br />
<br />
<br />
Request body: The new value to store inside specified JSlob<br />
<br />
Response: A JSlob representation according to [[#JSlobData | JSlob data ]]<br />
<br />
=== REST-like access to JSlob module ===<br />
<br />
to be done...<br />
<br />
<br />
== Module "freebusy" (available with v6.22.1) ==<br />
<br />
Provides access to free/busy information.<br />
<br />
<br />
=== Get free/busy information ===<br />
<br />
GET <code>/ajax/freebusy?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>participant</code> – The participant to get the free/busy data for. May be either an internal user-, group- or resource-ID, or an e-mail address for external participants.<br />
* <code>from</code> – The lower (inclusive) limit of the requested time-range.<br />
* <code>until</code> – The upper (exclusive) limit of the requested time-range.<br />
* <code>merged</code> (optional) – True or False. Whether to pre-process the free/busy data on the server or not. This includes sorting as well as merging overlapping free/busy intervals.<br />
<br />
Response: An array of free/busy intervals as described in [[#FreeBusyInterval | Free/Busy interval]]<br />
<br />
{| id="FreeBusyInterval" cellspacing="0" border="1"<br />
|+ align="bottom" | Free/Busy interval<br />
! Name !! Type !! Value<br />
|-<br />
| start_date || Time || Start time of the interval.<br />
|-<br />
| end_date || Time || End time of the interval.<br />
|-<br />
| shown_as || Number || The busy status of this interval, one of:<br />
{| cellspacing="0" border="1"<br />
| 1 || unknown<br />
|-<br />
| 1 || reserved<br />
|-<br />
| 2 || temporary<br />
|-<br />
| 3 || absent<br />
|-<br />
| 4 || free<br />
|}<br />
|-<br />
| id || String || Object ID of the corresponding appointment if available.<br />
|-<br />
| folder_id || String || Folder ID of the corresponding appointment if available.<br />
|-<br />
| title || String || Title of the corresponding appointment if available.<br />
|-<br />
| location || String || Location of the corresponding appointment if available.<br />
|-<br />
| full_time || Boolean || True if the corresponding appointment is a whole day appointment, not present otherwise.<br />
|}<br />
<br />
<br />
=== Get a list of free/busy information ===<br />
<br />
PUT <code>/ajax/freebusy?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>from</code> – The lower (inclusive) limit of the requested time-range.<br />
* <code>until</code> – The upper (exclusive) limit of the requested time-range.<br />
* <code>merged</code> (optional) – True or False. Whether to pre-process the free/busy data on the server or not. This includes sorting as well as merging overlapping free/busy intervals.<br />
<br />
Request body: An array of participants to get the free/busy data for. Each participant may be either an internal user-, group- or resource-ID, or an e-mail address for external participants.<br />
<br />
Response: The free/busy data for all requested participants inside a JSON object with the participants as keys. Besides a combined data element for a requested group, all group members are resolved and listed seperately in the result. If the 'merged' view was requested, an additional data element named 'merged' representing a combined view for all requested participants is added to the results implicitly.<br />
<br />
<br />
== Messaging Services ==<br />
<br />
Messaging Services represent a messaging backend. The messaging services add a new folder module "messaging". <br />
<br />
A *Messaging Service* Object has the following structure:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Messaging Service<br />
! Field !! Type !! Description<br />
|-<br />
| id || String || Identifies a messagingService. Usually a String in reverse domain name notation. Example: "com.openexchange.messaging.twitter"<br />
|-<br />
| displayName || String || Human readable display name of the service. Example: "Twitter" <br />
|-<br />
| formDescription || Array || A description for dynamic form fields. Same as in PubSub <br />
|-<br />
| messagingActions || Array || An array of Strings a dynamic set of actions that are possible with messages of this service. Described in detail later on. <br />
|-<br />
|}<br />
<br />
The available JSON calls are:<br />
<br />
GET /ajax/messaging/service?action=all<br />
<br />
* session - A session ID previously obtained from the login module. <br />
<br />
Response: A standard response object containing an array of messaging service objects. <br />
<br />
<br />
GET /ajax/messaging/service?action=get<br />
<br />
* session - A session ID previously obtained from the login module. <br />
* id - The ID of the messaging service to load<br />
<br />
Response: A standard response object containing a messaging service object.<br />
<br />
== Messaging Accounts ==<br />
<br />
A messaging account represents the concrete configuration of an account of a given messaging service.<br />
A *messaging account* has the following structure:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Messaging Account<br />
! Field !! Type !! Description<br />
|-<br />
| id || Number || Identifies a given messaging account. This is not writeable and is generated by the server <br />
|-<br />
| messagingService || String || The messaging service id of the messaging service this account belongs to <br />
|-<br />
| displayName || String || User chosen String to identify a given account. Will also be translated into the folder name of the folder representing the accounts content <br />
|-<br />
| configuration || Object || Configuration data according to the formDescription of the relevant messagingService <br />
|-<br />
|}<br />
<br />
The available JSON calls are:<br />
<br />
PUT /ajax/messaging/account?action=new<br />
<br />
* session - A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON Object describing the account to be created.<br />
Response: A response object containing the new account id as its data.<br />
<br />
<br />
PUT /ajax/messaging/account?action=update<br />
<br />
* session - A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON Object describing the update to the account. Note that the "id" and "messagingService" must always be set.<br />
Response: A response object containing the number 1 as its data on success.<br />
<br />
GET /ajax/messaging/account?action=get<br />
<br />
* session - A session ID previously obtained from the login module.<br />
* messagingService - The messaging service id that the account belongs to<br />
* id - An account ID to load<br />
<br />
Response: A response object containing the JSON Object representing the loaded account as its data.<br />
<br />
GET /ajax/messaging/account?action=delete<br />
<br />
* session - A session ID previously obtained from the login module.<br />
* messagingService - The messaging service id that the account belongs to<br />
* id - An account ID to delete<br />
<br />
Response: A response object containing 1 as its data on success.<br />
<br />
GET /ajax/messaging/account?action=all<br />
<br />
* session - A session ID previously obtained from the login module<br />
* messagingService - (optional) list only those accounts that belong to the given messagingService.<br />
<br />
Response: A response object containing a JSON array of account objects in its data section.<br />
<br />
<br />
== Messaging Messages ==<br />
<br />
A Messaging Message represents a single message. It consists of some metadata, headers and a content. The content attribute varies by the content-type header. <br />
If the content type is text/* it is a string, if it is a multipart/* it is an array of objects, each representing a part of the multipart. If it is anything else<br />
it is considered binary and is a Base64 encoded string (ToDo : This is not smart enough yet. I suppose we'll have to include encoding options for binaries much like in our EAVJSONProposal).<br />
<br />
The folder id of a message follows a predefined format:<br />
<br />
<pre><br />
[messagingService]://[accountId]/[path]<br />
</pre><br />
<br />
for an imaginary example consider: "com.openexchange.messaging.twitter://535/defaultTimeline/directMessages"<br />
<br />
The structure of a Messaging Message is as follows:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Messaging Message<br />
! Field !! Type !! Description<br />
|-<br />
|id ||String || The id of this message. Only unique in the given folder. <br />
|-<br />
|folder ||String || The folder id. <br />
|-<br />
|threadLevel ||Number || The nesting level of this message according to the conversation it's belonged to. May not be set. <br />
|-<br />
|flags ||Number || Bitmask showing the state of this message. The same as in the module "mail". <br />
|-<br />
|receivedDate ||Time || The time this message was received. <br />
|-<br />
|colorLabel ||Number || An arbitrary number marking this message in a certain color. The same as the colorLabel common to all groupware objects (see HTTP API)<br />
|-<br />
|user ||Array || An array of strings. Represents user flags. <br />
|-<br />
|size ||Number || The binary size of this message in bytes. <br />
|-<br />
|picture || String || A string depicting the URL to a picture for this message <br />
|-<br />
|url || String || A string that contains a link to the messages origin. Currently used in RSS messages.<br />
|-<br />
|headers ||JSONObject || A JSON Object of header data. Usually the value is either a String or an Array (if the headers has more than one value). Certain headers are rendered as more complex structures, see the section "Complex Headers". <br />
|-<br />
|content ||String or Array || See introductory note for Messaging Messages. <br />
|-<br />
|}<br />
<br />
The structure of a Multipart Part (an element of the content array in a multipart/* message) is a s follows:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Multipart Element<br />
! Field !! Type !! Description<br />
|-<br />
|sectionId || String || The sectionId of this part.<br />
|-<br />
|headers || JSONObject || Same as above. <br />
|-<br />
|content || String or Array || Same as above. <br />
|-<br />
|}<br />
<br />
Some *Complex Headers* have a structure differing from simple key/value(s) pairs. These are:<br />
<br />
=== Content-Type ===<br />
<br />
The Content-Type header is represented as a JSON Object with the following structure:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Content Type Header<br />
! Field !! Type !! Description<br />
|-<br />
| type || String || The type string (eg. text/plain). This governs the rendering of the content of a message. <br />
|-<br />
| params || Object || An Object with the keys "charset", containing the charset of this message and "name" pointing to the filename this part or message should have. <br />
|-<br />
|}<br />
<br />
When setting the content-type header in a messaging messages generated on the client the header may also be sent in it's short form. The short form is the type followed by a semi-colon separated list of key=value pairs<br />
of the params. For example: "text/plain;charset=utf-8;name=something.txt".<br />
<br />
=== Address Headers ===<br />
<br />
Address headers ( From, To,Cc,Bcc,Reply-To,Resent-Reply-To,Disposition-Notification-To,Resent-To,Sender,Resent-Sender,Resent-To,Resent-Cc,Resent-Bcc ) are formatted as an array of objects, or in case of "From" as a single object, with the attributes *address* and *personal*:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Address Headers<br />
! Field !! Type !! Description<br />
|-<br />
| address || String || The technical part of the address<br />
|-<br />
| personal || String || A displayable description of the addressee. May be unset.<br />
|-<br />
|}<br />
<br />
When setting an address header the header may also be sent by clients in the short form <code>"personal &lt;address&gt;"</code>, for example <code>"Clark Kent &lt;clark.kent@dailyplanet.com&gt;"</code>. <br />
<br />
=== List renderings of Messaging Messages ===<br />
<br />
Actions returning lists of messages usually return only a selection of attributes of a message driven by a "columns" parameter. The columns that are addressable point either to attributes of the top-level message or its headers. <br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Header Equivalence<br />
! Column !! Refers To<br />
|-<br />
| *column* | *refers to* <br />
|-<br />
| id || The id attribute <br />
|-<br />
| folderId || The folder attribute <br />
|-<br />
| contentType || The "Content-Type" header <br />
|-<br />
| from || The "From" header <br />
|-<br />
| to || The "To" header <br />
|-<br />
| cc || The "Cc" header <br />
|-<br />
| bcc || The "Bcc" header <br />
|-<br />
| subject || The "Subject" header <br />
|-<br />
| size || The size attribute <br />
|-<br />
| sentDate || The "Date" header <br />
|-<br />
| receivedDate || The receivedDate attribute <br />
|-<br />
| flags || The flags attribute <br />
|-<br />
| threadLevel || The threadLevel attribute <br />
|-<br />
| dispositionNotificationTo || The "Disposition-Notification-To" header. <br />
|-<br />
| priority || The "X-Priority" header <br />
|-<br />
| colorLabel || The colorLabel attribute <br />
|-<br />
| url || The url attribute <br />
|-<br />
| body || The content attribute <br />
|-<br />
| headers || The headers attribute <br />
|-<br />
|}<br />
<br />
=== JSON calls ===<br />
<br />
GET /ajax/messaging/message?action=get<br />
<br />
* session - A session ID previously obtained from the login module<br />
* id - The ID of the message to load<br />
* peek - (optional) if set to "true" the read/unread state of the message will not change. Defaults to false.<br />
* folder - The folder id<br />
<br />
Response: An Object representing the loaded message.<br />
<br />
PUT /ajax/messaging/message?action=send<br />
<br />
* session - A session ID previously obtained from the login module<br />
* recipients - (optional) If set the message is sent to the given list of recipients, otherwise this defaults to the "To" header of the message.<br />
<br />
Request Body: The Request Body should contain the JSON Object representing the message to be sent.<br />
Response: "1" as the data of a regular response on success.<br />
<br />
GET or PUT /ajax/messaging/message?action=perform<br />
<br />
* session - A session ID previously obtained from the login module<br />
* action - The messaging action to invoke<br />
* id - The id of the message the action should be invoked on. Only used on actions of type "storage".<br />
* folder - The folder id.<br />
<br />
Request Body: On actions of type "message" the body should contain the JSON representation of the message the action should be applied to.<br />
Response: Either 1 if no further user interaction is needed or a messaging message that, after having the user modify it has to be supplied back to the follower action of this action.<br />
<br />
Thus, to invoke a messaging action of type "storage" the folder and id are needed. Messaging actions of type "message" need a folder and message in the body. <br />
Messaging actions of type "none" need a messaging message and account. <br />
<br />
==== List style requests ====<br />
<br />
GET /ajax/messaging/message?action=all<br />
<br />
* session - A session ID previously obtained from the login module<br />
* columns - A comma-separated list of column names.<br />
* sort - (optional) A column to sort by.<br />
* order - (optional) The order direction. "asc" for ascending or "desc" for descending. Defaults to "asc"<br />
* folder - The folder id.<br />
<br />
Response: An array of arrays with the sub arrays containing the values of the fields asked for by the the columns parameter.<br />
<br />
<br />
PUT /ajax/messaging/messages?action=list<br />
<br />
* session - A session ID previously obtained from the login module<br />
* columns - A comma-separated list of column names.<br />
<br />
Request Body: An array of arrays with the folder and id as elements each identifying a message. <br />
<br />
Response: An array of arrays with the sub arrays containing the values of the fields asked for by the columns parameter.<br />
<br />
== Snippet module (available with v7.0.0/v6.22.0) ==<br />
<br />
=== Gets a certain snippet by identifier ===<br />
<br />
GET /ajax/snippet?action=get<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
<br />
Response:<br />
The snippet's JSON representation; e.g.<br />
<br />
{<br />
"id": "1",<br />
"type": "signature",<br />
"props": {"x-custom": "any value"},<br />
"module": "mail",<br />
"displayname": "My signature",<br />
"misc": {"foo": "bar"},<br />
"createdby": 17,<br />
"content": "-- \\nMy name and position here",<br />
"accountid": 0,<br />
"shared": false,<br />
"files":<br />
[<br />
{<br />
"mimetype": "image/png; name=pic.png",<br />
"filename": "pic.png",<br />
"id": "46f49f8a-40d5-4f29-8bc9-728f3420864c",<br />
"size": 6074<br />
}<br />
]<br />
}<br />
<br />
=== Gets all snippets associated with the current user and context ===<br />
<br />
GET /ajax/snippet?action=all<br />
<br />
* session - The session identifier<br />
* type - Optional CSV of types to filter by; e.g. "signature"<br />
<br />
Response:<br />
A JSON array of snippets' JSON representations<br />
<br />
<br />
<br />
=== Gets certain snippets by identifiers ===<br />
<br />
GET /ajax/snippet?action=list<br />
<br />
* session - The session identifier<br />
<br />
Request body:<br />
A JSON array of snippet identifiers<br />
<br />
Response:<br />
A JSON array of snippets' JSON representations<br />
<br />
<br />
<br />
=== Gets a certain snippet's attachment by identifier ===<br />
<br />
GET /ajax/snippet?action=getattachment<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
* attachmentid - The attachment identifier<br />
<br />
Response:<br />
The attachment's raw data<br />
<br />
<br />
<br />
=== Creates a new snippet ===<br />
<br />
PUT /ajax/snippet?action=new<br />
<br />
* session - The session identifier<br />
<br />
Request body:<br />
A JSON representation of the snippet.<br />
Excluding its attachments (see attach/detach actions)<br />
<br />
Response:<br />
The created snippet's identifier<br />
<br />
<br />
<br />
=== Updates a certain snippet by identifier ===<br />
<br />
PUT /ajax/snippet?action=update<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
<br />
Request body:<br />
A JSON representation of the snippet providing the fields that should be changed.<br />
Excluding its attachments (see attach/detach actions)<br />
<br />
Response:<br />
The updated snippet's JSON representation<br />
<br />
<br />
<br />
=== Deletes a certain snippet by identifier ===<br />
<br />
PUT /ajax/snippet?action=delete<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier (otherwise provide one or more identifiers through request body's JSON array)<br />
<br />
Request body:<br />
A JSON array of identifiers denoting the snippets to delete<br />
<br />
Response:<br />
An empty/dummy result (don't care)<br />
<br />
<br />
<br />
=== Attaches one or more files to an existing snippet ===<br />
<br />
POST /ajax/snippet?action=attach<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
<br />
Request body:<br />
Multipart form data providing the upload files to attach to the snippet.<br />
<br />
Response:<br />
The updated snippet's identifier<br />
<br />
<br />
<br />
=== Detaches open or more files from an existing snippet ===<br />
<br />
PUT /ajax/snippet?action=detach<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
<br />
Request body:<br />
A JSON array providing the identifiers of the attachments to remove from snippet<br />
<br />
Response:<br />
The updated snippet's identifier<br />
<br />
== Picture Halo (since 7.4.1) ==<br />
<br />
GET /appsuite/api/halo/contact/picture<br />
* session - (optional) falls back to the public session cookie<br />
* internal_userid - (optional) The internal user id of a user whose picture you want to load<br />
* userid - (optional) an alias for internal_userid<br />
* user_id - (optional) an alias for internal_userid<br />
* id - (optional) a contact id<br />
* email - (optional) an email to search for. Will pick global address book matches before regular matches. After that picks the most recently changed contact<br />
* email1 - (optional) an alias for email<br />
* email2 - (optional) another email address to use to find matches<br />
* email3 - (optional) and yet another email address to use to find matches<br />
<br />
''At least one of the optional search parameters should be set. All parameters are connected by OR during the search. More specific parameters like user_id or id are prioritized in case of multiple matches.''<br />
<br />
Response:<br />
The picture with proper eTag and caching headers set, or an HTTP Status 404 response, if no picture could be found.<br />
<br />
<br />
== Module "capabilities" (available with v7.4.2) ==<br />
<br />
Provides access to capabilities, i.e. modules or features that are available on the backend and the user has access to.<br />
<br />
=== Get a capability ===<br />
<br />
GET <code>/ajax/capabilities?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The identifier of the capability<br />
<br />
Response: The requested capability as described in [[#Capability| Capability]], if available, otherwise an empty result<br />
<br />
{| id="Capability" cellspacing="0" border="1"<br />
|+ align="bottom" | Capability<br />
! Name !! Type !! Value<br />
|-<br />
| id || String || The identifier of the capability<br />
|-<br />
| attributes || Object || A JSON object holding optional properties of the capability <br />
|}<br />
<br />
=== Get all capabilities ===<br />
<br />
GET <code>/ajax/capabilities?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: An array of capability objects as described in [[#Capability| Capability]].<br />
<br />
<br />
== Module "jump" (available with v7.6.0) ==<br />
<br />
The jump module is used to pass an acquired identity token for an authenticated user from one system to another for a single sign-on.<br />
<br />
=== Acquire an identity token ===<br />
<br />
GET <code>/ajax/jump?action=identityToken</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>system</code> – The identifier for the external service/system<br />
<br />
Response: The acquired identity token wrapped by a simple JSON object as described in [[#Jump| Jump]]<br />
<br />
{| id="Jump" cellspacing="0" border="1"<br />
|+ align="bottom" | Jump<br />
! Name !! Type !! Value<br />
|-<br />
| token || String || The identifier of the token<br />
|}<br />
<br />
== Module "find" (preliminary, available with v7.6.1) ==<br />
The Find API consists of calls for performing searches within the modules mail, contacts, calendar, tasks and drive. It was designed to provide an iterative approach where the search criteria can be refined step-wise until the desired items are found. The starting point is always an "autocomplete" request, that suggests possible search filters based on a users input. Those filters are grouped into categories, called "facets". A facet may provide one or more "values" with every value being a possible filter. A client is meant to remember every value that was selected by a user and include it within the following "autocomplete" and "query" requests, while "query" performs the actual search and returns the found items.<br />
<br />
Every request is bound to a module that must be specified via the URL-Parameter "module". Possible modules are<br />
* mail<br />
* contacts<br />
* calendar<br />
* tasks<br />
* drive<br />
<br />
=== General assumptions ===<br />
Some of the objects returned by the server contain former user input. A client must never interpret strings as HTML but always as plain text to be not vulnerable for CSS attacks!<br />
<br />
=== Calls ===<br />
The find API provides two dedicated calls under the servlet path <code>find</code>:<br />
* action=autocomplete<br />
* action=query<br />
<br />
=== Facets ===<br />
The style of a facet is responsible for how the according object is structured, how it is handled on the server-side and how the client has to handle it.<br />
We distinguish three styles of facets:<br />
* simple<br />
* default<br />
* exclusive<br />
<br />
Every facet value contains an embedded "filter" object. The filter must not be changed by the client, it has to be seen as a black-box. Instead the filters<br />
of selected facet values have to be copied and sent to the server with the subsequent requests.<br />
<br />
==== Simple Facets ====<br />
A simple facet is a special facet that has exactly one value. The facets<br />
type and its value are strictly coupled, in a way that a display name for both,<br />
facet and value would be redundant. A simple facet generally denotes a logical field like<br />
'phone number'. Internally this logical field can map to several internal fields<br />
(e.g. 'phone_private', 'phone_mobile', 'phone_business'). In clients the facet as<br />
a whole can be displayed as a single item. Example: "Search for 'term' in field 'phone<br />
number'".<br />
<br />
<br />
{| id="Facet Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Facet Structure<br />
! Field !! Type !! Description<br />
|-<br />
| style || "simple" || Denotes that this is a facet of style simple<br />
|-<br />
| id || <string> || The id of this facet. Unique within an autocomplete response. Can be used to distinguish and filter certain facets.<br />
|-<br />
| name || <string> || A displayable (and localized) name for this facet. If absent, an "item" attribute is present.<br />
|-<br />
| item (optional) || <object> || A more complex object to display this facet. Attributes are "name", "detail" (optional) and "image_url" (optional).<br />
|-<br />
| filter || <object> || The filter to refine the search.<br />
|-<br />
| flags || <array> || An array of flags, represented as strings.<br />
|}<br />
<br />
Example:<br />
<pre><br />
{<br />
"id":"global",<br />
"style":"simple",<br />
"name":"test",<br />
"filter":{},<br />
"flags":[]<br />
}<br />
</pre><br />
<br />
==== Default Facets ====<br />
A default facet contains multiple values and may be present<br />
multiple times in search requests to filter results by a combination of different<br />
values (e.g. "mails with 'foo' and 'bar' in subject").<br />
<br />
Facet values may be one- or two-dimensional. A one-dimensional value can be displayed as is and contains an according filter object.<br />
A two-dimensional value contains an array "options" with every option defining different semantics of how the value is used to filter the search results.<br />
<br />
{| id="Default Facet Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Facet Structure<br />
! Field !! Type !! Description<br />
|-<br />
| style || "default" || Denotes that this is a facet of style default<br />
|-<br />
| id || <string> || The id of this facet. Unique within an autocomplete response. Can be used to distinguish and filter certain facets.<br />
|-<br />
| name || <string> || A displayable (and localized) name for this facet. If absent, an "item" attribute is present.<br />
|-<br />
| item (optional) || <object> || A more complex object to display this facet. Attributes are "name", "detail" (optional) and "image_url" (optional).<br />
|-<br />
| values || <array> || An array of facet values.<br />
|-<br />
| flags || <array> || An array of flags, represented as strings.<br />
|}<br />
<br />
{| id="Default Facet Value Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Value Structure<br />
! Field !! Type !! Description<br />
|-<br />
| id || <string> || The values id. Unique within one facet.<br />
|-<br />
| name || <string> || A displayable (and localized) name for this value. May be superseded with an "item" attribute. Absent if the value contains options.<br />
|-<br />
| item (optional) || <object> || A more complex object to display this value. Attributes are "name", "detail" (optional) and "image_url" (optional). Absent if the value contains options.<br />
|-<br />
| filter || <object> || The filter to refine the search. Absent if the value contains options.<br />
|-<br />
| options (optional) || <array> || An array of options.<br />
|}<br />
<br />
{| id="Default Facet Option Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Option Structure<br />
! Field !! Type !! Description<br />
|-<br />
| id || <string> || The options id. Unique within a set of options.<br />
|-<br />
| name || <string> || The displayable (and localized) name for this option.<br />
|-<br />
| filter || <object> || The filter to refine the search.<br />
|-<br />
|}<br />
<br />
Example:<br />
<pre><br />
{<br />
"id":"contacts",<br />
"style":"default",<br />
"name":"People",<br />
"values":[<br />
{<br />
"id":"contact/424242669/525793",<br />
"item":{<br />
"name":"Test Usere2123",<br />
"detail":"testuse1212r@example.com"<br />
},<br />
"options":[<br />
{<br />
"id":"from",<br />
"name":"From",<br />
"filter":{}<br />
},<br />
{<br />
"id":"to",<br />
"name":"To",<br />
"filter":{}<br />
},<br />
{<br />
"id":"all",<br />
"name":"From/To",<br />
"filter":{}<br />
}<br />
]<br />
}<br />
],<br />
"flags":[]<br />
}<br />
</pre><br />
<br />
==== Exclusive Facets ====<br />
An exclusive facet is a facet where the contained values are<br />
mutually exclusive. That means that the facet must only be present once<br />
in an autocomplete or query request.<br />
<br />
Facet values may be one- or two-dimensional. A one-dimensional value can be displayed as is and contains an according filter object.<br />
A two-dimensional value contains an array "options" with every option defining different semantics of how the value is used to filter the search results. <br />
<br />
{| id="Exclusive Facet Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Facet Structure<br />
! Field !! Type !! Description<br />
|-<br />
| style || "exclusive" || Denotes that this is a facet of style exclusive<br />
|-<br />
| id || <string> || The id of this facet. Unique within an autocomplete response. Can be used to distinguish and filter certain facets.<br />
|-<br />
| name || <string> || A displayable (and localized) name for this facet. If absent, an "item" attribute is present.<br />
|-<br />
| item (optional) || <object> || A more complex object to display this facet. Attributes are "name", "detail" (optional) and "image_url" (optional).<br />
|-<br />
| options || <array> || An array of facet values.<br />
|-<br />
| flags || <array> || An array of flags, represented as strings.<br />
|}<br />
<br />
{| id="Exclusive Facet Value Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Value Structure<br />
! Field !! Type !! Description<br />
|-<br />
| id || <string> || The values id. Unique within one facet.<br />
|-<br />
| name || <string> || A displayable (and localized) name for this value. May be superseded with an "item" attribute. Absent if the value contains options.<br />
|-<br />
| item (optional) || <object> || A more complex object to display this value. Attributes are "name", "detail" (optional) and "image_url" (optional). Absent if the value contains options.<br />
|-<br />
| filter || <object> || The filter to refine the search. Absent if the value contains options.<br />
|-<br />
| options (optional) || <array> || An array of options.<br />
|}<br />
<br />
{| id="Exclusive Facet Option Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Option Structure<br />
! Field !! Type !! Description<br />
|-<br />
| id || <string> || The options id. Unique within a set of options.<br />
|-<br />
| name || <string> || The displayable (and localized) name for this option.<br />
|-<br />
| filter || <object> || The filter to refine the search.<br />
|-<br />
|}<br />
<br />
Example:<br />
<pre><br />
{<br />
"id":"time",<br />
"style":"exclusive",<br />
"name":"Time",<br />
"options":[<br />
{<br />
"id":"last_week",<br />
"name":"last week",<br />
"filter":{}<br />
},<br />
{<br />
"id":"last_month",<br />
"name":"last month",<br />
"filter":{}<br />
},<br />
{<br />
"id":"last_year",<br />
"name":"last year",<br />
"filter":{}<br />
}<br />
],<br />
"flags":[]<br />
}<br />
</pre><br />
<br />
<br />
==== Active Facets ====<br />
Every value that has been selected by a user must be remembered and provided with every subsequent request. The representation of a facet within a request body differs from the one within an autocomplete response. We call those "active facets". Their representation is independent from their style.<br />
<br />
{| id="Active Facet Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Active Facet Structure<br />
! Field !! Type !! Description<br />
|-<br />
| facet || <string> || The id of the according facet.<br />
|-<br />
| value || <string> || The id of the according value. Must always be copied from the value object, not from a possibly according option (in the two-dimensional case).<br />
|-<br />
| filter || <object> || The filter object, copied from the value or option.<br />
|}<br />
<br />
<br />
=== Configuration ===<br />
According to the users configuration, some restrictions may apply that have to be heeded by clients. Those restrictions can be retrieved via the "config" or the "jslob" modules. The following restrictions may apply:<br />
<br />
* A user might have limited access to modules and therefore the Find API may only serve requests for a subset of all possible modules. The configuration object may contain an object with key "modules". Its value is an array containing all module identifiers that the user is allowed to use.<br />
<br />
* Some facets can be mandatory, i.e. they must be pre-defined by the client and provided with every request. Whether a facet is mandatory or not is decided on a per-module basis. The configuration object may contain an object with key "mandatory". Every facet that may be mandatory is specified via its id in that object (e.g. mandatory.folder). The value of such a key is either an array containing all module identifiers, where the facet is mandatory or null, if it is not manadatory in any module.<br />
<br />
* Due to performance reasons the service provider can enforce a minimium number of characters that have to be provided before an autocomplete request may be issued. That property is called "minimumQueryLength" and its value is an integer that specifies the minimum number of characters. If a client does not heed this property, the server will respond with an error if the provided user input is too short.<br />
<br />
==== Config Example ====<br />
<pre><br />
GET http://localhost/appsuite/api/config/search?session={{session}}<br />
Response:<br />
{<br />
"data": {<br />
"mandatory": {<br />
"folder": [<br />
"mail"<br />
]<br />
},<br />
"modules": [<br />
"mail",<br />
"contacts",<br />
"calendar",<br />
"tasks",<br />
"drive"<br />
]<br />
}<br />
}<br />
<br />
GET http://localhost/appsuite/api/config/minimumSearchCharacters?session={{session}}<br />
Response:<br />
{<br />
"data": 0<br />
}<br />
</pre><br />
<br />
==== JSLob Example ====<br />
<pre><br />
GET http://localhost/appsuite/api/jslob?action=get&id=io.ox/core&session={{session}}<br />
Response:<br />
{<br />
"data": {<br />
"id": "io.ox/core",<br />
"tree": {<br />
"search": {<br />
"modules": [<br />
"mail",<br />
"contacts",<br />
"calendar",<br />
"tasks",<br />
"drive"<br />
],<br />
"mandatory": {<br />
"folder": [<br />
"mail"<br />
]<br />
},<br />
"minimumQueryLength": 0<br />
}<br />
}<br />
}<br />
}<br />
</pre><br />
<br />
=== autocomplete ===<br />
Mandatory URL parameters:<br />
* action=autocomplete<br />
* module=<module-name><br />
* session=<session-id><br />
<br />
Optional URL parameters:<br />
* limit=<int> - The maximum number of values returned per facet<br />
<br />
Request body: A JSON object containing the users input (specified as "prefix"), already selected facets and possible options.<br />
<br />
<br />
==== Example ====<br />
<pre><br />
PUT http://localhost/appsuite/api/find?action=autocomplete&module=mail&limit=3&session={{session}}<br />
{<br />
"prefix":"test", <br />
"facets":[<br />
{<br />
"facet":"folder",<br />
"value":"default0/INBOX"<br />
}<br />
],<br />
"options":{<br />
"timezone":"UTC",<br />
"admin":false<br />
}<br />
}<br />
<br />
Response:<br />
{<br />
"data":{<br />
"facets":[<br />
{<br />
"id":"global",<br />
"style":"simple",<br />
"name":"test",<br />
"filter":{},<br />
"flags":[]<br />
}, <br />
{<br />
"id":"contacts",<br />
"style":"default",<br />
"name":"People",<br />
"values":[<br />
{<br />
"id":"contact/424242669/525793",<br />
"item":{<br />
"name":"Test Usere2123",<br />
"detail":"testuse1212r@example.com"<br />
},<br />
"options":[<br />
{<br />
"id":"from",<br />
"name":"From",<br />
"filter":{}<br />
},<br />
{<br />
"id":"to",<br />
"name":"To",<br />
"filter":{}<br />
},<br />
{<br />
"id":"all",<br />
"name":"From/To",<br />
"filter":{}<br />
}<br />
]<br />
}<br />
],<br />
"flags":[]<br />
},<br />
{<br />
"id":"time",<br />
"style":"exclusive",<br />
"name":"Time",<br />
"options":[<br />
{<br />
"id":"last_week",<br />
"name":"last week",<br />
"filter":{}<br />
},<br />
{<br />
"id":"last_month",<br />
"name":"last month",<br />
"filter":{}<br />
},<br />
{<br />
"id":"last_year",<br />
"name":"last year",<br />
"filter":{}<br />
}<br />
],<br />
"flags":[]<br />
}<br />
]<br />
}<br />
}<br />
</pre><br />
<br />
=== query ===<br />
Mandatory URL parameters:<br />
* action=query<br />
* module=<module-name><br />
* session=<session-id><br />
<br />
Optional URL parameters:<br />
* columns=<column-ids> - A comma-separated list of the module-specific columns that shall be contained in the response items.<br />
<br />
Request body: A JSON object containing the selected facets and possible options. For pagination the keys "start" and "size" can be set.<br />
<br />
==== Example ====<br />
<pre><br />
PUT http://localhost/appsuite/api/find?action=query&module=mail&columns=102,600,601,602,603,604,605,607,608,610,611,614,652&session={{session}}<br />
{<br />
"facets":[<br />
{<br />
"facet":"folder",<br />
"value":"default0/INBOX",<br />
"filter":null<br />
},<br />
{<br />
"facet":"subject",<br />
"value":1409579708116,<br />
"filter":{<br />
"fields":[<br />
"subject"<br />
],<br />
"queries":[<br />
"lorem"<br />
]<br />
}<br />
}<br />
],<br />
"options":{<br />
"timezone":"UTC",<br />
"admin":false<br />
},<br />
"start":0,<br />
"size":101<br />
}<br />
<br />
Response:<br />
{<br />
"data":{<br />
"num_found":-1,<br />
"start":0,<br />
"size":1,<br />
"results":[<br />
{<br />
"color_label":0,<br />
"id":"110458",<br />
"folder_id":"default0/INBOX",<br />
"attachment":false,<br />
"from":[<br />
[<br />
"John Doe",<br />
"john.doe@example.com"<br />
]<br />
],<br />
"to":[<br />
[<br />
"Jane Doe",<br />
"jane.doe@example.com"<br />
]<br />
],<br />
"cc":[<br />
<br />
],<br />
"subject":"Lorem Ipsum",<br />
"size":7501,<br />
"received_date":1408531387000,<br />
"flags":32,<br />
"priority":3,<br />
"account_name":"E-Mail",<br />
"account_id":0<br />
}<br />
]<br />
}<br />
}<br />
</pre><br />
<br />
=== Available Options ===<br />
Every request body may contain an "options" object to finetune some specific behavior. Currently possible options are:<br />
* timezone: <tz-name> - The timezone to use if any dates are returned.<br />
* admin: <boolean> - true to include the context admin if it matches any search criteria. If the context admin shall always be ignored (i.e. not returned), false has to be set.<br />
<br />
=== Possible Flags ===<br />
Every facet may carry one or more flags that describe further aspects of that facet. Currently possible flags are:<br />
* conflicts - Specified in the form of "conflicts:<other-id>". A facet carrying this flag must not be combined with a facet of type <other-id>.<br />
<br />
<br />
== Module "share/management" (preliminary, available with v7.8.0) ==<br />
<br />
Existing shares can be accessed via different actions in the "share/management" module. <br />
<br />
=== Get all shares ===<br />
<br />
GET <code>/ajax/share/management?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>module</code> – (optional) The module identifier to list all shares for.<br />
<br />
Response with timestamp: An array with share data. Each array element is a JSON object as described Share Info.<br />
<br />
{| id="ShareInfo" cellspacing="0" border="1"<br />
|+ align="bottom" | Share Info<br />
! Name !! Type !! Value<br />
|-<br />
| share_url || String || The URL to access the share.<br />
|-<br />
| token || String || The (fully qualified) token of the share target.<br />
|-<br />
| authentication || String || The authentication type used to access the share, one of ''guest_password'', ''anonymous'' or ''anonymous_password''. <br />
|-<br />
| created || Time || The time the share was created. <br />
|-<br />
| created_by || Number || The identifier of the user who created the share. <br />
|-<br />
| last_modified || Time || The time the share was last modified. <br />
|-<br />
| modified_by || Time || The identifier of the user who modified the share. <br />
|-<br />
| target || Object || The share target as described in Share Target <br />
|-<br />
| recipient || Object || Information about the recipient of the share, i.e. the guest user, as described in Share Recipient <br />
|}<br />
<br />
{| id="ShareTarget" cellspacing="0" border="1"<br />
|+ align="bottom" | Share Target<br />
! Name !! Type !! Value<br />
|-<br />
| module || String || The folder's module name, i.e. one of "tasks", "calendar", "contacts", "infostore" <br />
|-<br />
| folder || String || The folder identifier <br />
|-<br />
| item || String || (Optional) The object identifier, in case the share targets a single item <br />
|-<br />
| expiry_date || Time || (Optional) The end date / expiration time after which the share link is no longer accessible. Must be given in milliseconds after 01-01-1970 in the users time zone or the time zone contained as URL parameter <br />
|-<br />
| meta || JSON || Stores arbitrary JSON data as specified by client. <br />
|}<br />
<br />
{| id="ShareRecipient" cellspacing="0" border="1"<br />
|+ align="bottom" | Share Recipient<br />
! Name !! Type !! Value<br />
|-<br />
| type || String || The recipient type, one of ''guest'' or ''anonymous''. <br />
|-<br />
| base_token || String || The base token associated with the guest user. <br />
|-<br />
| password || String || The password to access the share, in case the used authentication mode is ''anonymous_password''. <br />
|-<br />
| email_address || String || The email address of the named guest user, in case the recipient type is ''guest''. <br />
|-<br />
| entity || Number || The identifier of the underlying guest user entity. <br />
|}<br />
<br />
=== Get a share ===<br />
<br />
GET <code>/ajax/share/management?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>token</code> – The (fully qualified) token of the share.<br />
<br />
Response with timestamp: A JSON object as described in Share Info.<br />
<br />
=== Delete shares ===<br />
<br />
PUT <code>/ajax/share/management?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An array containing the tokens of the shares to delete.<br />
<br />
Response with timestamp: An empty JSON result in case of no errors.<br />
<br />
=== Get a link ===<br />
<br />
PUT <code>/ajax/share/management?action=getLink</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON object describing the shares to be created as described in Get a link. It contains an array holding the share "targets" as well as some properties of the guest user to be created.<br />
<br />
Response with timestamp: Basic information about the created share as described in GetALinkResponse.<br />
<br />
{| id="GetALink" cellspacing="0" border="1"<br />
|+ align="bottom" | Get a link<br />
! Name !! Type !! Value<br />
|-<br />
| targets || Array || An array of objects as described in Share Target <br />
|-<br />
| bits || Number || (Optional) A number as described in Permission flags. For single items, the bits for reading, writing and deleting objects in folders are taken into account. At least one of those must grant permissions to all objects, not only own ones. The highest value will be chosen based on the following sequence: delete all > write all > read all. If not set, only read permissions are granted. <br />
|-<br />
| password || String || (Optional) An additional secret / pin number an anonymous user needs to enter when accessing the share <br />
|}<br />
<br />
{| id="GetALinkResponse" cellspacing="0" border="1"<br />
|+ align="bottom" | Get a link response<br />
! Name !! Type !! Value<br />
|-<br />
| url || String || The link to the share<br />
|-<br />
| token || String || The share token as a reference for consecutive requests <br />
|}<br />
<br />
=== Update a link ===<br />
<br />
PUT <code>/ajax/share/management?action=updateLink</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – The last modified timestamp of the share to be updated. Used to detect concurrent modifications.<br />
<br />
Request body: A JSON object describing the share to be updated as described in UpdateALink.<br />
<br />
Response with timestamp: An empty JSON result in case of no errors.<br />
<br />
{| id="UpdateALink" cellspacing="0" border="1"<br />
|+ align="bottom" | Update a link<br />
! Name !! Type !! Value<br />
|-<br />
| token || String || The token of the share to update<br />
|-<br />
| expiry_date || Time || (Optional) The end date / expiration time after which the share link is no longer accessible. Must be given in milliseconds after 01-01-1970 in the users time zone or the time zone contained as URL parameter.<br />
|-<br />
| password || String || (Optional) An additional secret / pin number an anonymous user needs to enter when accessing the share<br />
|-<br />
| bits || Number || (Optional) A number as described in Permission flags. For single items, the bits for reading, writing and deleting objects in folders are taken into account. At least one of those must grant permissions to all objects, not only own ones. The highest value will be chosen based on the following sequence: delete all > write all > read all. If not set, only read permissions are granted.<br />
|-<br />
| meta || JSON || Stores arbitrary JSON data as specified by client<br />
|}<br />
<br />
=== Delete a link ===<br />
<br />
GET <code>/ajax/share/management?action=deleteLink</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>token</code> – The token of the share to delete.<br />
<br />
Response with timestamp: An empty JSON result in case of no errors.<br />
<br />
=== Invite ===<br />
<br />
PUT <code>/ajax/share/management?action=invite</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON object representing the shares to be created as described in Invite Data.<br />
<br />
Response with timestamp: An array of share tokens for all created external recipients. The tokens are in the same order as the recipients in the request array. For internal users and groups a NULL value is set in the array.<br />
<br />
{| id="InviteData" cellspacing="0" border="1"<br />
|+ align="bottom" | Invite data<br />
! Name !! Type !! Value<br />
|-<br />
| targets || Array || An array of objects as described in Share Target <br />
|-<br />
| recipients || Array || An array of objects as described in Invited Recipient<br />
|-<br />
| message || String || (Optional) A custom message that will be contained in the notification mails for guests with mail addresses and password.<br />
|}<br />
<br />
{| id="InvitedRecipient" cellspacing="0" border="1"<br />
|+ align="bottom" | Invited recipient<br />
! Name !! Type !! Value<br />
|-<br />
| type || String || The recipient type, i.e. one of "user", "group", "guest", "anonymous"<br />
|-<br />
| bits || Number || A number as described in Permission flags. For single items, the bits for reading, writing and deleting objects in folders are taken into account. At least one of those must grant permissions to all objects, not only own ones. The highest value will be chosen based on the following sequence: delete all > write all > read all.<br />
|-<br />
| entity || Number || (for type "user" or "group") The user or group identifier of the recipient<br />
|-<br />
| password || String || (for type "anonymous", optional) An additional secret / pin number an anonymous user needs to enter when accessing the share<br />
|-<br />
| email_address || String || (for type "guest") The e-mail address of the recipient<br />
|-<br />
| display_name || String || (for type "guest", optional) The display name of the recipient<br />
|-<br />
| contact_id || String || (for type "guest", optional) The object identifier of the corresponding contact entry if the recipient was chosen from the address book<br />
|-<br />
| contact_folder || String || (for type "guest", required if "contact_id" is set) The folder identifier of the corresponding contact entry if the recipient was chosen from the address book<br />
|}<br />
<br />
== Module "drive" ==<br />
The module <code>drive</code> is used to synchronize files and folders between server and client, using a server-centric approach to allow an easy implementation on the client-side. <br />
<br />
A detailed description can be found in a sepearet article: [[OX_Drive_API|OX Drive API]].<br />
<br />
<br />
== Module "passwordchange" ==<br />
<br />
Users can change their password via the "passwordchange" module. <br />
<br />
=== Update password ===<br />
<br />
Note: The new password will be set without any checks. The client must ensure that it is the password the user wants to set. <br />
<br />
PUT <code>/ajax/passwordchange?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON object as described in PasswordChange.<br />
<br />
Response: An empty JSON result in case of no errors.<br />
<br />
{| id="PasswordChange" cellspacing="0" border="1"<br />
|+ align="bottom" | Password change<br />
! Name !! Type !! Value<br />
|-<br />
| old_password || String || The users' current password<br />
|-<br />
| new_password || String || The new password the user wants to set<br />
|-<br />
|}</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:I18n&diff=19705AppSuite:I18n2015-06-22T12:56:56Z<p>Viktor.Pracht: /* Custom Translations */ Use best practices for require calls</p>
<hr />
<div>{{Stability-experimental}}<br />
<br />
<div class="title">Internationalization (i18n)</div><br />
<br />
__TOC__<br />
<br />
Providing software for users in the whole world means providing it in multiple languages. This consists of two steps:<br />
<br />
* ''Internationalization (i18n)'' - Making the software international, i. e. preparing it to be adapted to different languages and locations.<br />
* ''Localization (L10n)'' - Adapting the software to a particular language and/or location.<br />
The Open-Xchange platform offers several facilities to simplify both parts. The L10n part is mostly a concern for translators. Open-Xchange facilities for that consist mainly of using a well-established format for translations: [http://www.gnu.org/s/gettext/ GNU Gettext] Portable Object (PO) files. This allows translators to use existing dedicated translation tools or a simple UTF-8-capable text editor.<br />
<br />
The i18n part is what software developers will be mostly dealing with and is what the rest of this document describes.<br />
<br />
==Translation==<br />
<br />
The main part of i18n is the translation of various text strings which are presented to the user. For this purpose, the Open-Xchange platform provides the RequireJS plugin <tt>'gettext'</tt>. Individual translation files are specified as a module dependency of the form <tt>'gettext!module_name'</tt>. The resulting module API is a function which can be called to translate a string using the specified translation files:<br />
<br />
<pre class="language-javascript"><br />
define('com.example/example', ['gettext!com.example/example'],<br />
function (gt) {<br />
'use strict';<br />
alert(gt('Hello, world!'));<br />
});<br />
</pre><br />
<br />
A file named ox.pot is created by the <tt>ox.pot</tt> (< 7.6.0) or <tt>create_pot</tt> (>= 7.6.0) tasks of the build system. So for versions < 7.6.0 you will need to run:<br />
<br />
$ build-appsuite ox.pot<br />
<br />
to create the file in the apps root directory.<br />
<br />
Working with a version starting from 7.6.0, the command:<br />
<br />
$ grunt create_pot<br />
<br />
will generate this file within the <tt>i18n/</tt> directory. It will contain an entry for every call to one of <tt>gettext</tt> functions:<br />
<br />
<pre class="language-gettext"><br />
#: apps/com.example/example.js:4<br />
msgid "Hello, world!"<br />
msgstr ""<br />
</pre><br />
<br />
This file can be sent to the translators and during the translation process, one PO file for each language will be created. The PO files in the directory <tt>i18n</tt> shoud contain the translated entry:<br />
<br />
<pre class="language-gettext"><br />
#: apps/com.example/example.js:4<br />
msgid "Hello, world!"<br />
msgstr "Hallo, Welt!"<br />
</pre><br />
<br />
During the next build, the entries are copied from the central PO files into individual translation files. In our example, this would be <tt>apps/com.example/example.de_DE.js</tt>. Because of the added language ID, translation files can usually have the same name as the corresponding main module. Multiple related modules should use the same translation file to avoid the overhead of too many small translation files.<br />
<br />
Most modules will require more complex translations than can be provided by a simple string lookup. To handle some of these cases, the <tt>gettext</tt> module provides traditional methods in addition to being a callable function. Other cases are handled by the build system.<br />
<br />
==Composite Phrases==<br />
<br />
In most cases, the translated texts will not be static, but contain dynamic values as parts of a sentence. The straight-forward approach of translating parts of the sentence individually and then using string concatenation to compose the final text is a BAD idea. Different languages have different sentence structures, and if there are multiple dynamic values, their order might need to be reversed in some languages, and not reversed in others.<br />
<br />
The solution is to translate entire sentences and then to use the <tt>gettext</tt> function to insert dynamic values:<br />
<br />
<pre class="language-javascript"><br />
alert(<br />
//#. %1$s is the given name<br />
//#. %2$s is the family name<br />
//#, c-format<br />
gt('Welcome, %1$s %2$s!', firstName, lastName));<br />
</pre><br />
<br />
Results in:<br />
<br />
<pre class="language-gettext"><br />
#. %1$s is the given name<br />
#. %2$s is the family name<br />
#, c-format<br />
msgid "Welcome, %1$s, %2$s"<br />
msgstr ""<br />
</pre><br />
<br />
As shown in the example, it is possible to add comments for translators by starting a comment with <tt>"#."</tt>. Such comments must be placed immediately before the name of the variable which refers to the <tt>gettext</tt> module (in this case <tt>gt</tt>). They can be separated by arbitrary whitespace and newlines, but not other tokens. All such <tt>gettext</tt> calls should have comments explaining every format specifier.<br />
<br />
Comments starting with <tt>"#,"</tt> are meant for <tt>gettext</tt> tools, which in the case of <tt>"#, c-format"</tt>, can ensure that the translator did not leave out or mistype any of the format specifiers.<br />
<br />
For the cases when the format string must be translated by one of the functions described below, there is a dedicated format function <tt>gettext.format</tt> which, except for debugging, is an alias for <tt>_.printf</tt>.<br />
<br />
==Debugging==<br />
<br />
One of the most common i18n errors is forgetting to use a <tt>gettext</tt> function. To catch this kind of error, the UI can be started with the hash parameter <tt>"#debug-i18n=1"</tt>. (Reloading of the browser tab is usually required for the setting to take effect.)<br />
<br />
In this mode, every translated string is marked with invisible Unicode characters, and any DOM text without those characters gets reported on the console. The <tt>gettext.format</tt> function then also checks that every parameter is translated. This is the reason why <tt>_.printf</tt> should not be used for user-visible strings directly.<br />
<br />
Unfortunately, this method will also report any string which does not actually require translation. Examples of such strings include user data, numbers, strings already translated by the server, etc. To avoid filling the console with such false positives, every such string must be marked by passing it through the function <tt>gettext.noI18n</tt>:<br />
<br />
<pre class="language-javascript"><br />
alert(<br />
//#. %1$s is the given name<br />
//#. %2$s is the family name<br />
//#, c-format<br />
gt('Welcome, %1$s %2$s!', gt.noI18n(firstName), gt.noI18n(lastName)));<br />
</pre><br />
<br />
This results in the strings being marked as 'translated' without actually changing their visible contents. When not debugging, <tt>gettext.noI18n</tt> simply returns its first parameter.<br />
<br />
==Advanced gettext Functions==<br />
<br />
Besides <tt>gettext.format</tt> and <tt>gettext.noI18n</tt> there are several other functions which are required to cover all typical translation scenarios.<br />
<br />
===Contexts===<br />
<br />
Sometimes, the same English word or phrase has multiple meanings and must be translated differently depending on context. To be able to tell the individual translations apart, the method <tt>gettext.pgettext</tt> ('p' stands for 'particular') should be used instead of calling <tt>gettext</tt> directly. It takes the context as the first parameter and the text to translate as the second parameter:<br />
<br />
<pre class="language-javascript"><br />
alert(gt.pgettext('description', 'Title'));<br />
alert(gt.pgettext('salutation', 'Title'));<br />
</pre><br />
<br />
Results in:<br />
<br />
<pre class="language-gettext"><br />
msctxt "description"<br />
msgid "Title"<br />
msgstr "Beschreibung"<br />
<br />
msctxt "salutation"<br />
msgid "Title"<br />
msgstr "Anrede"<br />
</pre><br />
<br />
===Plural forms===<br />
<br />
In the case of numbers, the rules to select the proper plural form can be very complex. With the exception of languages with no separate plural forms, English is the second simplest language in this respect, having only two plural forms: singular and plural. Other languages can have up to four forms, and theoretically even more. The functions <tt>gettext.ngettext</tt> and <tt>gettext.npgettext</tt> (for a combination of plural forms with contexts) can select the proper plural form by using a piece of executable code embedded in the header of a PO file:<br />
<br />
<pre class="language-javascript"><br />
alert(gt.format(<br />
//#. %1$d is the number of mails<br />
//#, c-format<br />
gt.ngettext('You have %1$d mail', 'You have %1$d mails', n),<br />
gt.noI18n(n)));<br />
</pre><br />
<br />
The function <tt>gettext.ngettext</tt> accepts three parameters: the English singular and plural forms and the number which determines the chosen plural form. The function <tt>gettext.npgettext</tt> adds a context parameter before the others, similar to <tt>gettext.pgettext</tt>. They are usually used in combination with <tt>gettext.format</tt> to insert the actual number into the translated string.<br />
<br />
The above example results in the following entry:<br />
<br />
<pre class="language-gettext"><br />
#. %1$d is the number of mails<br />
#, c-format<br />
msgid "You have %1$d mail"<br />
msgid_plural "You have %1$d mails"<br />
msgstr[0] ""<br />
msgstr[1] ""<br />
</pre><br />
<br />
The number of <tt>msgstr[N]</tt> lines is determined by the number of plural forms in each language. This number is specified in the header of each PO file, together with the code to compute the index of the correct plural form the supplied number.<br />
<br />
==Custom Translations==<br />
App Suite has support for custom translations. ''gettext'' provides a function ''addTranslation(dictionary, key, value)'' that allows adding custom translation to a global dictionary ("*") as well as replacing translations in existing dictionaries. In order to use this, you have to create a plugin for the "core" namespace.<br />
<br />
<pre class="language-javascript"> <br />
require(['io.ox/core/gettext'], function (gt) {<br />
gt.addTranslation('*', 'Existing translation', 'My custom translation');<br />
});<br />
</pre><br />
<br />
To keep it simple you can use the internal escaping to build counterparts for ngettext, pgettext, as well as npgettext. A context is escaped by \x00. Singular and plural are separated by \x01:<br />
<br />
<pre class="language-javascript"> <br />
// load gettext<br />
var gt = require('io.ox/core/gettext');<br />
<br />
// replace translation in dictionary 'io.ox/core'. Apps use context "app".<br />
gt.addTranslation('io.ox/core', 'app\x00Address Book', 'My Contacts');<br />
<br />
// replace translation - counterpart to ngettext<br />
gt.addTranslation('io.ox/mail', 'Copy\x01Copies', { 0: 'Kopie', 1: 'Kopien' });<br />
<br />
// replace translation - counterpart to npgettext<br />
gt.addTranslation('io.ox/mail', 'test\x00One\x01Two', { 0: 'Eins', 1: 'Zwei' });<br />
<br />
// some checks<br />
require(['gettext!io.ox/mail'], function (gt) {<br />
<br />
console.log('Sigular:', gt.ngettext('Copy', 'Copies', 1));<br />
console.log('Plural:', gt.ngettext('Copy', 'Copies', 2));<br />
<br />
console.log('Without context', gt.gettext('Files')); // should be 'My File Box'<br />
console.log('With context', gt.pgettext('test', 'Files')); // should be 'Files'<br />
<br />
console.log('Plural with context', gt.npgettext('test', 'One', 'Two', 2)); // should be 'Two'<br />
});<br />
<br />
</pre><br />
<br />
''addTranslation()'' always works for current language. If you want to benefit from automatic POT file generation, use the following approach:<br />
<br />
<pre class="language-javascript"> <br />
define('plugins/example/register', ['io.ox/core/gettext', 'gettext!custom'], function (gettext, gt) {<br />
<br />
'use strict';<br />
<br />
/* Just list all custom translations in your plugin by standalone gt() calls.<br />
The build system recognizes these strings and collects them in a POT file, <br />
so that they can be subject to translation processes. At runtime, gt('...')<br />
returns translations for current language.<br />
*/<br />
if (false) {<br />
gt('Tree');<br />
gt('House');<br />
gt('Dog');<br />
}<br />
<br />
// get internal dictionary (for current language of course)<br />
var dictionary = gt.getDictionary();<br />
<br />
// add all translations to global dictionary. Done!<br />
gettext.addTranslation('*', dictionary);<br />
});<br />
</pre><br />
<br />
<br />
[[Category:AppSuite]]<br />
[[Category:UI]]<br />
[[Category:Developer]]</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:Debugging_production_servers&diff=19643AppSuite:Debugging production servers2015-05-29T09:14:09Z<p>Viktor.Pracht: Created page with "{{Stability-experimental}} <div class="title">Debugging production servers</div> A how-to for debugging your local UI plugin in combination with production and staging server..."</p>
<hr />
<div>{{Stability-experimental}}<br />
<div class="title">Debugging production servers</div><br />
<br />
A how-to for debugging your local UI plugin in combination with production and staging servers, which use redirects, HTTPS, and other things which break with a simple <tt>grunt dev</tt> command.<br />
<br />
== Introduction ==<br />
<br />
Not everybody has access to a dedicated test server. Sometimes, a plugin requires a backend system which is hard to access outside of existing infrastructure. And sometimes, a bug appears only on a production server. There are many reasons why a server which is used by <tt>grunt dev</tt> can not be reconfigured and has to be used as-is.<br />
<br />
The most frequent reason, why debugging with a remote server fails, are redirects to an external login page. After the login, the browser is usually redirected to the original domain, and all the cookies used for authentication are also set for that domain, not http://localhost:8337, where Grunt listens.<br />
<br />
The solution is to use a proxy server, which redirects all requests to the server's domain to Grunt. Until <tt>grunt dev</tt> can be used as an HTTP proxy directly, a dedicated proxy is required. This proxy needs to support custom hosts files. Any kind of rewriting or forwarding usually ends up in the wrong domain being used, and therefore still breaking cookies and redirects. The global <tt>/etc/hosts</tt> can't be used because Grunt still needs to access the original server, and use the original domain name for that to properly set the <tt>Host</tt> header.<br />
<br />
The usual way to use a custom hosts file is to set it in the <tt>HOSTALIASES</tt> environment variable. Unfortunately, for security reasons, this variable is explicitly cleared when executing setuid processes. And this is exactly what proxy servers tend to do. A proxy server with explicit configuration support for custom hosts files is Squid. So that's what we will use for debugging.<br />
<br />
== HOWTO ==<br />
<br />
All commands are specified for Debian. Commands which need to be run as root start with <tt>#</tt>, commands which can be run as a normal user start with <tt>$</tt>.<br />
<br />
The examples use <tt>''user''</tt> as user name, and all temporary files are stored in <tt>/home/''user''/proxy</tt>. You should use your own directory, and can pick any other directory. For the server domain, we'll use <tt>''example.com''</tt>, which should of course be replaced by the real domain of the OX server.<br />
<br />
=== Squid ===<br />
<br />
Install Squid.<br />
<br />
# apt-get install squid3<br />
<br />
Copy your <tt>/etc/hosts</tt> file to another location.<br />
<br />
$ cp /etc/hosts /home/''user''/proxy/hosts<br />
<br />
Add a line which redirects the target domain to localhost.<br />
<br />
$ echo '127.0.0.1 ''example.com''<nowiki/>' >> /home/''user''/proxy/hosts<br />
<br />
Now this file can be added to Squid's configuration file.<br />
<br />
# echo 'hosts_file /home/''user''/proxy/hosts' >> /etc/squid3/squid.conf<br />
# service squid3 reload<br />
<br />
=== Grunt ===<br />
<br />
Assuming you already have a working <tt>local.conf.json</tt>, add the following entries to the <tt>"appserver"</tt> section:<br />
<br />
"protocol": "https",<br />
"port": 443,<br />
"server": "https://''example.com''/''custom-path''/",<br />
"rejectUnauthorized": false,<br />
"path": "/''custom-path''",<br />
<br />
The entry <tt>"path"</tt> is optional, if the default <tt>/appsuite</tt> is used.<br />
<br />
If the main path uses an HTTP redirect for a custom login page, then the initial request can't be intercepted by Grunt. The following entry disables it:<br />
<br />
"index": "/",<br />
<br />
This has two side-effects:<br />
# The mail HTML file is always served by the original server, and therefore<br />
# The timestamps used for cache-busting are not updated by Grunt.<br />
<br />
This means clearing the cache will be required more often. If that becomes too much overhead, you can log in, then remove the option and restart Grunt.<br />
<br />
=== Running <tt>grunt dev</tt>===<br />
<br />
Since Grunt needs to bind to port 443, it requires additional privileges. There are several options. Running Grunt as root is the quickest, but also least secure way. Better alternatives are <tt>authbind</tt> and <tt>setcap</tt>.<br />
<br />
Don't forget to stop your local web server (e.g. Apache),<br />
<br />
# service apache2 stop<br />
<br />
or at least disable SSL.<br />
<br />
# a2dismod ssl<br />
# service apache2 restart<br />
<br />
==== <tt>authbind</tt> ====<br />
<br />
<tt>authbind</tt> is a program which uses a setuid helper to bind to lower ports. It is usually not installed by default.<br />
<br />
# apt-get install authbind<br />
<br />
The configuration is performed by creating files in <tt>/etc/authbind</tt> and giving execute permissions to the appropriate users.<br />
<br />
# touch /etc/authbind/443<br />
# chown ''user'' /etc/authbind/443<br />
# chmod 544 /etc/authbind<br />
<br />
Now, Grunt can be started using the wrapper.<br />
<br />
$ authbind --deep grunt dev<br />
<br />
==== <tt>setcap</tt> ====<br />
<br />
This option can be used if your file system supports capabilities. It is less secure since it grants the permission to bind to all low ports to any Node program. But if supported, it at least does not require additional tools.<br />
<br />
# setcap "cap_net_bind_service=+ep" "$(readlink -f "$(which node)")"<br />
<br />
On OS X, <tt>greadlink</tt> needs to be used instead of <tt>readlink</tt>. If you don't have it, just find out where the actual <tt>node</tt> binary is installed and use it directly as the second parameter to <tt>setcap</tt>.<br />
<br />
Grunt can then be run as usual.<br />
<br />
$ grunt dev<br />
<br />
=== Launching the browser ===<br />
<br />
Now that everything is running, you only need to use the proxy when debugging your code in the browser. Most browsers have their own proxy settings, which override system-wide settings. They also respect environment variables like <tt>http_proxy</tt>.<br />
<br />
$ http_proxy=http://localhost:3128 firefox<br />
<br />
Chrome does not have its own settings (it starts the global settings dialog) and it ignores http_proxy. Instead, you have to use a command line parameter:<br />
<br />
$ chromium --proxy-server=http://localhost:3128</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=Portal:AppSuite_UI/Topics&diff=19642Portal:AppSuite UI/Topics2015-05-29T09:14:01Z<p>Viktor.Pracht: added "Debugging production servers" (last rename, honest ;-) )</p>
<hr />
<div>== Getting started ==<br />
* [[AppSuite:GettingStarted | Getting started developing an external app]]<br />
* [[AppSuite:Upgrade_app_using_yo | Upgrade your external app to latest App Suite version]]<br />
* [[AppSuite:UI developer primer| Skills needed to develop the UI]]<br />
* [[AppSuite:Getting started developing the UI | Getting started developing the UI]]<br />
* [[AppSuite:UI_Development_Style_Guide | UI Development Style Guide]]<br />
* [[AppSuite:Appserver | Appserver]]<br />
* [[AppSuite:Apache Configuration | Apache Configuration]]<br />
* [[AppSuite:Definition of done|Definition of done]]<br />
* [[Appsuite:UI_FAQ | Frequently asked questions]]<br />
<br />
== Upgrading apps, plugins, and themes to 7.6 ==<br />
* [[AppSuite:Upgrading_to_7_6|Upgrading to 7.6]]<br />
<br />
== Testing ==<br />
* [[AppSuite:Test basics | Lessons learned while testing]]<br />
* [[AppSuite:RunTests | Running ui tests]]<br />
* [[AppSuite:Testing_3rd-party_code | In-depth article on testing]] aimed at external developers<br />
<br />
== How-to articles ==<br />
* [[AppSuite:Action links|Understanding action links]]<br />
** [[AppSuite:Files App Actions|Adding actions to the files app]]<br />
* [[AppSuite:Date_and_time|Date and time]]<br />
* [[AppSuite:i18n | Internationalization (i18n)]]<br />
* [[AppSuite:a11y | Accessibility (a11y)]]<br />
* [[AppSuite:Mediaplayer | Mediaplayer]]<br />
* [[AppSuite:Theming | Theming]]<br />
* [[AppSuite:UI manifests explained | UI manifests explained]]<br />
* [[AppSuite:Upsell | Upsell]]<br />
* [[AppSuite:VGrid | VGrid]]<br />
* [[AppSuite:Mobile | Mobile development]]<br />
* [[AppSuite:Upsell tools| Upsell tools]]<br />
* [[AppSuite:Guided tours| Guided tours]]<br />
* [[AppSuite:Browserdetection | Browser detection with form-login]]<br />
* [[AppSuite:BackboneMiniViews | Backbone mini views]]<br />
<br />
=== Server communication ===<br />
* [[AppSuite:APIs | APIs]]<br />
* [[AppSuite:API_Factory | API Factory]]<br />
* [[AppSuite:http.js | http.js]]<br />
<br />
=== Extension points ===<br />
* [[AppSuite:Extending_the_UI_(Hands-on_introduction)| Hands-on introduction]]<br />
* [[AppSuite:Extending_the_UI | General information on extension points]]<br />
* [[AppSuite:Modifying forms by using extension points | Modifying forms]]<br />
* [[AppSuite:Create custom folderview entries in settings app | Edit folderview entries in settings]]<br />
* [[AppSuite:Extension points for calendar |extension points: Calendar]]<br />
* [[AppSuite:Extension points for contact |extension points: Contact]]<br />
* [[AppSuite:Extension points for core | extension points: Core]]<br />
* [[AppSuite:Extension points for email | extension points: E-Mail]]<br />
* [[AppSuite:Extension points for files |extension points: Files]]<br />
* [[AppSuite:Extension points for tasks |extension points: Tasks]]<br />
* [[AppSuite:Extension points for miscellaneous |extension points: Miscellaneous]]<br />
<br />
=== Writing components ===<br />
* [[AppSuite:Writing a portal plugin | Writing a portal plugin]]<br />
** [[AppSuite:Configuring portal plugins|Configuring a portal plugin]]<br />
** [[AppSuite:Using the Upsell widget|Using the Upsell widget]]<br />
* [[AppSuite:Writing a simple application | Writing a simple application]]<br />
* [[AppSuite:Writing a simple application with embedded iframe | Writing a simple application with embedded iframe and launcher link ]]<br />
* [[AppSuite:Writing a notification area plugin | Writing a plugin for the notification area]]<br />
* [[AppSuite:Writing a wizard | Writing a wizard]]<br />
* [[AppSuite:Capabilities | Capabilities explained]] - if you want to enable or disable your plugin<br />
<br />
== Miscellaneous articles ==<br />
* [[AppSuite:External libraries for the UI | External libraries used by the UI]]<br />
* [[AppSuite:Configuration| Configuration]]<br />
* [[AppSuite:Custom configurations| Custom configurations]]<br />
* [[AppSuite:UI build system| The UI build system]]<br />
* [[AppSuite:Embedding your settings into AppSuite settings|How to embed your own settings into the Appsuite settings page]]<br />
* [[AppSuite:Debugging the UI|Debugging the UI]]<br />
* [[Appsuite:Debugging production servers|Debugging production servers]]<br />
* [[AppSuite:Memory leaks (UI)|Finding memory leaks in the UI]]<br />
* [[AppSuite:Device reference|_.device() reference]]<br />
* [[AppSuite:Paste inline images|Paste inline images]]<br />
* All articles regarding the UI are filed in the category [[:Category:UI]]</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=Portal:AppSuite_UI/Topics&diff=19639Portal:AppSuite UI/Topics2015-05-28T16:16:02Z<p>Viktor.Pracht: </p>
<hr />
<div>== Getting started ==<br />
* [[AppSuite:GettingStarted | Getting started developing an external app]]<br />
* [[AppSuite:Upgrade_app_using_yo | Upgrade your external app to latest App Suite version]]<br />
* [[AppSuite:UI developer primer| Skills needed to develop the UI]]<br />
* [[AppSuite:Getting started developing the UI | Getting started developing the UI]]<br />
* [[AppSuite:UI_Development_Style_Guide | UI Development Style Guide]]<br />
* [[AppSuite:Appserver | Appserver]]<br />
* [[AppSuite:Apache Configuration | Apache Configuration]]<br />
* [[AppSuite:Definition of done|Definition of done]]<br />
* [[Appsuite:UI_FAQ | Frequently asked questions]]<br />
<br />
== Upgrading apps, plugins, and themes to 7.6 ==<br />
* [[AppSuite:Upgrading_to_7_6|Upgrading to 7.6]]<br />
<br />
== Testing ==<br />
* [[AppSuite:Test basics | Lessons learned while testing]]<br />
* [[AppSuite:RunTests | Running ui tests]]<br />
* [[AppSuite:Testing_3rd-party_code | In-depth article on testing]] aimed at external developers<br />
<br />
== How-to articles ==<br />
* [[AppSuite:Action links|Understanding action links]]<br />
** [[AppSuite:Files App Actions|Adding actions to the files app]]<br />
* [[AppSuite:Date_and_time|Date and time]]<br />
* [[AppSuite:i18n | Internationalization (i18n)]]<br />
* [[AppSuite:a11y | Accessibility (a11y)]]<br />
* [[AppSuite:Mediaplayer | Mediaplayer]]<br />
* [[AppSuite:Theming | Theming]]<br />
* [[AppSuite:UI manifests explained | UI manifests explained]]<br />
* [[AppSuite:Upsell | Upsell]]<br />
* [[AppSuite:VGrid | VGrid]]<br />
* [[AppSuite:Mobile | Mobile development]]<br />
* [[AppSuite:Upsell tools| Upsell tools]]<br />
* [[AppSuite:Guided tours| Guided tours]]<br />
* [[AppSuite:Browserdetection | Browser detection with form-login]]<br />
* [[AppSuite:BackboneMiniViews | Backbone mini views]]<br />
<br />
=== Server communication ===<br />
* [[AppSuite:APIs | APIs]]<br />
* [[AppSuite:API_Factory | API Factory]]<br />
* [[AppSuite:http.js | http.js]]<br />
<br />
=== Extension points ===<br />
* [[AppSuite:Extending_the_UI_(Hands-on_introduction)| Hands-on introduction]]<br />
* [[AppSuite:Extending_the_UI | General information on extension points]]<br />
* [[AppSuite:Modifying forms by using extension points | Modifying forms]]<br />
* [[AppSuite:Create custom folderview entries in settings app | Edit folderview entries in settings]]<br />
* [[AppSuite:Extension points for calendar |extension points: Calendar]]<br />
* [[AppSuite:Extension points for contact |extension points: Contact]]<br />
* [[AppSuite:Extension points for core | extension points: Core]]<br />
* [[AppSuite:Extension points for email | extension points: E-Mail]]<br />
* [[AppSuite:Extension points for files |extension points: Files]]<br />
* [[AppSuite:Extension points for tasks |extension points: Tasks]]<br />
* [[AppSuite:Extension points for miscellaneous |extension points: Miscellaneous]]<br />
<br />
=== Writing components ===<br />
* [[AppSuite:Writing a portal plugin | Writing a portal plugin]]<br />
** [[AppSuite:Configuring portal plugins|Configuring a portal plugin]]<br />
** [[AppSuite:Using the Upsell widget|Using the Upsell widget]]<br />
* [[AppSuite:Writing a simple application | Writing a simple application]]<br />
* [[AppSuite:Writing a simple application with embedded iframe | Writing a simple application with embedded iframe and launcher link ]]<br />
* [[AppSuite:Writing a notification area plugin | Writing a plugin for the notification area]]<br />
* [[AppSuite:Writing a wizard | Writing a wizard]]<br />
* [[AppSuite:Capabilities | Capabilities explained]] - if you want to enable or disable your plugin<br />
<br />
== Miscellaneous articles ==<br />
* [[AppSuite:External libraries for the UI | External libraries used by the UI]]<br />
* [[AppSuite:Configuration| Configuration]]<br />
* [[AppSuite:Custom configurations| Custom configurations]]<br />
* [[AppSuite:UI build system| The UI build system]]<br />
* [[AppSuite:Embedding your settings into AppSuite settings|How to embed your own settings into the Appsuite settings page]]<br />
* [[AppSuite:Debugging the UI|Debugging the UI]]<br />
* [[Appsuite:Debugging with HTTP redirects|Debugging with HTTP redirects]]<br />
* [[AppSuite:Memory leaks (UI)|Finding memory leaks in the UI]]<br />
* [[AppSuite:Device reference|_.device() reference]]<br />
* [[AppSuite:Paste inline images|Paste inline images]]<br />
* All articles regarding the UI are filed in the category [[:Category:UI]]</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=Portal:AppSuite_UI/Topics&diff=19638Portal:AppSuite UI/Topics2015-05-28T16:04:50Z<p>Viktor.Pracht: added Debugging HTTPS</p>
<hr />
<div>== Getting started ==<br />
* [[AppSuite:GettingStarted | Getting started developing an external app]]<br />
* [[AppSuite:Upgrade_app_using_yo | Upgrade your external app to latest App Suite version]]<br />
* [[AppSuite:UI developer primer| Skills needed to develop the UI]]<br />
* [[AppSuite:Getting started developing the UI | Getting started developing the UI]]<br />
* [[AppSuite:UI_Development_Style_Guide | UI Development Style Guide]]<br />
* [[AppSuite:Appserver | Appserver]]<br />
* [[AppSuite:Apache Configuration | Apache Configuration]]<br />
* [[AppSuite:Definition of done|Definition of done]]<br />
* [[Appsuite:UI_FAQ | Frequently asked questions]]<br />
<br />
== Upgrading apps, plugins, and themes to 7.6 ==<br />
* [[AppSuite:Upgrading_to_7_6|Upgrading to 7.6]]<br />
<br />
== Testing ==<br />
* [[AppSuite:Test basics | Lessons learned while testing]]<br />
* [[AppSuite:RunTests | Running ui tests]]<br />
* [[AppSuite:Testing_3rd-party_code | In-depth article on testing]] aimed at external developers<br />
<br />
== How-to articles ==<br />
* [[AppSuite:Action links|Understanding action links]]<br />
** [[AppSuite:Files App Actions|Adding actions to the files app]]<br />
* [[AppSuite:Date_and_time|Date and time]]<br />
* [[AppSuite:i18n | Internationalization (i18n)]]<br />
* [[AppSuite:a11y | Accessibility (a11y)]]<br />
* [[AppSuite:Mediaplayer | Mediaplayer]]<br />
* [[AppSuite:Theming | Theming]]<br />
* [[AppSuite:UI manifests explained | UI manifests explained]]<br />
* [[AppSuite:Upsell | Upsell]]<br />
* [[AppSuite:VGrid | VGrid]]<br />
* [[AppSuite:Mobile | Mobile development]]<br />
* [[AppSuite:Upsell tools| Upsell tools]]<br />
* [[AppSuite:Guided tours| Guided tours]]<br />
* [[AppSuite:Browserdetection | Browser detection with form-login]]<br />
* [[AppSuite:BackboneMiniViews | Backbone mini views]]<br />
<br />
=== Server communication ===<br />
* [[AppSuite:APIs | APIs]]<br />
* [[AppSuite:API_Factory | API Factory]]<br />
* [[AppSuite:http.js | http.js]]<br />
<br />
=== Extension points ===<br />
* [[AppSuite:Extending_the_UI_(Hands-on_introduction)| Hands-on introduction]]<br />
* [[AppSuite:Extending_the_UI | General information on extension points]]<br />
* [[AppSuite:Modifying forms by using extension points | Modifying forms]]<br />
* [[AppSuite:Create custom folderview entries in settings app | Edit folderview entries in settings]]<br />
* [[AppSuite:Extension points for calendar |extension points: Calendar]]<br />
* [[AppSuite:Extension points for contact |extension points: Contact]]<br />
* [[AppSuite:Extension points for core | extension points: Core]]<br />
* [[AppSuite:Extension points for email | extension points: E-Mail]]<br />
* [[AppSuite:Extension points for files |extension points: Files]]<br />
* [[AppSuite:Extension points for tasks |extension points: Tasks]]<br />
* [[AppSuite:Extension points for miscellaneous |extension points: Miscellaneous]]<br />
<br />
=== Writing components ===<br />
* [[AppSuite:Writing a portal plugin | Writing a portal plugin]]<br />
** [[AppSuite:Configuring portal plugins|Configuring a portal plugin]]<br />
** [[AppSuite:Using the Upsell widget|Using the Upsell widget]]<br />
* [[AppSuite:Writing a simple application | Writing a simple application]]<br />
* [[AppSuite:Writing a simple application with embedded iframe | Writing a simple application with embedded iframe and launcher link ]]<br />
* [[AppSuite:Writing a notification area plugin | Writing a plugin for the notification area]]<br />
* [[AppSuite:Writing a wizard | Writing a wizard]]<br />
* [[AppSuite:Capabilities | Capabilities explained]] - if you want to enable or disable your plugin<br />
<br />
== Miscellaneous articles ==<br />
* [[AppSuite:External libraries for the UI | External libraries used by the UI]]<br />
* [[AppSuite:Configuration| Configuration]]<br />
* [[AppSuite:Custom configurations| Custom configurations]]<br />
* [[AppSuite:UI build system| The UI build system]]<br />
* [[AppSuite:Embedding your settings into AppSuite settings|How to embed your own settings into the Appsuite settings page]]<br />
* [[AppSuite:Debugging the UI|Debugging the UI]]<br />
* [[Appsuite:Debugging HTTPS|Debugging with an HTTPS server]]<br />
* [[AppSuite:Memory leaks (UI)|Finding memory leaks in the UI]]<br />
* [[AppSuite:Device reference|_.device() reference]]<br />
* [[AppSuite:Paste inline images|Paste inline images]]<br />
* All articles regarding the UI are filed in the category [[:Category:UI]]</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=HTTP_API&diff=19553HTTP API2015-05-11T09:17:53Z<p>Viktor.Pracht: /* Get all grants */ Use the types defined in #Date_and_time</p>
<hr />
<div>== Introduction ==<br />
<br />
This document defines the Open-Xchange HTTP API which is used by the new AJAX GUI. The first chapter describes general definitions and conventions which apply to all server modules. All other chapters describe individual server modules.<br />
<br />
=== Low level protocol ===<br />
<br />
The client accesses the server through HTTP GET, POST and PUT requests. HTTP cookies are used for authentication and must therefore be processed and sent back by the client as specified by [http://tools.ietf.org/html/rfc6265 RFC 6265]. The HTTP API is accessible at URIs starting with <code>/ajax</code>. Each server module has a unique name and its own sub-namespace with that name below <code>/ajax</code>, e. g. all access to the module "tasks" is via URIs starting with <code>/ajax/tasks</code>.<br />
<br />
Text encoding is always UTF-8. Data is sent from the server to the client as <code>text/javascript</code> and interpreted by the client to obtain an ECMAScript object. The HTTP API uses only a small subset of the ECMAScript syntax. This subset is roughly described by the following BNF:<br />
<br />
Value ::= "null" | Boolean | Number | String | Array | Object<br />
Boolean ::= "true" | "false"<br />
Number ::= see NumericLiteral in ECMA 262 3rd edition<br />
String ::= \"([^"\n\\]|\\["\n\\])*\"<br />
Array ::= "[]" | "[" Value ("," Value)* "]"<br />
Object ::= "{}" | "{" Name ":" Value ("," Name ":" Value)* "}"<br />
Name ::= [A-Fa-f][0-9A-Fa-f_]*<br />
<br />
Numbers are the standard signed integer and floating point numbers. Strings can contain any character, except double quotes, newlines and backslashes, which must be escaped by a backslash. Control characters in strings (other than newline) are not supported. Whitespace is allowed between any two tokens. See [http://json.org JSON] and [http://www.ecma-international.org/publications/standards/Ecma-262.htm ECMA 262, 3<sup>rd</sup> edition] for the formal definition.<br />
<br />
The response body consists of an object, which contains up to four fields as described in [[#ResponseBody | Response body]]. The field <code>data</code> contains the actual payload which is described in following chapters. The fields <code>timestamp</code>, <code>error</code> and <code>error_params</code> are present when data objects are returned, if an error occurred and if the error message contains conversion specifiers, respectively. Following sections describe the contents of these fields in more detail.<br />
<br />
{| id="ResponseBody" cellspacing="0" border="1"<br />
|+ align="bottom" | Response body<br />
! Name !! Type !! Value<br />
|-<br />
| data || Value || Payload of the response.<br />
|-<br />
| timestamp || Timestamp || The latest timestamp of the returned data (see [[HTTP_API#Updates|Updates]]).<br />
|-<br />
| error || String || The translated error message. Present in case of errors.<br />
|-<br />
| error_params || Array || As o 7.4.2: Empty JSON array. Before that: Parameters for the error message that would need to be replaced in the error string (in a printf-format style).<br />
|-<br />
| error_id || String || Unique error identifier to help finding this error instance in the server logs.<br />
|-<br />
| error_desc || String || The technical error message (always English) useful for debugging the problem. Might be the same as error message if there is no more information available<br />
|-<br />
| code || String || Error code consisting of an upper-case module identifier and a four-digit message number, separated by a dash; e.g. "MSG-0012"<br />
|-<br />
| error_stack || Array || If configured (see "com.openexchange.ajax.response.includeStackTraceOnError" in 'server.properties') this field provides the stack trace of associated Java exception represented as a JSON array<br />
|-<br />
| categories || String OR Array || Either a single (String) or list (Array) of upper-case category identifiers to which the error belongs. E.g.<br />
{| cellspacing="0" border="1"<br />
| "USER_INPUT" || An error resulting from wrong or missing input from front-end (e.g. mandatory field missing).<br />
|-<br />
| "CONFIGURATION" || An error related to user/system configuration which denies requested operation.<br />
|-<br />
| "PERMISSION_DENIED" || An error related to insufficient permission settings.<br />
|-<br />
| "TRY_AGAIN" || A requested operation could not be accomplished because a needed resource is temporary down or missing (e.g. imap server rejects connection because of too many established connections).<br />
|-<br />
| "SERVICE_DOWN" || A subsystem or third party service is down and therefore does not respond (e.g. database is down).<br />
|-<br />
| "CONNECTIVITY" || The underlying socket connection is corrupt, empty or closed. Only a temporary error that does not affect the whole system.<br />
|-<br />
| "ERROR" || A programming error which was caused by incorrect program code.<br />
|-<br />
| "CONFLICT" || A concurrent modification.<br />
|-<br />
| "CAPACITY" || The requested operation could not be performed cause an underlying resource is full or busy (e.g. IMAP folder exceeds quota).<br />
|-<br />
| "TRUNCATED" || The given data could not be stored into the database because an attribute contains a too long value.<br />
|-<br />
| "WARNING" || Action was at least partially successful, but a condition occurred that merited a warning<br />
|}<br />
|-<br />
| category || Number || Maintained for legacy reasons: The numeric representation of the first category:<br />
{| cellspacing="0" border="1"<br />
| 1 || An error resulting from wrong or missing input from front-end (e.g. mandatory field missing).<br />
|-<br />
| 2 || An error strictly related to user configuration which denies requested operation.<br />
|-<br />
| 3 || An error related to insufficient permission settings.<br />
|-<br />
| 4 || A requested operation could not be accomplished because a needed resource is temporary down or missing (e.g. imap server rejects connection because of too many established connections).<br />
|-<br />
| 5 || A subsystem or third party service is down and therefore does not respond (e.g. database is down).<br />
|-<br />
| 6 || The underlying socket connection is corrupt, empty or closed. Only a temporary error that does not affect the whole system.<br />
|-<br />
| 8 || A programming error which was caused by incorrect programm code.<br />
|-<br />
| 9 || A concurrent modification.<br />
|-<br />
| 11 || The requested operation could not be performed cause an underlying resource is full or busy (e.g. IMAP folder exceeds quota).<br />
|-<br />
| 12 || The given data could not be stored into the database because an attribute contains a too long value.<br />
|-<br />
| 13 || Action was at least partially successful, but a condition occurred that merited a warning<br />
|}<br />
|}<br />
<br />
Data from the client to the server can be sent in several formats. Small amounts of data are sent as <code>application/x-www-urlencoded</code> in query parameters in the request URI. For POST requests, some or all parameters may be sent in the request body instead of in the URI using any valid encoding for POST requests. Alternatively, some requests specify that data is sent as <code>text/javascript</code> in the body of a PUT request. The format of the request body for PUT requests is the same as for sending data from the server to the client, except that the payload is sent directly, without being wrapped in another object.<br />
<br />
When updating existing data, the client sends only fields that were modified. To explicitly delete a field, the field is sent with the value <code>null</code>. For fields of type <code>String</code>, the empty string <code>""</code> is equivalent to <code>null</code>.<br />
<br />
=== Error handling ===<br />
<br />
If the session of the user times out, if the client doesn't send a session ID or if the session for the specified session ID can not be found then the server returns the above described response object, that contains an error code and an error message. If the request URI or the request body is malformed or incomplete then the server returns the reponse object with an error message, too. In case of internal server errors, especially Java exceptions, or if the server is down, it returns the HTTP status code 503, Service Unavailable. Other severe errors may return other HTTP status values.<br />
<br />
Application errors, which can be caused by a user and are therefore expected during the operation of the groupware, are reported by setting the field error in the returned object, as described in [[#ResponseBody | Response body]]. Since the error messages are translated by the client, they can not be composed of multiple variable parts. Instead, the error message can contain simplified printf()-style conversion specifications, which are replaced by elements from the array in the field error_params. If error_params is not present, no replacement occurs, even if parts of the error message match the syntax of a conversion specification.<br />
<br />
A simplified conversion specification, as used for error messages, is either of the form %s or %''n''$s, where ''n'' is a 1-based decimal parameter index. The conversion specifications are replaced from left to right by elements from error_params, starting at the first element. %s is replaced by the current element and the current index is incremented. %''n''$s is replaced by the ''n''th element and the current index is set to the (''n'' + 1)th element.<br />
<br />
Some error message contain data sizes which must be expressed in Bytes or Kilobytes etc., depending on the actual value. Since the unit must be translated, this conversion is performed by the client. Unfortunately, standard printf()-style formatting does not have a specifier for this kind of translation. Therefore, the conversion specification for sizes is the same as for normal strings, and the client has to determine which parameters to translate based on the error code. The current error codes and the corresponding size parameters are listed in [[#DataSizeParameters | Data size parameters]]<br />
<br />
{| id="DataSizeParameters" cellspacing="0" border="1"<br />
|+ align="bottom" | Data size parameters<br />
! Error code !! Parameter indices<br />
|-<br />
| CON-0101 || 2, 3<br />
|-<br />
| FLS-0003 || 1, 2, 3<br />
|-<br />
| MSG-0065 || 1, 3<br />
|-<br />
| MSG-0066 || 1<br />
|-<br />
| NON-0005 || 1, 2<br />
|-<br />
|}<br />
<br />
<br />
=== Date and time ===<br />
<br />
Dates without time are transmitted as the number of milliseconds between 00:00 UTC on that date and 1970-01-01 00:00 UTC. Leap seconds are ignored, therefore this number is always an integer multiple of 8.64e7.<br />
<br />
Because ECMAScript Date objects have no way to explicitly specify a timezone for calculations, timezone correction must be performed on the server. Dates with time are transmitted as the number of milliseconds since 1970-01-01 00:00 UTC (again, ignoring leap seconds) plus the offset between the ''user's'' timezone and UTC at the time in question. (See the Java method java.util.TimeZone.getOffset(long)). Unless optional URL parameter <code>'''timezone'''</code> is present. Then dates with time are transmitted as the number of milliseconds since 1970-01-01 00:00 UTC (again, ignoring leap seconds) plus the offset between the ''specified'' timezone and UTC at the time in question.<br />
<br />
For some date and time values, especially timestamps, monotonicity is more important than the actual value. Such values are transmitted as the number of milliseconds since 1970-01-01 00:00 UTC, ignoring leap seconds and without timezone correction. If possible, a unique strictly monotonic increasing value should be used instead, as it avoids some race conditions described below.<br />
<br />
This specification refers to these three interpretations of the type Number as separate data types. The types are described in [[#DateAndTimeTypes | Date and time types]].<br />
<br />
{| id="DateAndTimeTypes" cellspacing="0" border="1"<br />
|+ align="bottom" | Date and time types<br />
! Type !! Time !! Timezone !! Comment<br />
|-<br />
| Date || No || UTC || Date without time.<br />
|-<br />
| Time || Yes || User || Date and time.<br />
|-<br />
| Timestamp || Yes || UTC || Timestamp or unique sequence number.<br />
|-<br />
|}<br />
<br />
=== Updates ===<br />
<br />
To allow efficient synchronization of a client with changes made by other clients and to detect conflicts, the server stores a timestamp of the last modification for each object. Whenever the server transmits data objects to the client, the response object described in [[#ResponseBody | Response body]] includes the field timestamp. This field contains a timestamp value which is computed as the maximum of the timestamps of all transmitted objects.<br />
<br />
When requesting updates to a previously retrieved set of objects, the client sends the last timestamp which belongs to that set of objects. The response contains all updates with timestamps greater than the one specified by the client. The field timestamp of the response contains the new maximum timestamp value.<br />
<br />
If multiple different objects may have the same timestamp values, then a race condition exists when an update is processed between two such objects being modified. The first, already modified object will be included in the update response and its timestamp will be the maximum timestamp value sent in the timestamp field of the response. If the second object is modified later but gets the same timestamp, the client will never see the update to that object because the next update request from the client supplies the same timestamp value, but only modifications with greater timestamp values are returned.<br />
<br />
If unique sequence numbers can't be used as timestamps, then the risk of the race condition can be at least minimized by storing timestamps in the most precise format and/or limiting update results to changes with timestamp values which are measurably smaller than the current timestamp value.<br />
<br />
=== Editing ===<br />
<br />
Editing objects is performed one object at a time. There may be multiple objects being edited by the same client simulataneously, but this is achieved by repeating the steps required for editing a single object. There is no batch edit or upload command.<br />
<br />
To edit an object, a client first requests the entire object from the server. The server response contains the timestamp field described in the previous section. For in-place editing inside a view of multiple objects, where only already retrieved fields can be changed, retrieving the entire object is not necessary, and the last timestamp of the view is used as the timestamp of each object in it.<br />
<br />
When sending the modified object back to the server, only modified fields need to be included in the sent object. The request also includes the timestamp of the edited object. The timestamp is used by the server to ensure that the object was not edited by another client in the meantime. If the current timestamp of the object is greater than the timestamp supplied by the client, then a conflict is detected and the field error is set in the response. Otherwise, the object gets a new timestamp and the response to the client is empty.<br />
<br />
If the client displays the edited object in a view together with other objects, then the client will need to perform an update of that view immediately after successfully uploading an edited object.<br />
<br />
=== File uploads ===<br />
<br />
File uploads are made by sending a POST request that submits both the file and the needed fields as parts of a request of content-type “multipart/form-data” or “multipart/mixed”. The file metadata are stored in a form field “file” (much like an <input type=”file” name=”file” /> would do). In general a call that allows file uploads via POST will have a corresponding call using PUT to send object data. The JSON-encoded object-data that is send as the body of a corresponding PUT call is, when performed as a POST with file uploads, put into the request parameter “json”.<br />
<br />
Since the upload is performed directly by the browser and is not an Ajax call, the normal callback mechanism for asynchronous Javascript calls cannot be used to obtain the result. For this reason the server responds to these POST calls with a complete HTML page that performs the callback and should not be displayed to the user. The HTML response is functionally equivalent to:<br />
<br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html><br />
<head><br />
<META http-equiv="Content-Type" content=\"text/html; charset=UTF-8\"><br />
<script type="text/javascript"><br />
(parent["callback_<b>action</b>"] || window.opener && window.opener["callback_<b>action</b>"])<br />
(<b>{json}</b>)<br />
</script><br />
</head><br />
</html><br />
<br />
The placeholders <code>{json}</code> is replaced by the response with the timestamp that would be expected from the corresponding PUT method. The placeholder <code>action</code> is replaced by the value of the parameter <code>action</code> of the request (except for the import bundle, which is named "import" instead of the action name for legacy purposes). The content-type of the answer is <code>text/html</code>.<br />
<br />
Non-browser clients don't need to interpret HTML or JavaScript. The JSON data can be recognized by the outermost <code>({</code> and <code>})</code>, where the inner braces are part of the JSON value. For example, the regular expression <code>\((\{.*\})\)</code> captures the entire JSON value in its first capturing group.<br />
<br />
=== Documentation conventions ===<br />
<br />
The rest of this document describes all available requests for each module. A module usually supports several different requests, which are differentiated by the used HTTP method, URI path and supplied URI parameters. The description of each method generally contains the following elements:<br />
* the HTTP method followed by the request URI, inclusing the URI parameter action, which is used to differentiate methods,<br />
* a list of URI parameters which can or must be supplied by the client,<br />
* for PUT requests, content of the request body,<br />
* "Response with timestamp:"if the timestamp field is required in the response body or simply "Response:" if not,<br />
* content of the response payload, unless it is supposed to be empty.<br />
<br />
=== Common object data ===<br />
<br />
This table contains common fields which apply for any module's data type and is referenced throughout this document whenever a module's data type is described.<br />
<br />
{| id="CommonObjectData" cellspacing="0" border="1"<br />
|+ align="bottom" | Common object data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 1 || id || String || Object ID<br />
|-<br />
| 2 || created_by || String || User ID of the user who created this object.<br />
|-<br />
| 3 || modified_by || String || User ID of the user who last modified this object.<br />
|-<br />
| 4 || creation_date || Time || Date and time of creation.<br />
|-<br />
| 5 || last_modified || Time || Date and time of the last modification.<br />
|-<br />
| 20 || folder_id || String || Object ID of the parent folder.<br />
|-<br />
| 100 || categories || String || String containing comma separated the categories. Order is preserved. Changing the order counts as modification of the object. Not present in folder objects.<br />
|-<br />
| 101 || private_flag || Boolean || Overrides folder permissions in shared private folders: When true, this object is not visible to anyone except the owner. Not present in folder objects.<br />
|-<br />
| 102 || color_label || Number || Color number used by Outlook to label the object. The assignment of colors to numbers is arbitrary and specified by the client. The numbers are integer numbers between 0 and 10 (inclusive). Not present in folder objects.<br />
|-<br />
| 104 || number_of_attachments || Number || Number of attachments <br />
|-<br />
| 105 || lastModifiedOfNewestAttachmentUTC || Time || Date and time of the newest attachment written with UTC time zone.<br />
|}<br />
<br />
== Module "login" ==<br />
<br />
The login module is used to obtain a session from the user's login credentials. To understand the details of the different login methods, see the article titled "[[Login variations]]".<br />
<br />
=== Login ===<br />
<br />
POST <code>/ajax/login?action=login</code><br />
<br />
Parameters:<br />
* <code>name</code> – The login name.<br />
* <code>password</code> – The password.<br />
* <code>authId</code> (optional) – Identifier for tracing every single login request passed between different systems in a cluster. The value should be some token that is unique for every login request. This parameter must be given as URL parameter and not inside the body of the POST request.<br />
* <code>client</code> (optional) – Identifier of the client using the HTTP/JSON interface. This is for statistic evaluations what clients are used with Open-Xchange.<br />
* <code>version</code> (optional) – Used version of the HTTP/JSON interface client.<br />
* <code>clientIP</code> (optional) – IP address of the client host for that the session is created. If this parameter is not specified the IP address of the HTTP client doing this request is used.<br />
* <code>clientUserAgent</code> (optional) – Value of the User-Agent header of the client host for that the session is created. If this parameter is not specified the User-Agent of the current HTTP client doing this request is used.<br />
<br />
Response: A JSON object containing the session ID used for all subsequent requests. Additionally a random token is contained to be used for the Easy Login method.<br />
<br />
=== Form Login (since 6.20) ===<br />
<br />
POST <code>/ajax/login?action=formlogin</code><br />
<br />
This request implements a possible login to the web frontend by only using a simple HTML form. An example for such a form can be found in the backend's documentation folder (<code>/usr/share/doc/open-xchange-core</code>) under <code>examples/login.html</code>.<br />
<br />
Parameters:<br />
* <code>login</code> – The login name.<br />
* <code>password</code> – The password.<br />
* <code>authId</code> – Identifier for tracing every single login request passed between different systems in a cluster. The value should be some token that is unique for every login request. This parameter must be given as URL parameter and not inside the body of the POST request.<br />
* <code>client</code> – Identifier of the client using the HTTP/JSON interface. This is for statistic evaluations what clients are used with Open-Xchange. If the autologin request should work the client must be the same as the client sent by the UI in the normal login request.<br />
* <code>version</code> – Used version of the HTTP/JSON interface client.<br />
* <code>autologin</code> – True or false. True tells the UI to issue a store request for the session cookie. This store request is necessary if you want the autologin request not to fail.<br />
* <code>uiWebPath</code> (optional) – Defines another path on the web server where the UI is located. If this parameter is not defined the configured default of the backend is used.<br />
* <code>clientIP</code> (optional) – IP address of the client host for that the session is created. If this parameter is not specified the IP address of the HTTP client doing this request is used.<br />
* <code>clientUserAgent</code> (optional) – Value of the User-Agent header of the client host for that the session is created. If this parameter is not specified the User-Agent of the current HTTP client doing this request is used.<br />
<br />
Response: A redirect to the web UI. The URL of the web UI is either taken from the given parameter or from the configured default of the backend.<br />
<br />
For a complete description of the FormLogin-Process please see [[FormLogin|this documentation]]<br />
<br />
=== Token Login (since 7.0.1) ===<br />
<br />
POST <code>/ajax/login?action=tokenLogin</code><br />
<br />
This request allows every possible client to create a very short living session. This session can then be transferred to any other client preferably a browser entering then the normal web interface. Then the sessions life time will be extended equally to every other session.<br />
<br />
Compared to the login mechanism using the random token, this request is more secure because two tokens are used. One of these tokens is only known to the client and one is generated by the server. Only the combination of both tokens allows to use the session. The combination of both tokens must be done by the client creating the session.<br />
<br />
Parameters:<br />
* <code>login</code> – The login information.<br />
* <code>password</code> – The password.<br />
* <code>clientToken</code> – Client side identifier for accessing the session later. The value should be some token that is unique for every login request.<br />
* <code>authId</code> – Identifier for tracing every single login request passed between different systems in a cluster. The value should be some token that is unique for every login request. This parameter must be given as URL parameter and not inside the body of the POST request.<br />
* <code>client</code> – Identifier of the client using the HTTP/JSON interface. This is for statistic evaluations what clients are used with Open-Xchange. If the autologin request should work the client should be the same as the client sent by the UI in the normal login request. For security considerations it can become necessary to define here the correct client that will use the session.<br />
* <code>version</code> – Version of the HTTP/JSON interface client. Only for statistic evaluations.<br />
* <code>autologin</code> – True or false. True tells the UI to issue a store request for the session cookie. This store request is necessary if you want the autologin request not to fail. This must be enabled on the server and a client can test with the autologin request if it is enabled or not.<br />
* <code>uiWebPath</code> (optional) – Defines another path on the web server where the UI is located. If this parameter is not defined the configured default of the backend is used.<br />
* <code>clientIP</code> (optional) – IP address of the client host for that the session is created. If this parameter is not specified the IP address of the HTTP client doing this request is used. Currently the IP address may change when using the session with both tokens. This can be disabled in future releases for security considerations.<br />
* <code>clientUserAgent</code> (optional) – Value of the User-Agent header of the client host for that the session is created. If this parameter is not specified the User-Agent of the current HTTP client doing this request is used. Currently the User-Agent may change when using the session. This can be disabled in future releases for security considerations.<br />
<br />
<br />
Response: A redirect to the web UI. The URL of the web UI is either taken from the given parameter or from the configured default of the backend. This redirect will only contain the server side token. The client side token sent in the request must be appended by the client creating the session. The final URL must have the form <code style="white-space: nowrap"><var>redirect_URL</var>&amp;clientToken=<var>token</var></code>. Both tokens are necessary to use the session and both tokens must match. Otherwise the session is terminated.<br />
<br />
=== Tokens (since 7.0.1) ===<br />
<br />
POST <code>/ajax/login?action=tokens</code><br />
<br />
This request allows clients to access a session created with the [[#Token_Login_.28since_7.0.1.29 | tokenLogin]] request. When accessing the session its life time is extended equally to every other session.<br />
<br />
Parameters:<br />
* <code>serverToken</code> – Server side identifier for accessing the session. This identifier was created by the server and is contained in the tokenLogin response.<br />
* <code>clientToken</code> – Client side identifier for accessing the session. This identifier was created by the client and passed within the POST data of the tokenLogin request.<br />
* <code>client</code> – Identifier of the client using the HTTP/JSON interface. Currently this request allows to change the client identifier for the session. This eases creating the session because the identifier of the client using the session must not be known. For security considerations it can become necessary to drop this parameter.<br />
<br />
<br />
Response: A JSON object conform to the normal [[#ResponseBody | response body]] contrary to the JSON object of the normal login request. This JSON object contains the session identifier, the login, the identifier and the locale of the user.<br />
<br />
=== Logout ===<br />
<br />
GET <code>/ajax/login?action=logout</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
=== Refresh secret cookie (since 6.18.2) ===<br />
<br />
GET <code>/ajax/login?action=refreshSecret</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
=== Refresh auto-login cookie ===<br />
<br />
GET <code>/ajax/login?action=store</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
=== Redirect ===<br />
<br />
GET <code>/ajax/login;jsessionid=1157370816112.OX1?action=redirect</code><br />
<br />
'''SECURITY WARNING!''' Utilizing this request is '''INSECURE'''! This request allows to access a session with a single one time token. This one time token may be delivered to the wrong client if the protocol has an error or Apache or the load balancer make a mistake. This will cause a wrong user to be in a wrong session. '''IMMEDIATELY''' consider not to use this request anymore. You have been warned. Use instead the FormLogin that does not need to use the redirect request.<br />
<br />
Parameters:<br />
* <code>random</code> – A session random token to jump into the session. This random token is part of the login response. Only a very short configurable time after the login it is allowed to jump into the session with the random token.<br />
* <code>client</code> (optional) – The client can be defined here newly if it is not correct on the login request itself.<br />
* <code>store</code> (optional) – Tells the UI to do a store request after login to be able to use autologin request.<br />
* <code>uiWebPath</code> (optional) – The optional path on the webserver to the UI. If this parameter is not given the configured uiWebPath is used.<br />
<br />
=== Change IP ===<br />
<br />
The following request is especially for integration with systems located in the providers infrastructure. If those systems create a session with the following request the client host IP address in the session can be changed. The IP check for following requests will be done using this newly set client host IP address.<br />
<br />
POST <code>/ajax/login?action=changeip</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>clientIP</code> – New IP address of the client host for the current session.<br />
<br />
Response: A JSON object containing the string "1" as data attribute.<br />
<br />
=== Redeem Token (since 7.4.0)===<br />
<br />
POST <code>/ajax/login?action=redeemToken</code><br />
<br />
Parameters:<br />
* <code>token</code> – The token created with [[#Get_a_login_token | acquireToken]].<br />
* <code>authId</code> – Identifier for tracing every single login request passed between different systems in a cluster. The value should be some token that is unique for every login request. This parameter must be given as URL parameter and not inside the body of the POST request. <br />
* <code>client</code> – Identifier of the client using the HTTP/JSON interface. The client must identifier must be the same for each request after creating the login session. <br />
* <code>secret</code> – The value of the secret string for token logins. This is configured through the tokenlogin-secrets configuration file.<br />
<br />
Response: A JSON object containing the session ID used for all subsequent requests. Additionally a random token is contained to be used for the Easy Login method. If configured within tokenlogin-secrets configuration file even the user password will be returned.<br />
<br />
== Module "config" ==<br />
<br />
The config module is used to retrieve and set user-specific configuration. The configuration is stored in a tree. Each node of the tree has a name and a value. The values of leaf nodes are strings which store the actual configuration data. The values of inner nodes are defined recursively as objects with one field for each child node. The name and the value of each field is the name and the value of the corresponding child node, respectively.<br />
<br />
The namespace looks like the following:<br />
<br />
* <code>/ajax/config/</code><br />
** <code>gui</code> – A string containing GUI-specific settings (currently, it is a huge [[#Low_level_protocol | JSON]] object).<br />
** <code>fastgui</code> - A string containing GUI-specific settings. This is a JSON object that must be kept small for performance.<br />
** <code>context_id</code> - the unique identifier of the context (read-only, added 2008-01-28).<br />
** <code>cookielifetime</code> - the cookie life time in seconds or <code>-1</code> for session cookie (read-only, added 2010-11-16).<br />
** <code>identifier</code> – the unique identifier of the user (read-only).<br />
** <code>contact_id</code> – the unique identifier of the contact data of the user (read-only).<br />
** <code>language</code> – the configured language of the user.<br />
** <code>timezone</code> – the configured timezone of the user.<br />
** <code>availableTimeZones</code> – a JSON object containing all available time zones. The key is the time zone identifier and the value contains its name in users language. (read-only, added 2010-07-08/v6.18).<br />
** <code>calendarnotification</code> - send a mail notification for appointments (deprecated since 2008-12-11)<br />
** <code>tasknotification</code> - send a mail notification for tasks (deprecated since 2008-12-11)<br />
** <code>reloadTimes</code> - Selectable times for GUI reload<br />
** <code>serverVersion</code> - Version string of the server.<br />
** <code>currentTime</code> - User timezone specific long of the current server time.<br />
** <code>maxUploadIdleTimeout</code> - Timeout after that idle uploads are deleted.<br />
** <code>folder/</code> – the standard folder of the user<br />
*** <code>tasks</code> – the standard task folder (read-only)<br />
*** <code>calendar</code> – the standard calendar folder (read-only)<br />
*** <code>contacts</code> – the standard contacts folder (read-only)<br />
*** <code>infostore</code> – the private infostore folder (read-only, since v6.20.1)<br />
*** <code>eas</code> – whether EAS folder selection is enabled (read-only)<br />
** <code>mail/</code> – settings for the email module (deprecated 2008-04-29)<br />
*** <code>addresses</code> – all email addresses of the user including the primary address (read-only, deprecated 2008-04-29)<br />
*** <code>defaultaddress</code> – primary email address of the user (read-only, deprecated 2008-04-29)<br />
*** <code>sendaddress</code> – one email address out of the addresses list that are email sent with. (deprecated 2008-04-29)<br />
*** <code>folder/</code> – the standard email folders (read-only, deprecated 2008-04-29)<br />
**** <code>inbox</code> – identifier of the folder that gets all incoming mails (read-only, deprecated 2008-04-29)<br />
**** <code>drafts</code> – identifier of the folder with the mail drafts (read-only, deprecated 2008-04-29)<br />
**** <code>trash</code> – identifier of the folder with the deleted mails (read-only, deprecated 2008-04-29)<br />
**** <code>spam</code> – identifier of the folder with the spam mails (read-only, deprecated 2008-04-29)<br />
**** <code>sent</code> – identifier of the folder with the sent mails (read-only, deprecated 2008-04-29)<br />
*** <code>htmlinline</code> – activate inlining of HTML attachments. (deprecated 2008-04-29)<br />
*** <code>colorquote</code> – color quoted lines. (deprecated 2008-04-29)<br />
*** <code>emoticons</code> – display emoticons as graphics. (deprecated 2008-04-29)<br />
*** <code>harddelete</code> – delete emails at once. (deprecated 2008-04-29)<br />
*** <code>inlineforward</code> – forward messages as inline or attachment. (deprecated 2008-04-29)<br />
*** <code>vcard</code> – attach vcard when sending mails. (deprecated 2008-04-29)<br />
*** <code>notifyonreadack</code> – notify on read acknowledgement. (deprecated 2008-04-29)<br />
*** <code>msgpreview</code> – show a message preview. (deprecated 2008-04-29)<br />
*** <code>ignorereplytext</code> (deprecated 2008-04-29)<br />
*** <code>nocopytosent</code> – don't put a copy to the sent folder when sending mails. (deprecated 2008-04-29)<br />
*** <code>spambutton</code> - Spam Button should be displayed in GUI or not. (deprecated 2008-04-29)<br />
** <code>participants</code><br />
*** <code>autoSearch</code> - If a search for all users, groups and resources when participant selection dialog is opened. (read-only, added 2008-10-09/SP5)<br />
*** <code>maximumNumberParticipants</code> – Defines the maximum number of participants for appointments and tasks. (read-only, added 2008-10-20/SP5)<br />
*** <code>showWithoutEmail</code> - If external participants without email should be shown.<br />
*** <code>showDialog</code> – Enables participant selection dialog for appointments and tasks. (read-only, added 2008-04-30/SP4)<br />
** <code>availableModules</code> – Contains a JSON array listing all enabled modules for a user. GUI loads Plugins through this list. To get your plugin listed here, create a subtree below <code>modules/</code> without a <code>module</code> subelement or with a subelement containing <code>true</code> (read-only, added 2008-02-25)<br />
** <code>minimumSearchCharacters</code> – Minimum number of characters a search pattern must have to prevent large responses and slow queries. (read-only, added 2008-10-20/SP5)<br />
** <code>modules</code><br />
*** <code>portal</code><br />
**** <code>gui</code> GUI settings for portal module<br />
**** <code>module</code><br />
*** <code>mail</code><br />
**** <code>addresses</code> – all email addresses of the user including the primary address (read-only, added 2008-02-25)<br />
**** <code>appendmailtext</code> – (added 2008-02-25)<br />
**** <code>allowhtmlimages</code> – Alters default setting whether external images contained in HTML content are allowed or not (added 2008-05-27)<br />
**** <code>colorquoted</code> – color quoted lines (added 2008-02-25)<br />
**** <code>contactCollectFolder</code> – contact folder id to save mail addresses from sent mails (added 2008-10-16)<br />
**** <code>contactCollectEnabled</code> – switch contact collection on/off (added 2008-10-16)<br />
**** <code>contactCollectOnMailAccess</code> – enables/disables contact collection for incoming mails. Default is true. (added 2009-09-24)<br />
**** <code>contactCollectOnMailTransport</code> – enables/disables contact collection for outgoing mails. Default is true. (added 2009-09-24)<br />
**** <code>defaultaddress</code> – primary email address of the user (read-only, added 2008-02-25)<br />
**** <code>deletemail</code> – delete emails or move to trash (added 2008-02-25)<br />
**** <code>emoticons</code> – display emoticons as graphics (added 2008-02-25)<br />
**** <code>defaultFolder</code><br />
***** <code>drafts</code> – identifier of the folder with the mail drafts (read-only, added 2008-02-25)<br />
***** <code>inbox</code> – identifier of the folder that gets all incoming mails (read-only, added 2008-02-25)<br />
***** <code>sent</code> – identifier of the folder with the sent mails (read-only, added 2008-02-25)<br />
***** <code>spam</code> – identifier of the folder with the spam mails (read-only, added 2008-02-25)<br />
***** <code>trash</code> – identifier of the folder with the deleted mails (read-only, added 2008-02-25)<br />
**** <code>forwardmessage</code> – forward messages as inline or attachment (added 2008-02-25)<br />
**** <code>gui</code> GUI settings for mail module<br />
**** <code>inlineattachments</code> – activate inlining of HTML attachments (added 2008-02-25)<br />
**** <code>linewrap</code> – (added 2008-02-25)<br />
**** <code>module</code> – if mail module is enabled or not (added 2008-02-25)<br />
**** <code>phishingheaders</code> – header(s) identifying phishing headers (added 2008-05-27)<br />
**** <code>replyallcc</code> – put all recipients on reply all into CC (added 2008-12-16/SP5)<br />
**** <code>sendaddress</code> – one email address out of the addresses list that are email sent with (added 2008-02-25)<br />
**** <code>spambutton</code> – Spam Button should be displayed in GUI or not (added 2008-02-25)<br />
**** <code>vcard</code> – attach vcard when sending mails (added 2008-02-25)<br />
*** <code>calendar</code><br />
**** <code>calendar_conflict</code><br />
**** <code>calendar_freebusy</code><br />
**** <code>calendar_teamview</code><br />
**** <code>gui</code> GUI settings for the calendar module<br />
**** <code>module</code><br />
**** <code>notifyNewModifiedDeleted</code> receive mail notification for new, modified or deleted appointments (added 2008-12-11/SP5)<br />
**** <code>notifyAcceptedDeclinedAsCreator</code> receive mail notification for accepted or declined appointments created by the user (added 2008-12-11/SP5)<br />
**** <code>notifyAcceptedDeclinedAsParticipant</code> receive mail notification for accepted or declined appointments that the user participates (added 2008-12-11/SP5)<br />
**** <code>defaultStatusPrivate</code> Default status for new appointments in private folders, where the user is participant. This does not affect appointments created by this user, which always have the status "accepted". The status are described in [[#UserParticipantObject | User participant object]]. Default is 0:none (added 2009-07-20/6.12)<br />
**** <code>defaultStatusPublic</code> Default status for new appointments in public folders, where the user is participant. This does not affect appointments created by this user, which always have the status "accepted". The status are described in [[#UserParticipantObject | User participant object]]. Default is 0:none (added 2009-07-20/6.12)<br />
*** <code>contacts</code><br />
**** <code>gui</code> GUI settings for the contacts module<br />
**** <code>mailAddressAutoSearch</code> – Define if a search is triggered when the recipient selection dialog is opened or the folder is changed. (read-only, added 2008-10-20/SP5)<br />
**** <code>module</code> True if the contact module is enabled for the current user, false otherwise.<br />
**** <code>singleFolderSearch</code> – True if the current user is allowed to search for contacts only in a single folder. False if contact searches across all folders are allowed. (read-only, added 2009-02-04/SP5 U1)<br />
**** <code>characterSearch</code> – True if the side bar for searching for contacts by a start letter should be displayed. False if the side bar should be hidden. (read-only, added 2009-05-29/6.10)<br />
**** <code>allFoldersForAutoComplete</code> – true if an auto complete search may omit the folder identifier array and search for contacts in all readable folders. This is configured through the contact.properties configuration file. (read-only, added 2010-07-22/v6.18.0)<br />
*** <code>tasks</code><br />
**** <code>gui</code> GUI settings for the tasks module<br />
**** <code>module</code><br />
**** <code>delegate_tasks</code><br />
**** <code>notifyNewModifiedDeleted</code> receive mail notification for new, modified or deleted tasks (added 2008-12-11/SP5)<br />
**** <code>notifyAcceptedDeclinedAsCreator</code> receive mail notification for accepted or declined tasks created by the user (added 2008-12-11/SP5)<br />
**** <code>notifyAcceptedDeclinedAsParticipant</code> receive mail notification for accepted or declined taks that the user participates (added 2008-12-11/SP5)<br />
*** <code>infostore</code><br />
**** <code>gui</code> GUI settings for the infostore module<br />
**** <code>folder</code> – the standard infostore folders (read-only, since 7.6.0)<br />
***** <code>trash</code> – identifier of the default infostore trash folder (read-only, since 7.6.0)<br />
***** <code>pictures</code> – identifier of the default infostore pictures folder (read-only, since 7.8.0)<br />
***** <code>documents</code> – identifier of the default infostore documents folder (read-only, since 7.8.0)<br />
***** <code>music</code> – identifier of the default infostore music folder (read-only, since 7.8.0)<br />
***** <code>videos</code> – identifier of the default infostore videos folder (read-only, since 7.8.0)<br />
***** <code>templates</code> – identifier of the default infostore templates folder (read-only, since 7.8.0)<br />
**** <code>module</code><br />
*** <code>interfaces</code><br />
**** <code>ical</code><br />
**** <code>vcard</code><br />
**** <code>syncml</code><br />
*** <code>folder</code><br />
**** <code>gui</code> UI settings for the folder tree<br />
**** <code>public_folders</code><br />
**** <code>read_create_shared_folders</code><br />
**** <code>tree</code> – Selected folder tree, the user wants to use. Currents trees are 0 for the known OX folder tree and 1 for the new virtual folder tree. (added 2010-04-09/6.18)<br />
*** <code>com.openexchange.extras</code><br />
**** <code>module</code> – Extras link in the configuration (read only, added 2008-04-29)<br />
*** <code>com.openexchange.user.passwordchange</code><br />
**** <code>module</code> – Will load Plug-In which allows to change the Password within the users configuration (read only, added 2008-07-09)<br />
*** <code>com.openexchange.user.personaldata</code><br />
**** <code>module</code> – Will load Plug-In which allows to edit personal contact information within the users configuration (read only, added 2008-07-09)<br />
*** <code>com.openexchange.group</code><br />
**** <code>enabled</code> – Specifies whether the user is allowed to edit groups and loads the corresponding Plug-In. (read only, added 2008-08-08)<br />
*** <code>com.openexchange.resource</code><br />
**** <code>enabled</code> – Specifies whether the user is allowed to edit resources and loads the corresponding Plug-In. (read only, added 2008-08-08)<br />
*** <code>com.openexchange.publish</code><br />
**** <code>enabled</code> – Specifies whether the user is allowed to publish items. (read only, added 2009-05-27)<br />
*** <code>com.openexchange.subscribe</code><br />
**** <code>enabled</code> – Specifies whether the user is allowed to subscribe sources. (read only, added 2009-05-27)<br />
*** <code>olox20</code><br />
**** <code>active</code> – Tells the UI if the user is allowed to use the OXtender for Microsoft Outlook 2. (read only, added 2011-03-15/6.20)<br />
**** <code>module</code> – Is set to false to prevent the UI from trying to load a plugin. (read only, added 2011-03-15/6.20)<br />
***<code>com.openexchange.oxupdater</code><br />
****<code>module</code> – Is true if the OXUpdater package is installed and started. (read only, added 2011-06-01/6.20)<br />
****<code>active</code> – Is true if the user is allowed to download the OXUpdater. Otherwise it's false. (read only, added 2011-06-01/6.20)<br />
***<code>com.openexchange.passwordchange</code><br />
**** <code>showStrength</code> – Show a widget, which displays the current passwort Strength while entering. (default: false)<br />
**** <code>minLength</code> – The minimum length of an entered password. (default: 4)<br />
**** <code>maxLength</code> – The maximum length of an entered password. 0 for unlimited. (default: 0)<br />
**** <code>regexp</code> – Defines the class of allowed special characters as Regular Expression. (default: [^a-z0-9])<br />
**** <code>special</code> – Shows an example of allowed special characters to the user. Should be a subset of "regexp" in a human readable format. (default: $, _, or %) <br />
<br />
=== Get configuration data ===<br />
<br />
GET <code>/ajax/config/path</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: Value of the node specified by path.<br />
<br />
=== Set configuration data ===<br />
<br />
PUT <code>/ajax/config/path</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: The new value of the node specified by path.<br />
<br />
<br />
=== Get a property (since 7.6.2) ===<br />
<br />
GET <code>/ajax/config?action=get_property</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>name</code> – The name of the property to return.<br />
<br />
Response: A JSON response providing the property's name and its value; e.g.<br />
<code><br />
{<br />
"data": {<br />
"name": "com.openexchange.dummy.prop001",<br />
"value": "test1234"<br />
}<br />
}<br />
</code><br />
<br />
=== Set a property (since 7.6.2) ===<br />
<br />
Note: Only allowed for context administrator!<br />
<br />
PUT <code>/ajax/config?action=set_property</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>name</code> – The name of the property to set.<br />
<br />
Request body: A JSON object providing the value to set; e.g<br />
<code><br />
{"value":"test1237"}<br />
</code><br />
<br />
<br />
Response: A JSON response providing the property's name and its new value; e.g.<br />
<code><br />
{<br />
"data": {<br />
"name": "com.openexchange.dummy.prop001",<br />
"value": "test1237"<br />
}<br />
}<br />
</code><br />
<br />
== Module "folders" ==<br />
<br />
The folders module is used to access the OX folder structure.<br />
<br />
=== Special System Folders ===<br />
<br />
Folders with some kind of special.<br />
<br />
{| cellspacing="0" border="1"<br />
! ID !! Type !! Description<br />
|-<br />
| 6 || contacts || System Users<br />
|}<br />
<br />
=== Get root folders ===<br />
<br />
GET <code>/ajax/folders?action=root</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Response: An array with data for all folders at the root level of the folder structure. Each array element describes one folder and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="CommonFolderData" cellspacing="0" border="1"<br />
|+ align="bottom" | Common folder data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 1 || id || String || Object ID<br />
|-<br />
| 2 || created_by || String || User ID of the user who created this object.<br />
|-<br />
| 3 || modified_by || String || User ID of the user who last modified this object.<br />
|-<br />
| 4 || creation_date || Time || Date and time of creation.<br />
|-<br />
| 5 || last_modified || Time || Date and time of the last modification.<br />
|-<br />
| 6 || last_modified_utc || Timestamp || Timestamp of the last modification. Note that the type is Timestamp, not Time. See [[#Date and time]] for details. (added 2008-10-17, with SP5, temporary workaround)<br />
|-<br />
| 20 || folder_id || String || Object ID of the parent folder.<br />
|}<br />
<br />
{| id="DetailedFolderData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed folder data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 300 || title || String || Name of this folder.<br />
|-<br />
| 301 || module || String || Name of the module which implements this folder; e.g. "tasks", "calendar", "contacts", "infostore", or "mail"<br />
|-<br />
| 302 || type || Number || Type of folder:<br />
{| cellspacing="0" border="1"<br />
| 1 || private<br />
|-<br />
| 2 || public<br />
|-<br />
| 3 || shared<br />
|-<br />
| 5 || system folder<br />
|-<br />
| 7 || This type is no more in use (legacy type). Will be removed with a future update!<br />
|-<br />
| 16 || trash<br />
|-<br />
| 20 || pictures<br />
|-<br />
| 21 || documents<br />
|-<br />
| 22 || music<br />
|-<br />
| 23 || videos<br />
|-<br />
| 24 || templates<br />
|}<br />
|-<br />
| 304 || subfolders || Boolean || true if this folder has subfolders.<br />
|-<br />
| 305 || own_rights || Number or String || Permissions which apply to the current user, as described either in [[#PermissionFlags | Permission flags]] or in RFC 2086.<br />
|-<br />
| 306 || permissions || Array || Each element is an object described in [[#PermissionObject | Permission object]].<br />
|-<br />
| 307 || summary || String || Information about contained objects.<br />
|-<br />
| 308 || standard_folder || Boolean || Indicates whether or not folder is marked as a default folder (only OX folder)<br />
|-<br />
| 309 || total || Number || The number of objects in this Folder.<br />
|-<br />
| 310 || new || Number || The number of new objects in this Folder.<br />
|-<br />
| 311 || unread || Number || The number of unread objects in this Folder.<br />
|-<br />
| 312 || deleted || Number || The number of deleted objects in this Folder.<br />
|-<br />
| 313 || capabilities || Number || Bit mask containing information about mailing system capabilites, as described in [[#Capabilities | capabilities]].<br />
|-<br />
| 314 || subscribed || Boolean || Indicates whether this folder should appear in folder tree or not. '''Note:''' Standard folders cannot be unsubscribed.<br />
|-<br />
| 315 || subscr_subflds || Boolean || Indicates whether subfolders should appear in folder tree or not.<br />
|-<br />
| 316 || standard_folder_type || Number || Indicates the default folder type. Zero for non-default folder. See [[#DefaultTypes | Standard folder types]]<br />
|-<br />
| 317 || supported_capabilities || Array || Each element is a String identifying a supported folder capability as described in [[#SupportedCapabilities | supported capabilities]]. Only applicable for non-mail folders. Read Only, Since 7.4.0.<br />
|-<br />
| 3010 || com.openexchange.publish.publicationFlag || Boolean || Indicates whether this folder is published. Read Only, provided by the com.openexchange.publish plugin, since 6.14.<br />
|-<br />
| 3020 || com.openexchange.subscribe.subscriptionFlag || Boolean || Indicates whether this folder has subscriptions storing their content in this folder. Read Only, provided by the com.openexchange.subscribe plugin, since 6.14.<br />
|-<br />
| 3030 || com.openexchange.folderstorage.displayName || String || Provides the display of the folder's owner. Read Only, Since 6.20.<br />
|}<br />
<br />
<br />
<br />
<br />
{| id="PermissionFlags" cellspacing="0" border="1"<br />
|+ align="bottom" | Permission flags<br />
! Bits !! Value<br />
|-<br />
| 0-6 || Folder permissions:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || See the folder.<br />
|-<br />
| 2 || Create objects in the folder. '''Note''': '''Does not apply to folders of module ''system'''''.<br />
|-<br />
| 4 || Create subfolders.<br />
|-<br />
| 64 || All permissions. This is currently the same as "Create subfolders" but in the future additional permissions may be added that will be given to the user when using this value.<br />
|}<br />
The values are scalars and not bit sets. Any other than the described values should not be used. If they are used expect an exception from the backend. Every value automatically contains the access rights covered by lower values.<br>'''NOTE''': ''Create objects in the folder'' is not covered by ''Create subfolders'' if folder's module is ''system''.<br />
|-<br />
| 7-13 || Read permissions for objects in the folder:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || Read only own objects.<br />
|-<br />
| 2 || Read all objects.<br />
|-<br />
| 64 || All permissions. This is currently the same as "Read all objects" but in the future additional permissions may be added that will be given to the user when using this value.<br />
|}<br />
The values are scalars and not bit sets. Any other than the described values should not be used. If they are used expect an exception from the backend. Every value automatically contains the access rights covered by lower values.<br />
|-<br />
| 14-20 || Write permissions for objects in the folder:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || Modify only own objects.<br />
|-<br />
| 2 || Modify all objects.<br />
|-<br />
| 64 || All permissions. This is currently the same as "Modify all objects" but in the future additional permissions may be added that will be given to the user when using this value.<br />
|}<br />
The values are scalars and not bit sets. Any other than the described values should not be used. If they are used expect an exception from the backend. Every value automatically contains the access rights covered by lower values.<br />
|-<br />
| 21-27 || Delete permissions for objects in the folder:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || Delete only own objects.<br />
|-<br />
| 2 || Delete all objects.<br />
|-<br />
| 64 || All permissions. This is currently the same as "Delete all objects" but in the future additional permissions may be added that will be given to the user when using this value.<br />
|}<br />
The values are scalars and not bit sets. Any other than the described values should not be used. If they are used expect an exception from the backend. Every value automatically contains the access rights covered by lower values.<br />
|-<br />
| 28 || Admin flag:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || Every operation modifying the folder in some way requires this permission. This are e.g. changing the folder name, modifying the permissions, deleting or moving the folder.<br />
|}<br />
|}<br />
<br />
{| id="PermissionObject" cellspacing="0" border="1"<br />
|+ align="bottom" | Permission object<br />
! Name !! Type !! Value<br />
|-<br />
| bits || Number || For non-mail folders, a number as described in [[#PermissionFlags | Permission flags]].<br />
|-<br />
| rights || String || For mail folders, the rights string as defined in RFC 2086.<br />
|-<br />
| entity || Number || User ID of the user or group to which this permission applies (ignored for type "anonymous" or "guest").<br />
|-<br />
| group || Boolean || true if entity refers to a group, false if it refers to a user (ignored for type "anonymous" or "guest").<br />
|-<br />
| type || String || The recipient type, i.e. one of "guest", "anonymous" (required if no internal "entity" defined).<br />
|-<br />
| password || String || An additional secret / pin number an anonymous user needs to enter when accessing the share (for type "anonymous", optional) .<br />
|-<br />
| email_address || String || The e-mail address of the recipient (for type "guest").<br />
|-<br />
| display_name || String || The display name of the recipient (for type "guest", optional).<br />
|-<br />
| contact_id || String || The object identifier of the corresponding contact entry if the recipient was chosen from the address book (for type "guest", optional).<br />
|-<br />
| contact_folder || String || The folder identifier of the corresponding contact entry if the recipient was chosen from the address book (for type "guest", required if "contact_id" is set).<br />
|-<br />
| expiry_date || Time || The end date / expiration time after which the share link is no longer accessible (for type "guest" or "anonymous", optional).<br />
|}<br />
<br />
{| id="Capabilities" cellspacing="0" border="1"<br />
|+ align="bottom" | Capabilities<br />
! Bit !! Description<br />
|-<br />
| 0 || Mailing system supports permissions.<br />
|-<br />
| 1 || Mailing system supports ordering mails by their thread reference.<br />
|-<br />
| 2 || Mailing system supports quota restrictions.<br />
|-<br />
| 3 || Mailing system supports sorting.<br />
|-<br />
| 4 || Mailing system supports folder subscription.<br />
|}<br />
<br />
'''Note''': Capabilities describe the entire mailing system (mail account), not the specific folder in which they are transmitted. E.g. bit 4 of the capabilities on the user's inbox describes whether subscriptions are supported by the default account, even though the inbox itself cannot be unsubscribed because it's a standard folder.<br />
<br />
{| id="DefaultTypes" cellspacing="0" border="1"<br />
|+ align="bottom" | Standard Folder Types<br />
! Bit !! Description<br />
|-<br />
| 0 || No default folder.<br />
|-<br />
| 1 || Task.<br />
|-<br />
| 2 || Calendar.<br />
|-<br />
| 3 || Contact.<br />
|-<br />
| 7 || Inbox.<br />
|-<br />
| 8 || Infostore.<br />
|-<br />
| 9 || Drafts.<br />
|-<br />
| 10 || Sent.<br />
|-<br />
| 11 || Spam.<br />
|-<br />
| 12 || Trash.<br />
|}<br />
<br />
{| id="SupportedCapabilities" cellspacing="0" border="1"<br />
|+ align="bottom" | Supported Capabilities<br />
! Name !! Description<br />
|-<br />
| permissions || Folder storage supports permissions.<br />
|-<br />
| publication || Folder storage supports folder publication.<br />
|-<br />
| quota || Folder storage supports quota restrictions.<br />
|-<br />
| sort || Folder storage supports sorting.<br />
|-<br />
| subscription || Folder storage supports folder subscription.<br />
|}<br />
<br />
=== Get subfolders ===<br />
<br />
GET <code>/ajax/folders?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>parent</code> – Object ID of a folder, which is the parent folder of the requested folders.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
* <code>all</code> – Set to <code>1</code> to list even not subscribed folders.<br />
* <code>tree</code> – The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
* <code>errorOnDuplicateName</code> – An optional flag to enable or disable (default) check for duplicate folder names within returned folder response (since v6.20.1). If a duplicate folder name is detected, an appropriate error is returned as [[#ResponseBody | response]].<br />
<br />
Response with timestamp: An array with data for all folders, which have the folder with the requested object ID as parent. Each array element describes one folder and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get path ===<br />
<br />
GET <code>/ajax/folders?action=path</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of a folder.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Response with timestamp: An array with data for all parent nodes until root folder. Each array element describes one folder and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get updated folders ===<br />
<br />
GET <code>/ajax/folders?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>parent</code> – Object ID of a folder, which is the parent folder of the requested folders.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested folders.<br />
* <code>ignore</code> (optional) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Response with timestamp: An array with data for new, modified and deleted folders. New and modified folders are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted folders (should the <code>ignore</code> parameter be ever implemented) would be identified by their object IDs as plain strings, without being part of a nested array.<br />
<br />
=== Get a folder ===<br />
<br />
GET <code>/ajax/folders?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested folder.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Response with timestamp: An object containing all data of the requested folder. The fields of the object are listed in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]]. The field id is not present. Since OX access controls are folder-based, the folder object also defines the permissions for the objects it contains. The permissions for a given user or group are defined by the object described in [[#PermissionObject | Permission object]]. The format of the actual permissions depends on the type of the folder. The permissions of mail folders are transmitted as a rights string as defined in section 3 of RFC 2086. Permissions of all other folders are transmitted as a single nonnegative integer number. The permissions for any given action on the folder or on contained objects is defined by a group of bits in the binary representation of this number. Each group of bits is interpreted as a separate number. Zero always means "no permissions". Any other values add new permissions and always include the permissions of all lower values. The individual values are described in [[#PermissionFlags | Permission flags]].<br />
<br />
=== Update a folder ===<br />
<br />
PUT <code>/ajax/folders?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated folder.<br />
* <code>timestamp</code> – Timestamp of the updated folder. If the folder was modified after the specified timestamp, then the update must fail.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
* <code>cascadePermissions</code> – (Optional. Defaults to false) Flag to cascade permissions to all sub-folders. The user must have administrative permissions to all sub-folders subject to change. If one permission change fails, the entire operation fails. (Since 7.8.0)<br />
<br />
Request body: Folder object as described in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]]. Only modified fields are present.<br />
<br />
=== Create a folder ===<br />
<br />
PUT <code>/ajax/folders?action=new</code><br />
<br />
Parameters:<br />
* <code>folder_id</code> – The parent folder of the newly created folder<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Request body: Folder object as described in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]]. The field id should not be present.<br />
<br />
Provided that permission is granted to create a folder, its module is bound to the limitation, that the new folder's module must be equal to parent folder's module except that:<br />
* Parent folder is one of the system folders <code>private</code>, <code>public</code>, or <code>shared</code>. Below these folders task, calendar, and contact modules are permitted.<br />
* Parent folder's module is one of task, calendar, or contact. Below this kind of folders task, calendar, and contact modules are permitted.<br />
<br />
Response: Object ID of the newly created folder.<br />
<br />
=== Delete folders ===<br />
<br />
PUT <code>/ajax/folders?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – The optional timestamp of the last update of the deleted folders.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered. <br />
* <code>hardDelete</code> - Optional, defaults to \"false\". If set to \"true\", the folders are deleted permanently. Otherwise, and if the underlying storage supports a trash folder and the folders are not yet located below the trash folder, they are moved to the trash folder.<br />
<br />
Request body: An array with object IDs of the folders that shall be deleted.<br />
<br />
Response: An array with object IDs of folders that were '''NOT''' deleted. There may be a lot of different causes for a not deleted folder: A folder has been modified in the mean time, the user does not have the permission to delete it or those permissions have just been removed, the folder does not exist, etc.<br />
<br />
=== Clearing a folder's content ===<br />
PUT <code>/ajax/folders?action=clear</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Request body: A JSON array containing the folder ID(s) whose content should be cleared. '''NOTE:''' Although the requests offers to clear multiple folders at once it is recommended to clear only one folder per request since if any exception occurs<br />
(e.g. missing permissions) the complete request is going to be aborted.<br />
<br />
Response: A JSON array containing the IDs of folders that could not be cleared due to a concurrent modification. Meaning you receive an empty JSON array if everything worked well.<br />
<br />
=== Get all visible folder of a certain module (since v6.18.2) ===<br />
PUT <code>/ajax/folders?action=allVisible</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>tree</code> – The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>content_type</code> – The desired content type (either numbers or strings; e.g. "tasks", "calendar", "contacts", "mail")<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
<br />
Request body: None<br />
<br />
Response with timestamp: A JSON object containing three fields: "private", "public, and "shared". Each field is a JSON array with data for all folders. Each folder is itself described by an array.<br />
<br />
== Module "tasks" ==<br />
<br />
The tasks module is used to access task information.<br />
<br />
=== Get all tasks ===<br />
<br />
GET <code>/ajax/tasks?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for tasks are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response with timestamp: An array with task data. Each array element describes one task and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedTaskAndAppointmentData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed task and appointment data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 200 || title || String || Short description.<br />
|-<br />
| 201 || start_date || Date or Time || Inclusive start of the event as Date for tasks and whole day appointments and Time for normal appointments. For sequencies, this date must be part of the sequence, i. e. sequencies always start at this date. (deprecated for tasks since v7.6.1, replaced by start_time and full_time)<br />
|-<br />
| 202 || end_date || Date or Time || Exclusive end of the event as Date for tasks and whole day appointments and as Time for normal appointments. (deprecated for tasks since v7.6.1, replaced by end_time and full_time)<br />
|-<br />
| 203 || note || String || Long description.<br />
|-<br />
| 204 || alarm || Number or Time || Specifies when to notify the participants as the number of minutes before the start of the appointment (-1 for "no alarm"). For tasks, the Time value specifies the absolute time when the user should be notified.<br />
|-<br />
| 209 || recurrence_type || Number || Specifies the type of the recurrence for a task sequence:<br />
{| cellspacing="0" border="1"<br />
| 0 || none (single event)<br />
|-<br />
| 1 || daily<br />
|-<br />
| 2 || weekly<br />
|-<br />
| 3 || monthly<br />
|-<br />
| 4 || yearly<br />
|}<br />
|-<br />
| 212 || days || Number || Specifies which days of the week are part of a sequence. The value is a bitfield with bit 0 indicating sunday, bit 1 indicating monday and so on. May be present if recurrence_type > 1. If allowed but not present, the value defaults to 127 (all 7 days).<br />
|-<br />
| 213 || day_in_month || Number || Specifies which day of a month is part of the sequence. Counting starts with 1. If the field "days" is also present, only days selected by that field are counted. If the number is bigger than the number of available days, the last available day is selected. Present if and only if recurrence_type > 2.<br />
|-<br />
| 214 || month || Number || Month of the year in yearly sequencies. 0 represents January, 1 represents February and so on. Present if and only if recurrence_type = 4.<br />
|-<br />
| 215 || interval || Number || Specifies an integer multiplier to the interval specified by recurrence_type. Present if and only if recurrence_type > 0. Must be 1 if recurrence_type = 4.<br />
|-<br />
| 216 || until || Date || Inclusive end date of a sequence. May be present only if recurrence_type > 0. The sequence has no end date if recurrence_type > 0 and this field is not present. Note: since this is a Date, the entire day after the midnight specified by the value is included.<br />
|-<br />
| 217 || notification || Boolean || If true, all participants are notified of any changes to this object. This flag is valid for the current change only, i. e. it is not stored in the database and is never sent by the server to the client.<br />
|-<br />
| 220 || participants || Array || Each element identifies a participant, user, group or booked resource as described in [[#Participant | participant table]].<br />
|-<br />
| 221 || users || Array || Each element represents a participant as described in [[#UserParticipantObject | User participant object]]. User groups are resolved and are represented by their members. Any user can occur only once.<br />
|-<br />
| 222 || occurrences || Number || Specifies how often a recurrence should appear. May be present only if recurrence_type > 0.<br />
|-<br />
| 223 || uid || String || Can only be written when the object is created. Internal and external globally unique identifier of the appointment or task. Is used to recognize appointments within iCal files. If this attribute is not written it contains an automatic generated UUID.<br />
|-<br />
| 224 || organizer || String || Contains the email address of the appointment organizer which is not necessarily an internal user. Not implemented for tasks.<br />
|-<br />
| 225 || sequence || Number || iCal sequence number. Not implemented for tasks. Must be incremented on update. Will be incremented by the server, if not set.<br />
|-<br />
| 226 || confirmations || Array || Each element represents a confirming participant as described in [[#ConfirmingParticipant | confirming participant]]. This can be internal and external user. Not implemented for tasks.<br />
|-<br />
| 227 || organizerId || Number || Contains the userIId of the appointment organizer if it is an internal user. Not implemented for tasks. (Introduced with 6.20.1)<br />
|-<br />
| 228 || principal || String || Contains the email address of the appointment principal which is not necessarily an internal user. Not implemented for tasks. (Introduced with 6.20.1)<br />
|-<br />
| 229 || principalId || Number || Contains the userIId of the appointment principal if it is an internal user. Not implemented for tasks. (Introduced with 6.20.1)<br />
|-<br />
| 401 || full_time || Boolean || True if the event is a whole day appointment or task, false otherwise.<br />
|}<br />
<br />
{| id="Participant" cellspacing="0" border="1"<br />
|+ align="bottom" | Participant identifier<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || User ID<br />
|-<br />
| type || Number || Type of participant:<br />
{|<br />
| 1 || user<br />
|-<br />
| 2 || user group<br />
|-<br />
| 3 || resource<br />
|-<br />
| 4 || resource group<br />
|-<br />
| 5 || external user<br />
|}<br />
|-<br />
| mail || String || mail address of an external participant<br />
|}<br />
<br />
{| id="UserParticipantObject" cellspacing="0" border="1"<br />
|+ align="bottom" | User participant object<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || User ID. Confirming for other users only works for appointments and not for tasks.<br />
|-<br />
| display_name || String || Displayable name of the participant.<br />
|-<br />
| confirmation || Number ||<br />
{| cellspacing="0" border="1"<br />
| 0 || none<br />
|-<br />
| 1 || accepted<br />
|-<br />
| 2 || declined<br />
|-<br />
| 3 || tentative<br />
|}<br />
|-<br />
| confirmmessage || String || Confirm Message of the participant<br />
|}<br />
<br />
{| id="ConfirmingParticipant" cellspacing="0" border="1"<br />
|+ align="bottom" | Confirming participant<br />
! Name !! Type !! Value<br />
|-<br />
| type || Number || Type of participant:<br />
{|<br />
| 1 || user<br />
|-<br />
| 5 || external user<br />
|}<br />
|-<br />
| mail || String || email address of external participant<br />
|-<br />
| display_name || String || display name of external participant<br />
|-<br />
| status || Number ||<br />
{|<br />
| 0 || none<br />
|-<br />
| 1 || accepted<br />
|-<br />
| 2 || declined<br />
|-<br />
| 3 || tentative<br />
|}<br />
|-<br />
| message || String || Confirm Message of the participant<br />
|}<br />
<br />
{| id="DetailedTaskData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed task data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 300 || status || Number || Status of the task:<br />
{| cellspacing="0" border="1"<br />
| 1 || not started<br />
|-<br />
| 2 || in progress<br />
|-<br />
| 3 || done<br />
|-<br />
| 4 || waiting<br />
|-<br />
| 5 || deferred<br />
|}<br />
|-<br />
| 301 || percent_completed || Number || How much of the task is completed. An integer number between 0 and 100.<br />
|-<br />
| 302 || actual_costs|| Number || A monetary attribute to store actual costs of a task. Allowed values must be in the range -9999999999.99 and 9999999999.99.<br />
|-<br />
| 303 || actual_duration<br />
|-<br />
| 304 || after_complete || Date || Deprecated. Only present in AJAX interface. Value will not be stored on OX server.<br />
|-<br />
| 305 || billing_information<br />
|-<br />
| 307 || target_costs|| Number || A monetary attribute to store target costs of a task. Allowed values must be in the range -9999999999.99 and 9999999999.99.<br />
|-<br />
| 308 || target_duration<br />
|-<br />
| 309 || priority || Number || 1 = LOW, 2 = MEDIUM, 3 = HIGH<br />
|-<br />
| 312 || currency<br />
|-<br />
| 313 || trip_meter<br />
|-<br />
| 314 || companies<br />
|-<br />
| 315 || date_completed<br />
|-<br />
| 316 || start_time || Date or Time || Inclusive start as Date for whole day tasks and Time for normal tasks. <br />
|-<br />
| 317 || end_time || Date or Time || Exclusive end as Date for whole day tasks and as Time for normal tasks.<br />
|}<br />
<br />
=== Get a list of tasks ===<br />
<br />
PUT <code>/ajax/tasks?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for tasks are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]].<br />
<br />
Request body: An array of with object IDs of requested tasks.<br />
<br />
Response with timestamp: An array with task data. Each array element describes one task and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get updated tasks ===<br />
<br />
GET <code>/ajax/tasks?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for tasks are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested tasks.<br />
* <code>ignore</code> – Which kinds of updates should be ignored. Omit this parameter or set it to "deleted" to not have deleted tasks identifier in the response. Set this parameter to "false" and the response contains deleted tasks identifier.<br />
<br />
Response with timestamp: An array with new, modified and deleted tasks. New and modified tasks are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted tasks would be identified by their object IDs as plain strings, without being part of a nested array.<br />
<br />
=== Get a task ===<br />
<br />
GET <code>/ajax/tasks?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested task.<br />
* <code>folder</code> – Object ID of the task's folder.<br />
<br />
Response with timestamp: An object containing all data of the requested task. The fields of the object are listed in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]]. The field id is not included.<br />
<br />
=== Update a task ===<br />
<br />
PUT <code>/ajax/tasks?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Folder Identifier through that the task is accessed. This is necessary for checking the permissions.<br />
* <code>id</code> – Object ID of the updated task.<br />
* <code>timestamp</code> – Timestamp of the updated task. If the task was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: Task object as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]]. Only modified fields are present.<br />
<br />
=== Create a task ===<br />
<br />
PUT <code>/ajax/tasks?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Task object as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]]. The field id is not present.<br />
<br />
Response: A json objekt with attribute <code>id</code> of the newly created task.<br />
<br />
=== Delete task ===<br />
<br />
PUT <code>/ajax/tasks?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted tasks.<br />
<br />
Request body: An object in the field “id” and “folder”.<br />
<br />
Response: An array with object IDs of tasks which were modified after the specified timestamp and were therefore not deleted.<br />
<br />
=== Delete tasks (since v6.22) ===<br />
<br />
PUT <code>/ajax/tasks?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted tasks.<br />
<br />
Request body: An array of objects with the fields “id” and “folder”.<br />
<br />
Response: An array with object IDs of tasks which were modified after the specified timestamp and were therefore not deleted.<br />
<br />
=== Confirm task ===<br />
<br />
PUT <code>/ajax/tasks?action=confirm</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the to confirm task.<br />
* <code>folder</code> – ID of the folder through that the task is accessed.<br />
* <code>timestamp</code> – Timestamp of the last update of the to confirm task.<br />
<br />
Request body: An object with the fields "confirmation" and "confirmmessage" as described in [[#UserParticipantObject | User participant object]].<br />
<br />
Response: Nothing, except the standard response object with empty data, the timestamp of the confirmed and thereby updated task, and maybe errors.<br />
<br />
=== Search for tasks ===<br />
<br />
PUT <code>/ajax/tasks?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified , then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Request Body: A JSON object with attributes described in [[#SearchTasks | Search tasks]]<br />
<br />
{| id="SearchTasks" cellspacing="0" border="1"<br />
|+ align="bottom" | Search tasks<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find tasks. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|-<br />
| folder || Number || (optional) Defines the folder to search for tasks in. If this is omitted in all task folders will be searched.<br />
|-<br />
| start || Date or Time || (optional) Inclusive start date for a time range the tasks should end in. If start is omitted end is ignored.<br />
|-<br />
| end || Date or Time || (optional) Exclusive end date for a time range the tasks should end in. If this parameter is omitted the time range has an open end.<br />
|}<br />
<br />
Response with timestamp: An array with matching tasks. Tasks are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
== Module "contacts" ==<br />
<br />
The contacts module is used to access contact information.<br />
<br />
=== Get all contacts ===<br />
<br />
GET <code>/ajax/contacts?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried (optional from 6.22.2 on: If not set, the contents of all visible folders are used instead).<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for contacts are defined in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (preliminary, since 6.20) – allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedContactData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed contact data<br />
! ID !! Displayed name !! Name !! Type !! Value<br />
|-<br />
| 223 || || uid || String || Can only be written when the object is created. Internal and external globally unique identifier of the contact. Is used to recognize contacts within vCard files. If this attribute is not written it contains an automatic generated UUID.<br />
|-<br />
| 500 || Display name || display_name || String<br />
|-<br />
| 501 || Given name || first_name || String || First name.<br />
|-<br />
| 502 || Sur name || last_name || String || Last name.<br />
|-<br />
| 503 || Middle name || second_name || String<br />
|-<br />
| 504 || Suffix || suffix || String<br />
|-<br />
| 505 || Title || title || String<br />
|-<br />
| 506 || Street home || street_home || String<br />
|-<br />
| 507 || Postal code home || postal_code_home || String<br />
|-<br />
| 508 || City home || city_home || String<br />
|-<br />
| 509 || State home || state_home || String<br />
|-<br />
| 510 || Country home || country_home || String<br />
|-<br />
| 511 || Birthday || birthday || Date<br />
|-<br />
| 512 || Martial status || marital_status || String<br />
|-<br />
| 513 || Number of children || number_of_children || String<br />
|-<br />
| 514 || Profession || profession || String<br />
|-<br />
| 515 || Nickname || nickname || String<br />
|-<br />
| 516 || Spouse name || spouse_name || String<br />
|-<br />
| 517 || Anniversay || anniversary || Date<br />
|-<br />
| 518 || Note || note || String<br />
|-<br />
| 519 || Department || department || String<br />
|-<br />
| 520 || Position || position || String<br />
|-<br />
| 521 || Employee type || employee_type || String<br />
|-<br />
| 522 || Room number || room_number || String<br />
|-<br />
| 523 || Street business || street_business || String<br />
|-<br />
| 524 || || internal_userid || Number<br />
|-<br />
| 525 || Postal code business || postal_code_business || String<br />
|-<br />
| 526 || City business || city_business || String<br />
|-<br />
| 527 || State business || state_business || String<br />
|-<br />
| 528 || Country business || country_business || String<br />
|-<br />
| 529 || Number of employee || number_of_employees || String<br />
|-<br />
| 530 || Sales volume || sales_volume || String<br />
|-<br />
| 531 || Tax id || tax_id || String<br />
|-<br />
| 532 || Commercial register || commercial_register || String<br />
|-<br />
| 533 || Branches || branches || String<br />
|-<br />
| 534 || Business category || business_category || String<br />
|-<br />
| 535 || Info || info || String<br />
|-<br />
| 536 || Manager's name || manager_name || String<br />
|-<br />
| 537 || Assistant's name || assistant_name || String<br />
|-<br />
| 538 || Street other || street_other || String<br />
|-<br />
| 539 || City other || city_other || String<br />
|-<br />
| 540 || Postal code other || postal_code_other || String<br />
|-<br />
| 541 || Country other || country_other || String<br />
|-<br />
| 542 || Telephone business 1 || telephone_business1 || String<br />
|-<br />
| 543 || Telephone business 2 || telephone_business2 || String<br />
|-<br />
| 544 || FAX business || fax_business || String<br />
|-<br />
| 545 || Telephone callback || telephone_callback || String<br />
|-<br />
| 546 || Telephone car || telephone_car || String<br />
|-<br />
| 547 || Telephone company || telephone_company || String<br />
|-<br />
| 548 || Telephone home 1 || telephone_home1 || String<br />
|-<br />
| 549 || Telephone home 2 || telephone_home2 || String<br />
|-<br />
| 550 || FAX home || fax_home || String<br />
|-<br />
| 551 || Cellular telephone 1 || cellular_telephone1 || String<br />
|-<br />
| 552 || Cellular telephone 2 || cellular_telephone2 || String<br />
|-<br />
| 553 || Telephone other || telephone_other || String<br />
|-<br />
| 554 || FAX other || fax_other || String<br />
|-<br />
| 555 || Email 1 || email1 || String<br />
|-<br />
| 556 || Email 2 || email2 || String<br />
|-<br />
| 557 || Email 3 || email3 || String<br />
|-<br />
| 558 || URL || url || String<br />
|-<br />
| 559 || Telephone ISDN || telephone_isdn || String<br />
|-<br />
| 560 || Telephone pager || telephone_pager || String<br />
|-<br />
| 561 || Telephone primary || telephone_primary || String<br />
|-<br />
| 562 || Telephone radio || telephone_radio || String<br />
|-<br />
| 563 || Telephone telex || telephone_telex || String<br />
|-<br />
| 564 || Telephone TTY/TDD || telephone_ttytdd || String<br />
|-<br />
| 565 || Instantmessenger 1 || instant_messenger1 || String<br />
|-<br />
| 566 || Instantmessenger 2 || instant_messenger2 || String<br />
|-<br />
| 567 || Telephone IP || telephone_ip || String<br />
|-<br />
| 568 || Telephone assostant || telephone_assistant || String<br />
|-<br />
| 569 || Company || company || String<br />
|-<br />
| 570 || || image1 || String<br />
|-<br />
| 571 || Dynamic Field 1 || userfield01 || String<br />
|-<br />
| 572 || Dynamic Field 2 || userfield02 || String<br />
|-<br />
| 573 || Dynamic Field 3 || userfield03 || String<br />
|-<br />
| 574 || Dynamic Field 4 || userfield04 || String<br />
|-<br />
| 575 || Dynamic Field 5 || userfield05 || String<br />
|-<br />
| 576 || Dynamic Field 6 || userfield06 || String<br />
|-<br />
| 577 || Dynamic Field 7 || userfield07 || String<br />
|-<br />
| 578 || Dynamic Field 8 || userfield08 || String<br />
|-<br />
| 579 || Dynamic Field 9 || userfield09 || String<br />
|-<br />
| 580 || Dynamic Field 10 || userfield10 || String<br />
|-<br />
| 581 || Dynamic Field 11 || userfield11 || String<br />
|-<br />
| 582 || Dynamic Field 12 || userfield12 || String<br />
|-<br />
| 583 || Dynamic Field 13 || userfield13 || String<br />
|-<br />
| 584 || Dynamic Field 14 || userfield14 || String<br />
|-<br />
| 585 || Dynamic Field 15 || userfield15 || String<br />
|-<br />
| 586 || Dynamic Field 16 || userfield16 || String<br />
|-<br />
| 587 || Dynamic Field 17 || userfield17 || String<br />
|-<br />
| 588 || Dynamic Field 18 || userfield18 || String<br />
|-<br />
| 589 || Dynamic Field 19 || userfield19 || String<br />
|-<br />
| 590 || Dynamic Field 20 || userfield20 || String || Contains a UUID if one was assigned (after 6.18.2)<br />
|-<br />
| 592 || || distribution_list || Array || If this contact is a distribution list, then this field is an array of objects. Each object describes a member of the list as defined in [[#DistributionListMember | Distribution list member]].<br />
|-<br />
| 594 || Number of distributionlists || number_of_distribution_list || Number<br />
|-<br />
| 596 || || number_of_images || Number<br />
|-<br />
| 597 || || image_last_modified || Timestamp<br />
|-<br />
| 598 || State other || state_other || String<br />
|-<br />
| 599 || || file_as || String<br />
|-<br />
| 601 || || image1_content_type || String<br />
|-<br />
| 602 || || mark_as_distributionlist || Boolean<br />
|-<br />
| 605 || Default address || default_address || Number<br />
|-<br />
| 606 || || image1_url || String<br />
|-<br />
| 608 || || useCount || Number || In case of sorting purposes the column 609 is also available, which places global address book contacts at the beginning of the result. If 609 is used, the order direction (ASC, DESC) is ignored.<br />
|-<br />
| 610 || || yomiFirstName || String || Kana based representation for the First Name. Commonly used in japanese environments for searchin/sorting issues. (since 6.20)<br />
|-<br />
| 611 || || yomiLastName || String || Kana based representation for the Last Name. Commonly used in japanese environments for searchin/sorting issues. (since 6.20)<br />
|-<br />
| 612 || || yomiCompany || String || Kana based representation for the Company. Commonly used in japanese environments for searchin/sorting issues. (since 6.20)<br />
|-<br />
| 613 || || addressHome || String || Support for Outlook 'home' address field. (since 6.20.1)<br />
|-<br />
| 614 || || addressBusiness || String || Support for Outlook 'business' address field. (since 6.20.1)<br />
|-<br />
| 615 || || addressOther || String || Support for Outlook 'other' address field. (since 6.20.1)<br />
|}<br />
<br />
<br />
{| id="DistributionListMember" cellspacing="0" border="1"<br />
|+ align="bottom" | Distribution list member<br />
! Name !! Type !! Value<br />
|-<br />
| id || String || Object ID of the member's contact if the member is an existing contact.<br />
|-<br />
| folder_id || String || Parent folder ID of the member's contact if the member is an existing contact (preliminary, from 6.22 on).<br />
|-<br />
| display_name || String || Display name<br />
|-<br />
| mail || String || Email address (mandatory before 6.22, afterwards optional if you are referring to an internal contact)<br />
|-<br />
| mail_field || Number || Which email field of an existing contact (if any) is used for the mail field.<br />
{| cellspacing="0" border="1"<br />
| 0 || independent contact<br />
|-<br />
| 1 || default email field (email1)<br />
|-<br />
| 2 || second email field (email2)<br />
|-<br />
| 3 || third email field (email3)<br />
|}<br />
|}<br />
<br />
=== Get a list of contacts ===<br />
<br />
PUT <code>/ajax/contacts?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for contacts are defined in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]].<br />
<br />
Request body: An array with objects. Each object contains fields “id” and “folder” of requested contacts.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a list of users ===<br />
<br />
PUT <code>/ajax/contacts?action=listuser</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for contacts are defined in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]].<br />
<br />
Request body: An array with id<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
Available with SP4<br />
<br />
=== Get updated contacts ===<br />
<br />
GET <code>/ajax/contacts?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for contacts are defined in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested contacts.<br />
* <code>ignore</code> (mandatory - should be set to "deleted") (deprecated) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
<br />
Response with timestamp: An array with new, modified and deleted contacts. New and modified contacts are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted contacts (should the <code>ignore</code> parameter be ever implemented) would be identified by their object IDs as plain strings, without being part of a nested array.<br />
<br />
=== Get a contact ===<br />
<br />
GET <code>/ajax/contacts?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested contact.<br />
* <code>folder</code> – Object ID of the contact's folder.<br />
<br />
Response with timestamp: An object containing all data of the requested contact. The fields of the object are listed in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]]. The field id is not included.<br />
<br />
=== Get contact by user ID ===<br />
<br />
GET <code>/ajax/contacts?action=getuser</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – User ID (not Object ID) of the requested user.<br />
<br />
Response with timestamp: An object containing all data of the requested contact. The fields of the object are listed in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]]. <br />
<br />
Available with SP4 package.<br />
<br />
=== Update a contact ===<br />
<br />
PUT <code>/ajax/contacts?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Folder identifier through that the contact is accessed. This is necessary for checking the permissions.<br />
* <code>id</code> – Object ID of the updated contact.<br />
* <code>timestamp</code> – Timestamp of the updated contact. If the contact was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: Contact object as described in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]]. Only modified fields are present.<br />
<br />
To remove some contact image send the image attribute set to <code>null</code>.<br />
<br />
To change or add some contact image the PUT command must be replaced with a POST command and all data must be provided within a <code>multipart/form-data</code> body. The normal request body must be placed into a form field named <code>json</code> while the image file must be placed in a file field named <code>file</code>. The response is then an HTML page as described in section [[#File_uploads | File uploads]].<br />
<br />
=== Create a contact ===<br />
<br />
PUT <code>/ajax/contacts?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Contact object as described in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]]. The field id is not included.<br />
<br />
Response: A json objekt with attribute <code>id</code> of the newly created contact.<br />
<br />
To add some contact image the PUT command must be replaced with a POST command and all data must be provided within a <code>multipart/form-data</code> body. The normal request body must be placed into a form field named <code>json</code> while the image file must be placed in a file field named <code>file</code>. The response is then an HTML page as described in section [[#File uploads | File uploads]].<br />
<br />
=== Delete a contact ===<br />
<br />
PUT <code>/ajax/contacts?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted contacts.<br />
<br />
Request body: An object with the fields “id” and “folder”.<br />
<br />
=== Delete contacts (since v6.22)===<br />
<br />
PUT <code>/ajax/contacts?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted contacts.<br />
<br />
Request body: An array of objects with the fields “id” and “folder”.<br />
<br />
=== Search contacts ===<br />
<br />
PUT <code>/ajax/contacts?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified. In case of use of column 609 (use count depending order for collected contacts with global address book) the parameter "order" ist NOT necessary and will be ignored.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (preliminary, since 6.20) – allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Request body: An Object as described in [[#SearchContacts | Search contacts]].<br />
<br />
{| id="SearchContacts" cellspacing="0" border="1"<br />
|+ align="bottom" | Search contacts<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find contacts. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves. Matching is performed against any substring of the field <code>display_name</code>.<br />
|-<br />
| startletter || String || Search contacts with the given startletter. If this field is present, the pattern is matched against the contact field which is specified by the property contact_first_letter_field on the server (default: last name). Otherwise, the pattern is matched against the display name.<br />
|-<br />
| folder || Array of Number || If a list of folder identifiers or at least a single folder identifier is given, only in that folders will be searched for contacts. This paramenter is optional but searching in all contact folders that are viewable and where objects can be read in is more expensive on that database than searching in a dedicated number of them. The possibility to provide here an array of folder identifier has been added with 6.10.<br />
|}<br />
<br />
Alternative request body: An Object as described in [[#SearchContactsAlternative | Search contacts alternative]].<br />
<br />
{| id="SearchContactsAlternative" cellspacing="0" border="1"<br />
|+ align="bottom" | Search contacts alternative<br />
! Name !! Type !! Value<br />
|-<br />
| last_name || String || Searches contacts where the last name match with the given last name.<br />
|-<br />
| first_name || String || Searches contacts where the first name match with the given first name.<br />
|-<br />
| display_name || String || Searches contacts where the display name match with the given display name.<br />
|-<br />
| email1 || String || Searches contacts where the email1 address match with the given search pattern. (requires version >= 6.12)<br />
|-<br />
| email2 || String || Searches contacts where the email2 address match with the given search pattern. (requires version >= 6.12)<br />
|-<br />
| email3 || String || Searches contacts where the email3 address match with the given search pattern. (requires version >= 6.12)<br />
|-<br />
| company || String || Searches contacts where the company match with the given search pattern. (requires version >= 6.12)<br />
|-<br />
| categories || String || Searches contacts where the categories match with the given search pattern. <br />
|-<br />
| orSearch || Boolean || If set to true, a contact is returned if any specified pattern matches at the start of the corresponding field. Otherwise, a contact is returned if all specified patterns match any substring of the corresponding field.<br />
|-<br />
| emailAutoComplete || Boolean || If set to true, results are guaranteed to contain at least one email adress and the search is performed as if orSearch were set to true. The actual value of orSearch is ignored.<br />
|-<br />
| exactMatch || Boolean || If set to true, contacts are returned where the specified patterns match the corresponding fields exactly. Otherwise, a 'startsWith' or 'substring' comparison is used based on the 'orSearch' parameter. (requires version > 6.22.1)<br />
|}<br />
<br />
Response: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Search contacts by filter (since 6.20) ===<br />
<br />
PUT <code>/ajax/contacts?action=advancedSearch</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified. <br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (preliminary, since 6.20) – allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Request body: An Object as described in [[#Module_.22search.22_.28alternative_suggestion.2C_still_preliminary.29 | Search Filter]]<br />
<br />
Response: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Search contacts by anniversary (Since 6.22.1, Preliminary) ===<br />
<br />
Find contacts whose anniversary falls into a timerange.<br />
<br />
GET <code>/ajax/contacts?action=anniversaries</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>start</code> – The lower (inclusive) limit of the requested time-range.<br />
* <code>end</code> – The upper (exclusive) limit of the requested time-range.<br />
* <code>columns</code> – The requested fields.<br />
* <code>folder</code> (optional) – Object ID of the parent folder that is searched. If not set, all visible folders are used.<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If not specified, the results are sorted ascending by their anniversary in the supplied timerange. If this parameter is specified, then the parameter order must be also specified. <br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (optional) – Allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Search contacts by birthday (Since 6.22.1, Preliminary) ===<br />
<br />
Find contacts whose birthday falls into a timerange.<br />
<br />
GET <code>/ajax/contacts?action=birthdays</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>start</code> – The lower (inclusive) limit of the requested time-range.<br />
* <code>end</code> – The upper (exclusive) limit of the requested time-range.<br />
* <code>columns</code> – The requested fields.<br />
* <code>folder</code> (optional) – Object ID of the parent folder that is searched. If not set, all visible folders are used.<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If not specified, the results are sorted ascending by their birthday in the supplied timerange. If this parameter is specified, then the parameter order must be also specified. <br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (optional) – Allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Auto-complete contacts (Since 7.6.1, Preliminary) ===<br />
<br />
Find contacts based on a prefix, usually used to auto-complete e-mail recipients while the user is typing.<br />
<br />
GET <code>/ajax/contacts?action=autocomplete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>query</code> – The query to search for.<br />
* <code>folder</code> (optional) – Object ID of the parent folder that is searched. If not set, all visible folders are used.<br />
* <code>email</code> (optional) – Whether to only include contacts with at least one e-mail address. Defaults to "true".<br />
* <code>columns</code> – The requested fields.<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is <br />
* <code>collation</code> (optional) – Allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
* <code>left_hand_limit</code> (optional) – A positive integer number to specify the "left-hand" limit of the range to return.<br />
* <code>right_hand_limit</code> (optional) – A positive integer number to specify the "right-hand" limit of the range to return.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
== Module "calendar" ==<br />
<br />
The calendar module is used to access calendar data.<br />
<br />
=== Get all appointments ===<br />
<br />
GET <code>/ajax/calendar?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> (optional) – Object ID of the folder, whose contents are queried. If not specified, defaults to all calendar folders.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]].<br />
* <code>start</code> – Lower inclusive limit of the queried range as a Date. Only appointments which start on or after this date are returned.<br />
* <code>end</code> – Upper exclusive limit of the queried range as a Date. Only appointments which end before this date are returned.<br />
* <code>recurrence_master</code> – Extract the recurrence to several appointments. The default value is false so every appointment of the recurrence will be calculated.<br />
* <code>showPrivate</code> (optional) – only works in shared folders: When enabled, shows private appointments of the folder owner. Such appointments are anonymized by stripping away all information except start date, end date and recurrence information (since 6.18)<br />
<br />
Response with timestamp: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Appointment sequencies are broken up into individual appointments and each occurrence of a sequence in the requested range is returned separately. The appointments are sorted in ascending order by the field start_date.<br />
<br />
{| id="DetailedAppointmentData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed appointment data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 206 || recurrence_id || Number || Object ID of the entire appointment sequence. Present on series and change exception appointments. Equals to object identifier on series appointment and is different to object identifier on change exceptions.<br />
|-<br />
| 207 || recurrence_position || Number || 1-based position of an individual appointment in a sequence. Present if and only if recurrence_type > 0.<br />
|-<br />
| 208 || recurrence_date_position || Date || Date of an individual appointment in a sequence. Present if and only if recurrence_type > 0.<br />
|-<br />
| 210 || change_exceptions || Array || An array of Dates, representing all change exceptions of a sequence.<br />
|-<br />
| 211 || delete_exceptions || Array || An array of Dates, representing all delete exceptions of a sequence.<br />
|-<br />
| 400 || location || String || Location<br />
|-<br />
| 402 || shown_as || Number || Describes, how this appointment appears in availability queries:<br />
{| cellspacing="0" border="1"<br />
| 1 || reserved<br />
|-<br />
| 2 || temporary<br />
|-<br />
| 3 || absent<br />
|-<br />
| 4 || free<br />
|}<br />
|-<br />
| 408 || timezone || String || Timezone<br />
|-<br />
| 410 || recurrence_start || Date || Start of a sequence without time<br />
|-<br />
| || ignore_conflicts || Boolean || Ignore soft conflicts for the new or modified appointment. This flag is valid for the current change only, i. e. it is not stored in the database and is never sent by the server to the client. <br />
|}<br />
<br />
=== Get appointment information ===<br />
<br />
GET <code>/ajax/calendar?action=has</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>start</code> – Lower inclusive limit of the queried range as a Date. Only appointments which end on or after this date are returned.<br />
* <code>end</code> – Upper exclusive limit of the queried range as a Date. Only appointments which start before this date are returned.<br />
<br />
Response is an array of booleans. Array length is the number of days. Each entry in the array corresponds with one day in the range that was queried, explaining whether there is an appointment on this day or not.<br />
<br />
=== Get a list of appointments ===<br />
<br />
PUT <code>/ajax/calendar?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]].<br />
* <code>recurrence_master</code> – Extract the recurrence to several appointments. The default value is false so every appointment of the recurrence will be calculated.<br />
<br />
Request body: An array with full object IDs (folder, id and optionally either recurrence_position or recurrence_date_position) of requested appointments.<br />
<br />
Response with timestamp: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="FullIdentifierForAnAppointment" cellspacing="0" border="1"<br />
|+ align="bottom" | Full identifier for an appointment<br />
! Name !! Type !! Value<br />
|-<br />
| id || String || Object ID<br />
|-<br />
| pos || Number || Value of the field recurrence_position, if present in the appointment.<br />
|}<br />
<br />
=== Get updated appointments ===<br />
<br />
GET <code>/ajax/calendar?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]].<br />
* <code>timestamp</code> – Timestamp of the last update of the requested appointments.<br />
* <code>start</code> (optional) – Lower inclusive limit of the queried range as a Date. Only appointments which end on or after this date are returned.<br />
* <code>end</code> (optional) – Upper exclusive limit of the queried range as a Date. Only appointments which start before this date are returned.<br />
* <code>ignore</code> (mandatory - should be set to "deleted") (deprecated) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
* <code>recurrence_master</code> – Extract the recurrence to several appointments. The default value is false so every appointment of the recurrence will be calculated.<br />
* <code>showPrivate</code> (optional) – only works in shared folders: When enabled, shows private appointments of the folder owner. Such appointments are anonymized by stripping away all information except start date, end date and recurrence information (since 6.18)<br />
<br />
Response with timestamp: An array with new, modified and deleted appointments. New and modified appointments are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted appointments (should the <code>ignore</code> parameter be ever implemented) would be identified by objects described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]] instead of arrays. Appointment sequencies are broken up into individual appointments and each modified occurrence of a sequence in the requested range is returned separately. The appointments are sorted in ascending order by the field start_date.<br />
<br />
=== Get an appointment ===<br />
<br />
GET <code>/ajax/calendar?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested appointment.<br />
* <code>folder</code> – Folder ID of the requested appointment.<br />
* <code>recurrence_position</code> (optional) – Recurrence Position requested appointment.<br />
<br />
Response with timestamp: An object containing all data of the requested appointment. The fields of the object are listed in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]]. The field id is not included.<br />
<br />
=== Update an appointment ===<br />
<br />
PUT <code>/ajax/calendar?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated appointment.<br />
* <code>folder</code> - Object ID of the appointment's folder.<br />
* <code>timestamp</code> – Timestamp of the updated appointment. If the appointment was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: Appointment object as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]]. The field recurrence_id is always present if it is present in the original appointment. The field recurrence_position is present if it is present in the original appointment and only this single appointment should be modified. The field id is not present because it is already included as a parameter. Other fields are present only if modified.<br />
<br />
=== Create an appointment ===<br />
PUT <code>/ajax/calendar?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Appointment object as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]]. The field id is not present.<br />
<br />
Response: If the appointment was created successfully, an object with the attribute <code>id</code> of the newly created appointment. If the appointment could not be created due to conflicts, the response body is an object with the field <code>conflicts</code>, which is an array of appointment objects which caused the conflict. Each appointment object which represents a resource conflict contains an additional field <code>hard_conflict</code> with the Boolean value true. If the user does not have read access to a conflicting appointment, only the fields <code>id</code>, <code>start_date</code>, <code>end_date</code>, <code>shown_as</code> and <code>participants</code> are present and the field <code>participants</code> contains only the participants which caused the conflict.<br />
<br />
=== Delete an appointment ===<br />
<br />
PUT <code>/ajax/calendar?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted appointments.<br />
<br />
Request body: The appointment object to delete. The fields for the object are described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]]. <br />
<br />
Response: An array of objects identifying the appointments which were modified after the specified timestamp and were therefore not deleted. The fields of each object are described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]].<br />
<br />
=== Delete appointments (since v6.22) ===<br />
<br />
PUT <code>/ajax/calendar?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted appointments.<br />
<br />
Request body: An array of appointment objects to delete. The fields for the object are described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]]. <br />
<br />
Response: An array of objects identifying the appointments which were modified after the specified timestamp and were therefore not deleted. The fields of each object are described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]].<br />
<br />
=== Confirm appointment ===<br />
<br />
PUT <code>/ajax/calendar?action=confirm</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the appointment to confirm.<br />
* <code>occurrence</code> – The numeric identifier of the occurrence to which the confirmation applies (in case "id" denotes a series appointment). Available with v7.6.0<br />
* <code>folder</code> – ID of the folder through which the appointment is accessed.<br />
* <code>timestamp</code> – Timestamp of the last update of the to confirmed appointment.<br />
<br />
Request body: An object with the fields "confirmation", "confirmmessage" and "id" (optional) as described in [[#UserParticipantObject | User participant object]].<br />
<br />
Response: Nothing, except the standard response object with empty data, the timestamp of the confirmed and thereby updated task, and maybe errors.<br />
<br />
=== Free & Busy ===<br />
<br />
GET <code>/ajax/calendar?action=freebusy</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> - Internal user id. Must be obtained from the contact module.<br />
* <code>type</code> - Constant for user or resource (1 for users, 3 for resources)<br />
* <code>start</code> – Lower inclusive limit of the queried range as a Date. Only appointments which end on or after this date are returned.<br />
* <code>end</code> – Upper exclusive limit of the queried range as a Date. Only appointments which start before this date are returned.<br />
<br />
Response: An array of objects identifying the appointments which lie between start and end as described.<br><br />
This objects consist of:<br />
{| id="FreeAndBusyAppointment" cellspacing="0" border="1"<br />
! Name !! Type !! Value<br />
|-<br />
| shown_as || Number || Describes, how this appointment appears in availability queries:<br />
{| cellspacing="0" border="1"<br />
| 1 || reserved<br />
|-<br />
| 2 || temporary<br />
|-<br />
| 3 || absent<br />
|-<br />
| 4 || free<br />
|}<br />
|-<br />
| start_date || Date or Time || see [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]]<br />
|- <br />
| end_date || Date or Time || see [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]]<br />
|-<br />
| id || String || Object ID<br />
|-<br />
| folder_id || String || Folder ID. Only set, if the user has the right to see the object. (added 2009-08-18/6.12) <br />
|-<br />
| full_time || Boolean || True if the appointment is a whole day appointment, not present otherwise.<br />
|}<br />
<br />
=== Search appointments ===<br />
<br />
PUT <code>/ajax/calendar?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
<br />
Request body: An Object as described in [[#SearchAppointments | Search appointments]].<br />
<br />
{| id="SearchAppointments" cellspacing="0" border="1"<br />
|+ align="bottom" | Search appointments<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find appointments. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|-<br />
| startletter || String || Search appointments with the given starting letter.<br />
|}<br />
<br />
Request body: An Object as described in [[#SearchAppointments | Search appointments]].<br />
<br />
Response: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get new appointments ===<br />
<br />
GET <code>/ajax/calendar?action=newappointments</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
* <code>start</code> – Lower inclusive limit of the queried range as a Date. Only appointments which end on or after this date are returned.<br />
* <code>end</code> – Upper exclusive limit of the queried range as a Date. Only appointments which start before this date are returned.<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified and holds a column number, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>limit</code> – limits the number of returned object to the given value.<br />
<br />
Response: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Resolve UID ===<br />
<br />
GET <code>/ajax/calendar?action=resolveuid</code><br />
<br />
Parameters<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>uid</code> – The UID to be resolved.<br />
<br />
Response: An object object with the field "id" containing the ox-object id, if existing, an error message otherwise.<br />
<br />
=== Get all Change Exceptions (Since v7.2.0) ===<br />
<br />
GET <code>/ajax/calendar?action=getChangeExceptions</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object id of the appointment series.<br />
* <code>folder</code> – Folder ID of the requested appointments. <br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier.<br />
<br />
Response with timestamp: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
== Module "mail" ==<br />
<br />
The mail module is used to access mail data.<br />
<br />
When mails are stored on an IMAP server, some functionality is not available due to restrictions of the IMAP protocol. Such functionality is marked with "not IMAP".<br />
<br />
=== Get mail count ===<br />
<br />
GET <code>/ajax/mail?action=count</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder whose mail count is queried<br />
<br />
Response (not IMAP: with timestamp): An integer value representing folder's mail count<br />
<br />
=== Get all mails ===<br />
<br />
GET <code>/ajax/mail?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#DetailedMailData | Detailed mail data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response or the string “thread” to return thread-sorted messages. If this parameter is specified and holds a column number, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>left_hand_limit</code> - A positive integer number to specify the "right-hand" limit of the range to return<br />
* <code>right_hand_limit</code> - A positive integer number to specify the "left-hand" limit of the range to return<br />
* <code>limit</code> - A positive integer number to specify how many items shall be returned according to given sorting; overrides <code>left_hand_limit</code>/<code>right_hand_limit</code> parameters and is equal to <code>left_hand_limit=0</code> and <code>right_hand_limit=&lt;limit&gt;</code><br />
<br />
Response (not IMAP: with timestamp): An array with mail data. Each array element describes one mail and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedMailData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed mail data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 102 || color_label || Number || Color number used by Outlook to label the object. The assignment of colors to numbers is arbitrary and specified by the client. The numbers are integer numbers between 0 and 10 (inclusive).<br />
|-<br />
| 600 || id || String || Object ID<br />
|-<br />
| 601 || folder_id || String || Object ID of the parent folder<br />
|-<br />
| 602 || attachment || Boolean || Specifies whether this mail has attachments.<br />
|-<br />
| 603 || from || Array || Each element is a two-element array specifying one sender. The first element of each address is the personal name, the second element is the email address. Missing address parts are represented by <code>null</code> values.<br />
|-<br />
| 604 || to || Array || Each element is a two-element array (see the from field) specifying one receiver.<br />
|-<br />
| 605 || cc || Array || Each element is a two-element array (see the from field) specifying one carbon-copy receiver.<br />
|-<br />
| 606 || bcc || Array || Each element is a two-element array (see the from field) specifying one blind carbon-copy receiver.<br />
|-<br />
| 607 || subject || String || Subject line.<br />
|-<br />
| 608 || size || Number || Size of the mail in bytes.<br />
|-<br />
| 609 || sent_date || Time || Date and time as specified in the mail by the sending client.<br />
|-<br />
| 610 || received_date || Time || Date and time as measured by the receiving server.<br />
|-<br />
| 611 || flags || Number || Various system flags. A sum of zero or more of following values:<br />
{| cellspacing="0" border="1"<br />
| 1 || answered<br />
|-<br />
| 2 || deleted<br />
|-<br />
| 4 || draft<br />
|-<br />
| 8 || flagged<br />
|-<br />
| 16 || recent<br />
|-<br />
| 32 || seen<br />
|-<br />
| 64 || user<br />
|-<br />
| 256 || forwarded<br />
|}<br />
See javax.mail.Flags.Flag for details.<br />
|-<br />
| 612 || level || Number || Zero-based nesting level in a thread.<br />
|-<br />
| 613 || disp_notification_to || String || Content of message's header “Disposition-Notification-To”<br />
|-<br />
| 614 || priority || Number || Value of message's “X-Priority” header:<br />
{| cellspacing="0" border="1"<br />
| 0 || No priority<br />
|-<br />
| 5 || Very Low<br />
|-<br />
| 4 || Low<br />
|-<br />
| 3 || Normal<br />
|-<br />
| 2 || High<br />
|-<br />
| 1 || Very High<br />
|}<br />
|-<br />
| 615 || msg_ref || String || Message reference on reply/forward.<br />
|-<br />
| 651 || flag_seen || String || Special field to sort mails by seen status<br />
|-<br />
| 652 || account_name || String || Message's account name.<br />
|-<br />
| 653 || account_id || int || Message's account identifier. Since v6.20.2<br />
|-<br />
| || user || Array || An array with user-defined flags as strings.<br />
|-<br />
| || headers || Object || An object with a field for every non-standard header. The header name is the field name. The header value is the value of the field as string.<br />
|-<br />
| || attachments || Array || Each element is an attachment as described in [[#Attachment | Attachment]]. The first element is the mail text. If the mail has multiple representations (multipart-alternative), then the alternatives are placed after the mail text and have the field disp set to alternative.<br />
|-<br />
| || nested_msgs || Array || Each element is a mail object as described in this table, except for fields id, folder_id and attachment.<br />
|-<br />
| || truncated || boolean || true/false if the mail content was trimmed. Since v7.6.1<br />
|-<br />
| || source || String || RFC822 source of the mail. Only present for <tt>action=get&attach_src=true</tt><br />
|}<br />
<br />
{| id="Attachment" cellspacing="0" border="1"<br />
|+ align="bottom" | Attachment<br />
! Name !! Type !! Value<br />
|-<br />
| id || String || Object ID (unique only inside the same message)<br />
|-<br />
| content_type || String || MIME type<br />
|-<br />
| content || String || Content as text. Present only if easily convertible to text.<br />
|-<br />
| filename || String || Displayed filename (mutually exclusive with content).<br />
|-<br />
| size || Number || Size of the attachment in bytes.<br />
|-<br />
| disp || String || Attachment's disposition: null, inline, attachment or alternative.<br />
|}<br />
<br />
=== Get all mail conversations (since v7.x) ===<br />
<br />
GET <code>/ajax/mail?action=threadedAll</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#DetailedMailData | Detailed mail data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response or the string “thread” to return thread-sorted messages. If this parameter is specified and holds a column number, then the parameter order must be also specified. <b>Note</b>: Applies only to root-level messages.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified. <b>Note</b>: Applies only to root-level messages.<br />
* <code>includeSent</code> - A boolean value to signal that conversations also include messages taken from special "sent" aka "sent items" folder<br />
* <code>left_hand_limit</code> - A positive integer number to specify the "right-hand" limit of the range to return. <b>Note</b>: Applies only to root-level messages.<br />
* <code>right_hand_limit</code> - A positive integer number to specify the "left-hand" limit of the range to return. <b>Note</b>: Applies only to root-level messages.<br />
* <code>limit</code> - A positive integer number to specify how many items shall be returned according to given sorting; overrides <code>left_hand_limit</code>/<code>right_hand_limit</code> parameters and is equal to <code>left_hand_limit=0</code> and <code>right_hand_limit=&lt;limit&gt;</code>. <b>Note</b>: Applies only to root-level messages.<br />
<br />
Response (not IMAP: with timestamp): An JSON array consisting of JSON objects, each representing a conversation's root message along with its message thread. The root message's JSON object is filled according to specified columns and is enhanced by special <code>"thread"</code> JSON field representing the full message thread (including the root message itself). The <code>"thread"</code> JSON field is a JSON array of JSON objects; each representing a message in the conversation sorted by time-line, also filled with specified columns. E.g.<br />
<br />
<pre><br />
{<br />
"flags":32,<br />
"color_label":0,<br />
"unreadCount":0,<br />
"id":"263852",<br />
"folder_id":"default0/INBOX",<br />
"thread":[<br />
{<br />
"id":"263852",<br />
"folder_id":"default0/INBOX",<br />
"flags":32,<br />
"color_label":0<br />
},<br />
{<br />
"id":"263853",<br />
"folder_id":"default0/INBOX",<br />
"flags":32,<br />
"color_label":0<br />
},<br />
{<br />
"id":"26323",<br />
"folder_id":"default0/Sent",<br />
"flags":32,<br />
"color_label":0<br />
},<br />
{<br />
"id":"263854",<br />
"folder_id":"default0/INBOX",<br />
"flags":32,<br />
"color_label":0<br />
}<br />
]<br />
}<br />
</pre><br />
<br />
=== Search mails ===<br />
<br />
PUT <code>/ajax/mail?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#DetailedMailData | Detailed mail data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response or the string “thread” to return thread-sorted messages. If this parameter is specified and holds a column number, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Request Body: A JSON array of JSON objects each containing the search field and its search pattern: e.g.:<br />
<code>[{"col": 612, "pattern": "Joe"}, {"col": 614, "pattern": "Tuesday"}]</code> Supported values for <code>col</code> are 603 to 607 (from, to, cc, bcc and subject) and -1 for full text search.<br />
<br />
Response (not IMAP: with timestamp): An array with mail data. Each array element describes one mail and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a list of mails ===<br />
<br />
PUT <code>/ajax/mail?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for mails are defined in [[#DetailedMailData | Detailed mail data]].<br />
* <code>headers</code> - (preliminary) A comma-separated list of header names. Each name requests denoted header from each mail<br />
<br />
Request body: An array with one object for each requested mail. Each object contains the fields <code>folder</code> and <code>id</code>.<br />
<br />
Response (not IMAP: with timestamp): An array with mail data. Each array element describes one mail and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter followed by requested headers.<br />
<br />
=== Copy mails ===<br />
<br />
PUT <code>/ajax/mail?action=copy</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested mail.<br />
* <code>folder</code> – Object ID of the source folder.<br />
<br />
Request Body: A JSON object containing the id of the destination folder inside the "folder_id" field: e.g.:<br />
<code>{"folder_id": 1376}</code><br />
<br />
Response: A JSON array containing the ID of the copied mail<br />
<br />
=== Move mails ===<br />
<br />
PUT <code>/ajax/mail?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested mail.<br />
* <code>folder</code> – Object ID of the source folder.<br />
<br />
Request Body: A JSON object containing the id of the destination folder inside the "folder_id" field: e.g.:<br />
<code>{"folder_id": 1376}</code><br />
<br />
<br />
Response: A JSON array containing the ID of the moved mail<br />
<br />
=== Update mails ===<br />
<br />
PUT <code>/ajax/mail?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested mail.<br />
* <code>message_id</code> – (Preliminary) The value of "Message-Id" header of the requested mail. This parameter is a substitute for "id" parameter.<br />
* <code>folder</code> – Object ID of the folder.<br />
<br />
'''Note''': If neither parameter "<code>id</code>" nor parameter "<code>message_id</code>" is specified, all folder's messages are updated accordingly. Available with v6.20.<br />
<br />
Request Body: A JSON object which carries the new values that ought to be applied to mail as described in [[#UpdateMail | Update mail]] or [[#UpdateMailExtended | Update mail extended]] (available with SP6 v6.10).<br />
<br />
Response: A JSON object containing the Object ID of the updated mail and its folder.<br />
<br />
{| id="UpdateMail" cellspacing="0" border="1"<br />
|+ align="bottom" | Update mail<br />
! Name !! Type !! Value<br />
|-<br />
| color_label || Number || The color number between 0 and 10.<br />
|-<br />
| flags || Number || A set of flags to add or remove. Note: Flags for "recent" (8) and "user" (64) are ignored.<br />
|-<br />
| value || Boolean || <code>true</code> to add the flags specified by <code>flags</code> (logical OR), <code>false</code> to remove them (logical AND with the inverted value).<br />
|}<br />
<br />
<br />
<br />
{| id="UpdateMailExtended" cellspacing="0" border="1"<br />
|+ align="bottom" | Update mail extended (available with SP6 v6.10)<br />
! Name !! Type !! Value<br />
|-<br />
| set_flags || Number || A set of flags to add. Note: Flags for "recent" (8) and "user" (64) are ignored.<br />
|-<br />
| clear_flags || Number || A set of flags to remove. Note: Flags for "recent" (8) and "user" (64) are ignored.<br />
|}<br />
<br />
<br />
=== Mark all mails as seen (available with v7.6.0) ===<br />
<br />
PUT <code>/ajax/mail?action=all_seen</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder.<br />
<br />
Request Body: n.a.<br />
<br />
Response: <code>true</code><br />
<br />
=== Not IMAP: Get updated mails ===<br />
<br />
GET <code>/ajax/mail?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: Just an empty JSON array is going to be returned since this action cannot be applied to IMAP.<br />
<br />
=== Get a mail ===<br />
<br />
GET <code>/ajax/mail?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested mail.<br />
* <code>message_id</code> – (Preliminary) The value of "Message-Id" header of the requested mail. This parameter is a substitute for "id" parameter.<br />
* <code>folder</code> – Object ID of the mail's folder.<br />
* <code>edit</code> (optional) – 1 indicates that this request should fill the message compose dialog to edit a message and thus display-specific date is going to be withheld.<br />
* <code>hdr</code> (optional) – 1 to let the response contain only the (formatted) message headers as plain text<br />
* <code>src</code> (optional) – 1 to let the response contain the complete message source as plain text<br />
* <code>save</code> (optional) – 1 to write the complete message source to output stream. '''NOTE:''' This parameter will only be used if parameter <code>src</code> is set to 1.<br />
* <code>view</code> (optional - available with SP4)<br />
** "raw" returns the content as it is, meaning no preparation are performed and thus no guarantee for safe contents is given (available with SP6 v6.10).<br />
** "text" forces the server to deliver a text-only version of the requested mail's body, even if content is HTML.<br />
** "textNoHtmlAttach" is the same as "text", but does not deliver the HTML part as attachment in case of multipart/alternative content.<br />
** "html" to allow a possible HTML mail body being transferred as it is (but white-list filter applied).<br />
** "noimg" to allow a possible HTML content being transferred but without original image src attributes which references external images: Can be used to prevent loading external linked images (spam privacy protection).<br />
** '''NOTE:''' if set, the corresponding gui config setting will be ignored.<br />
* <code>unseen</code> (optional) – "1" or "true" to leave an unseen mail as unseen although its content is requested<br />
* <code>max_size</code> (optional - available since v7.6.1) A positive integer number (greater than 10000) to specify how many characters of the message content will be returned. If the number is smaller than 10000 the value will be ignored and 10000 used.<br />
* <code>attach_src</code> (optional - available since v7.6.1) 1 to let the JSON mail representation being extended by <code>"source"</code> field containing the mail raw RFC822 source data<br />
<br />
Response (not IMAP: with timestamp): An JSON object containing all data of the requested mail. The fields of the object are listed in [[#DetailedMailData | Detailed mail data]]. The fields id and attachment are not included. '''NOTE:''' Of course response is not a JSON object if either parameter <code>hdr</code> or parameter <code>src</code> are set to "1". Then the response contains plain text. Moreover if optional parameter <code>save</code> is set to "1" the complete message source is going to be directly written to output stream to open browser's save dialog.<br />
<br />
=== Get multiple mails as a ZIP file ===<br />
<br />
GET <code>/ajax/mail?action=zip_messages</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – The folder identifier.<br />
* <code>id</code> – A comma-separated list of Object IDs of the requested mails<br />
<br />
Response body: The raw byte data of the ZIP file.<br />
<br />
=== Get a mail attachment ===<br />
<br />
GET <code>/ajax/mail?action=attachment</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – The folder identifier.<br />
* <code>id</code> – Object ID of the mail which contains the attachment.<br />
* <code>attachment</code> – ID of the requested attachment '''OR'''<br />
* <code>cid</code> – Value of header 'Content-ID' of the requested attachment<br />
* <code>save</code> – 1 overwrites the defined mimetype for this attachment to force the download dialog, otherwise 0.<br />
* <code>filter</code> (optional) – 1 to apply HTML white-list filter rules if and only if requested attachment is of MIME type <code>text/htm*</code> '''AND''' parameter <code>save</code> is set to 0.<br />
<br />
Response body: The raw byte data of the document. The response type for the HTTP Request is set accordingly to the defined mimetype for this attachment, except the parameter save is set to 1.<br />
<br />
=== Get multiple mail attachments as a ZIP file ===<br />
<br />
GET <code>/ajax/mail?action=zip_attachments</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – The folder identifier.<br />
* <code>id</code> – Object ID of the mail which contains the attachments.<br />
* <code>attachment</code> – A comma-separated list of IDs of the requested attachments<br />
<br />
Response body: The raw byte data of the ZIP file.<br />
<br />
=== Send a mail ===<br />
<br />
POST <code>/ajax/mail?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request Body: This method uses the encoding multipart/form-data or multipart/mixed.<br />
* The form filed <code>json_0</code> contains the rudimentary mail as JSON object as described in [[#DetailedMailData | Detailed mail data]] with just its message body (as html content) defined in nested JSON array "attachments" and its header data (from, to, subject, etc.). The field "content_type" defines whether the mail ought to be sent as plain text ("text/plain"), as html ("text/html") or as multipart/alternative ("ALTERNATIVE"). Sending a mail requires some special fields inside JSON mail object. The field "infostore_ids" defines a JSON array of infostore document ID(s) that ought to be appended to this mail as attachments. The field "msgref" indicates the ID of the referenced original mail. Moreover the field "sendtype" indicates the type of the message:<br />
** 0 - A normal new mail (optional)<br />
** 1 - A reply mail. The field "msgref" must be present<br />
** 2 - A forward mail. The field "msgref" must be present<br />
** 3 - A draft edit operation. The field "msgref" must be present in order to delete previous draft message since e.g. IMAP does not support changing/replacing a message but requires a delete-and-insert sequence<br />
** 4 - Transport of a draft mail. The field "msgref" must be present<br />
** 6 - This type signals that user intends to send out a saved draft message and expects the draft message (referenced by "msgref" field) being deleted after successful transport<br />
Example of a normal new mail which appends user's VCard and requests a read receipt from receiver:<br />
<br />
<code>Content-Disposition: form-data; name="json_0"....{"from":"\u0022Muster, Karl\u0022 <karl.muster@somewhere.com>","to":"someone@somewhere.com","cc":"","bcc":"",<br />
"subject":"Mail Subject","priority":"3","disp_notification_to":true,"vcard":1,<br />
"attachments":[{"content_type":"ALTERNATIVE","content":"Simple Mail Text!&lt;br&gt;&lt;br&gt;\u000a\u000a"}]}</code><br />
* The request accepts file fields in upload form that denote referenced files that are going to be appended as attachments<br />
* For "text/plain" mail bodies, the JSON boolean field "raw" may be specified inside the body's JSON representation to signal that the text content shall be kept as-is; meaning to keep all formatting intact<br />
<br />
==== Attach data sources ====<br />
Moreover the JSON representation may contain data sources which should be appended as file attachments to the mail. Then the mail contains the <code>"datasources"</code> key which is expected to be a JSON array of data source descriptions.<br />
<br />
A data source description follows the [[#Module_.22conversion.22_.28preliminary.29 | conversion specification]].<br />
<br />
For example to attach a file through an URL the field looks like this (available with v6.18.2):<br />
<br />
<pre><br />
{<br />
"from": "someone@somewhere.com,<br />
...<br />
"datasources"<br />
[<br />
{<br />
"identifier": "com.openexchange.url.mail.attachment",<br />
"args":<br />
{<br />
"url": <url-string>,<br />
"timeout": <optional-timeout-millis-int, default is 2500msec>,<br />
"contentType": <optional-content-type-string>,<br />
"charset": <optional-charset-string>,<br />
"size": <optional-size-int>,<br />
"disposition": <optional-disposition-string>,<br />
"fileName": <optional-file-name-string>,<br />
}<br />
}<br />
]<br />
}<br />
</pre><br />
<br />
Response: Object ID of the newly created mail.<br />
<br />
=== Send/Save mail as MIME data block (RFC822) (added in SP5) ===<br />
<br />
PUT <code>/ajax/mail?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> - A session ID previously obtained from the login module.<br />
* <code>folder</code> (optional) - In case the mail should not be sent out, but saved in a specific folder, the "folder" parameter can be used. If the mail should be sent out to the recipient, the "folder" parameter must not be included and the mail is stored in the folder "Sent Items". Example "folder=default.INBOX/Testfolder"<br />
* <code>flags</code> (optional) - In case the mail should be stored with status "read" (e.g. mail has been read already in the client inbox), the parameter "flags" has to be included. If no "folder" parameter is specified, this parameter must not be included. For infos about mail flags see [[#DetailedMailData | Detailed mail data]] spec.<br />
<br />
Request Body: The MIME Data Block<br />
<br />
Response: Object ID of the newly created/moved mail.<br />
<br />
=== Import of mails as MIME data block (RFC822) (added with 6.18) ===<br />
<br />
This request can be used to store a single or a lot of mails in the OX mail storage backend. This action should be used instead of <code>action=new</code> because it is faster and tolerant to 8bit encoded emails.<br />
<br />
<code>POST /ajax/mail?action=import</code><br />
<br />
Parameters:<br />
* <code>session</code> - A session ID previously obtained from the login module.<br />
* <code>folder</code> - For the import this parameter is required to specify the folder into that the emails should be imported. Example "folder=default.INBOX/Testfolder"<br />
* <code>flags</code> (optional) - In case the mail should be stored with status "read" (e.g. mail has been read already in the client inbox), the parameter "flags" has to be included. For infos about mail flags see [[#DetailedMailData | Detailed mail data]] spec.<br />
*<code>force</code> (optional) - If this parameter is set to true, the server skips checking the valid From-address<br />
<br />
Request Body: A multipart/form-data with a single or multiple file parts each having a different name and containing the RFC822 encoded email as binary data like in a file upload.<br />
<br />
Response: A JSON object containing the folder identifier and the object identifier of the imported mail or a JSON array of those JSON objects if multiple mails are imported.<br />
<br />
=== Reply/Forward a mail ===<br />
<br />
GET <code>/ajax/mail?action=reply</code><br><br />
GET <code>/ajax/mail?action=replyall</code><br><br />
GET <code>/ajax/mail?action=forward</code><br><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested Message.<br />
* <code>folder</code> - Object ID of the folder, whose contents are queried.<br />
* <code>view</code> (optional - available with SP6) - "text" forces the server to deliver a text-only version of the requested mail's body, even if content is HTML. "html" to allow a possible HTML mail body being transferred as it is (but white-list filter applied).'''NOTE:''' if set, the corresponding gui config setting will be ignored.<br />
* <code>setFrom</code> (optional - available since v7.6.0) A flag ("true"/"false") that signals if "From" header shall be pre-selected according to a suitable recipient address that matches one of user's E-Mail address aliases; only supported for <code>/ajax/mail?action=replyall</code> and <code>/ajax/mail?action=reply</code><br />
* <code>max_size</code> (optional - available since v7.6.1) A positive integer number (greater than 10000) to specify how many characters of the message content will be returned. If the number is smaller than 10000 the value will be ignored and 10000 used.<br />
<br />
Response (not IMAP: with timestamp): An object containing all data of the requested mail. The fields of the object are listed in [[#DetailedMailData | Detailed mail data]]. The fields id and attachment are not included.<br />
<br />
=== Delete mails ===<br />
<br />
PUT <code>/ajax/mail?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* Not IMAP: <code>timestamp</code> – Timestamp of the last update of the deleted mails.<br />
<br />
Request body: An array of objects providing folder IDs and object IDs of the deleted mails.<br />
<code><br><br />
[<br><br />
&nbsp;{&nbsp;&quot;folder&quot;:&quot;default0/INBOX&quot;,&nbsp;&quot;id&quot;:&quot;123&quot;&nbsp;}<br><br />
&nbsp;...<br><br />
&nbsp;{&nbsp;&quot;folder&quot;:&quot;default0/MyFolder&quot;,&nbsp;&quot;id&quot;:&quot;134&quot;&nbsp;}<br><br />
]<br><br />
</code><br />
<br />
Not IMAP: Response: An array with object IDs of mails which were modified after the specified timestamp and were therefore not deleted.<br />
<br />
=== Clear mail folder(s) ===<br />
<br />
PUT <code>/ajax/mail?action=clear</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* Not IMAP: <code>timestamp</code> – Timestamp of the last update of the deleted mails.<br />
<br />
Request body: An array with IDs of the mail folders to clear<br />
<br />
Response: An array with IDs of mail folder that could not be cleared; meaning the response body is an empty JSON array if everything went well.<br />
<br />
== Module "groups" ==<br />
<br />
The group module allows to query available groups. It is mainly used by the dialog for the selection of participants.<br />
<br />
=== Get a group ===<br />
<br />
GET <code>/ajax/group?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The group id.<br />
<br />
Response: A group object as described in [[#GroupData | Group data]].<br />
<br />
=== List groups ===<br />
<br />
PUT <code>/ajax/group?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An array with group identifiers.<br />
<br />
Response: An array of group objects as described in [[#GroupData | Group data]].<br />
<br />
=== Search for groups ===<br />
<br />
PUT <code>/ajax/group?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An object with search parameters as described in [[#GroupSearch | Group search]].<br />
<br />
{| id="GroupSearch" cellspacing="0" border="1"<br />
|+ align="bottom" | Group search<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find groups. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|}<br />
<br />
Response with timestamp: An array of group objects as described in [[#GroupData | Group data]].<br />
<br />
{| id="GroupData" cellspacing="0" border="1"<br />
|+ align="bottom" | Group data<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || ID<br />
|-<br />
| display_name || String || Display name<br />
|-<br />
| name || String || Name with character restrictions<br />
|-<br />
| members || Array || The array contains identifier of users that are member of the group.<br />
|}<br />
<br />
=== Create a group ===<br />
<br />
introduced 2008-06-12<br />
<br />
PUT <code>/ajax/group?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Group object as described in [[#GroupData | Group data]]. The field id is not present.<br />
<br />
Response: A json objekt with attribute <code>id</code> of the newly created group.<br />
<br />
=== Delete a group ===<br />
<br />
introduced 2008-06-12<br />
<br />
PUT <code>/ajax/group?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the group to delete.<br />
<br />
Request body: An object with the field “id” containing the unique identifier of the group.<br />
<br />
Response: An empty json array if the group was deleted successfully.<br />
<br />
=== Change a group ===<br />
<br />
introduced 2008-06-12<br />
<br />
PUT <code>/ajax/group?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the group to update.<br />
* <code>timestamp</code> – Time stamp of the group to update. If the group was modified after the specified time stamp, then the update must fail. <br />
<br />
Request body: Group object as described in [[#GroupData | Group data]]. Only modified fields are present and the field id is omitted.<br />
<br />
=== Get updates (since v6.18.1) ===<br />
<br />
introduced 2010-09-13<br />
<br />
GET <code>/ajax/group?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested groups.<br />
<br />
Response with timestamp: An array with new, modified and deleted groups. New, modified and deleted groups are represented by JSON objects as described in [[#GroupData | Group data]].<br />
<br />
== Module "resource" ==<br />
<br />
The resource module allows to query available resources. It is mainly used by the dialog for the selection of participants.<br />
<br />
=== Get all resources ===<br />
<br />
GET <code>/ajax/resource?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: An array of resource identifier.<br />
<br />
=== List resources ===<br />
<br />
PUT <code>/ajax/resource?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
<br />
Request body: An array with resources ids.<br />
<br />
Response: An array of resource objects as described in [[#ResourceResponse | Resource response]].<br />
<br />
=== Get a resource ===<br />
<br />
GET <code>/ajax/resource?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The resource id.<br />
<br />
Response: An array of resource objects as described in [[#ResourceResponse | Resource response]].<br />
<br />
=== Search for resources ===<br />
<br />
PUT <code>/ajax/resource?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An object with search parameters as described in [[#ParticipantSearch | Participant search]].<br />
<br />
{| id="ParticipantSearch" cellspacing="0" border="1"<br />
|+ align="bottom" | Participant search<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find resources. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|}<br />
<br />
Response: An array of resource objects as described in [[#ResourceResponse | Resource response]].<br />
<br />
{| id="ResourceResponse" cellspacing="0" border="1"<br />
|+ align="bottom" | Resource Response<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || ID<br />
|-<br />
| display_name || String || Display name<br />
|-<br />
| name || String || internal name<br />
|-<br />
| mailaddress || String || email address<br />
|-<br />
| availability || Boolean || can be false to mark the resource currently unavailable<br />
|-<br />
| description || String || description of the resource<br />
|-<br />
| last_modified || Time || Date and time of the last modification.<br />
|-<br />
| last_modified_utc || Timestamp || Date and time of the last modification.<br />
|}<br />
<br />
=== Create a resource ===<br />
<br />
PUT <code>/ajax/resource?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Resource object as described in [[#ResourceResponse | Resource response]]. The field id is not present.<br />
<br />
Response: An object with attribute <code>id</code> of the newly created resource.<br />
<br />
=== Delete a resource ===<br />
<br />
PUT <code>/ajax/resource?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the resource to delete.<br />
<br />
Request body: An object with the field “id” containing the unique identifier of the resource.<br />
<br />
Response: An empty json array if the resource was deleted successfully.<br />
<br />
=== Delete resources (since v6.22) ===<br />
<br />
PUT <code>/ajax/resource?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the resource to delete.<br />
<br />
Request body: An array of objects with the field “id” containing the unique identifier of the resource.<br />
<br />
Response: An empty json array if the resources were deleted successfully.<br />
<br />
=== Change a resource ===<br />
<br />
PUT <code>/ajax/resource?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the resource to update.<br />
* <code>timestamp</code> – Time stamp of the resource to update. If the resource was modified after the specified time stamp, then the update must fail. <br />
<br />
Request body: Resource object as described in [[#ResourceResponse | Resource response]]. Only modified fields are present and the field id is omitted.<br />
<br />
=== Get updates (since v6.18.1) ===<br />
<br />
introduced 2010-09-13<br />
<br />
GET <code>/ajax/resource?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested resources.<br />
<br />
Response with timestamp: An array with new, modified and deleted resources. New, modified and deleted resources are represented by JSON objects as described in [[#ResourceResponse | Resource response]].<br />
<br />
== Module "infostore" or "Filestore" or "Files" or "Drive" ==<br />
This module has been renamed quite often. Whatever its name, it combines the knowledge database, bookmarks and document storage.<br />
<br />
=== Get all infoitems ===<br />
<br />
GET <code>/ajax/infostore?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for infoitems are defined in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response with timestamp: An array with infoitem data. Each array element describes one infoitem and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedInfoitemData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed infoitem data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 108 || object_permissions || Array || Each element is an object described in [[#ObjectPermissionObject | Object Permission object]] (preliminary, available with 7.8.0).<br />
|-<br />
| 700 || title || String || Title<br />
|-<br />
| 701 || url || String || Link/URL<br />
|-<br />
| 702 || filename || String || Displayed filename of the document.<br />
|-<br />
| 703 || file_mimetype || String || MIME type of the document. The client converts known types to more readable names before displaying them.<br />
|-<br />
| 704 || file_size || Number || Size of the document in bytes.<br />
|-<br />
| 705 || version || Number || Version number of the document. New documents start at 1. Every update increments the version by 1.<br />
|-<br />
| 706 || description || String || Description<br />
|-<br />
| 707 || locked_until || Time || The time until which this item will presumably be locked. Only set if the docment is currently locked, 0 otherwise.<br />
|-<br />
| 708 || file_md5sum || String || MD5Sum of the document. Not yet implemented, so this is currently always empty.<br />
|-<br />
| 709 || version_comment || String || A version comment is used to file a changelog for the file.<br />
|-<br />
| 710 || current_version || Boolean || “true” if this version is the current version “false” otherwise. . Note: This is not writeable<br />
|-<br />
| 711 || number_of_versions || Number || The number of all versions of the infoitem. Note: This is not writeable.<br />
|}<br />
<br />
{| id="ObjectPermissionObject" cellspacing="0" border="1"<br />
|+ align="bottom" | Object Permission object<br />
! Name !! Type !! Value<br />
|-<br />
| bits || Number || A number as described in [[#ObjectPermissionFlags | Object Permission flags]].<br />
|-<br />
| entity || Number || User ID of the user or group to which this permission applies.<br />
|-<br />
| group || Boolean || true if entity refers to a group, false if it refers to a user.<br />
|-<br />
| type || String || The recipient type, i.e. one of "guest", "anonymous" (required if no internal "entity" defined).<br />
|-<br />
| password || String || An additional secret / pin number an anonymous user needs to enter when accessing the share (for type "anonymous", optional) .<br />
|-<br />
| email_address || String || The e-mail address of the recipient (for type "guest").<br />
|-<br />
| display_name || String || The display name of the recipient (for type "guest", optional).<br />
|-<br />
| contact_id || String || The object identifier of the corresponding contact entry if the recipient was chosen from the address book (for type "guest", optional).<br />
|-<br />
| contact_folder || String || The folder identifier of the corresponding contact entry if the recipient was chosen from the address book (for type "guest", required if "contact_id" is set).<br />
|-<br />
| expiry_date || Time || The end date / expiration time after which the share link is no longer accessible (for type "guest" or "anonymous", optional).<br />
|}<br />
<br />
{| id="ObjectPermissionFlags" cellspacing="0" border="1"<br />
|+ align="bottom" | Object Permission flags<br />
! Bits !! Value<br />
|-<br />
| 0 || The numerical value indicating no object permissions.<br />
|-<br />
| 1 || The numerical value indicating read object permissions.<br />
|-<br />
| 2 || The numerical value indicating write object permissions. This implicitly includes the “read” permission (this is no bitmask).<br />
|-<br />
| 4 || The numerical value indicating delete object permissions. This implicitly includes the “read” and “write” permission (this is no bitmask).<br />
|}<br />
<br />
=== Get a list of infoitems ===<br />
<br />
PUT <code>/ajax/infostore?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for infoitems are defined in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
<br />
Request body: An array with object IDs of requested infoitems.<br />
<br />
Response with timestamp: An array with infoitem data. Each array element describes one infoitem and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get updated infoitems ===<br />
<br />
GET <code>/ajax/infostore?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for infoitems are defined in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested infoitems.<br />
* <code>ignore</code> (optional) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
<br />
Response with timestamp: An array with new, modified and deleted infoitems. New and modified infoitems are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted infoitems (should the <code>ignore</code> parameter be ever implemented) would be identified by their object IDs as plain strings, without being part of a nested array.<br />
<br />
=== Get an infoitem ===<br />
<br />
GET <code>/ajax/infostore?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested infoitem.<br />
* <code>version</code> (optional) – If present the infoitem data describes the given version. Otherwise the current version is returned <br />
<br />
Response with timestamp: An object containing all data of the requested infoitem. The fields of the object are listed in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. The field id is not included.<br />
<br />
=== Search infoitems ===<br />
<br />
PUT <code>/ajax/infostore?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields as per tables [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>start</code> (optional) – The start index (inclusive) in the ordered search, that is requested.<br />
* <code>end</code> (optional) – The last index (inclusive) from the ordered search, that is requested.<br />
<br />
Request body: An Object as described in [[#SearchContacts | Search contacts]].<br />
<br />
=== Get an infoitem document ===<br />
<br />
GET <code>/ajax/infostore/[filename]?action=document</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested infoitem.<br />
* <code>folder</code> – Object ID of the infoitem's folder.<br />
* <code>version</code> (optional) – If present the infoitem data describes the given version. Otherwise the current version is returned <br />
* <code>content_type</code>(optional) – If present the response declares the given content_type in the Content-Type header.<br />
<br />
Response body: The raw byte data of the document. The response type for the HTTP Request is set accordingly to the defined mimetype for this infoitem or the content_type given.<br />
<br />
Note: The Filename may be added to the customary infostore path to suggest a filename to a Save-As dialog.<br />
<br />
=== Get a ZIP archive containing the infoitems of a denoted folder (available with v7.6.1) ===<br />
<br />
GET <code>/ajax/infostore/[filename]?action=zipfolder</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the infoitem's folder.<br />
* <code>recursive</code> – <code>true</code> to also include subfolders and their infoitems respectively; otherwise <code>false</code> to only consider the infoitems of specified folder<br />
<br />
Response body: The raw byte data of the ZIP archive. The response type for the HTTP Request is set to <code>application/zip</code>.<br />
<br />
=== Get all versions ===<br />
<br />
GET <code>/ajax/infostore?action=versions</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the infoitem whose versions are requested.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for infoitems are defined in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response with timestamp: An array with infoitem data. Each array element describes one infoitem and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. The timestamp is the timestamp relating to the requested infostore item.<br />
<br />
=== Get multiple documents as a ZIP archive (available with v7.4.0) ===<br />
<br />
GET <code>/ajax/infostore?action=zipdocuments</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>body</code> – A URL-encoded JSON array; see below for details<br />
<br />
Parameter <code>body</code>: A JSON array of JSON object tuples specifying the documents' versions to include in the requested ZIP archive; e.g<br><br />
<pre><br />
[{"id":"61820","folder":"70303"},{"id":"61821","folder":"70303", "version": "1"}]<br />
</pre><br />
The field <code>"version"</code> is optional; if missing it refers to latest/current version.<br><br />
So, a valid parameter would look like:<br />
<pre><br />
...&body=%5B%7B%22id%22%3A%2261820%22%2C%22folder%22%3A%2270303%22%7D%2C%7B%22id%22%3A%2261821%22%2C%22folder%22%3A%2270303%22%2C%22version%22%3A%221%22%7D%5D<br />
</pre><br />
<br />
Response: The download offer for the requested ZIP archive containing specified document versions<br />
<br />
=== Update an infoitem via PUT ===<br />
<br />
PUT <code>/ajax/infostore?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated infoitem.<br />
* <code>timestamp</code> – Timestamp of the updated infoitem. If the infoitem was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. Only modified fields are present.<br />
<br />
=== Update an infoitem via POST ===<br />
<br />
POST <code>/ajax/infostore?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated infoitem.<br />
* <code>timestamp</code> – Timestamp of the updated infoitem. If the infoitem was modified after the specified timestamp, then the update must fail.<br />
* <code>json</code> - Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. Only modified fields are present.<br />
* <code>file</code> – File Metadata as per <input type=”file” /><br />
<br />
Request Body: Body of content-type “multipart/form-data” or “multipart/mixed” containing the above mentioned fields and file-data.<br />
<br />
Response: The response is sent as a HTML document (see introduction).<br />
<br />
=== Create an infoitem via PUT ===<br />
<br />
PUT <code>/ajax/infostore?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. The field id is not included.<br />
<br />
Response: Object ID of the newly created infoitem.<br />
<br />
=== Create an infoitem via POST ===<br />
<br />
POST <code>/ajax/infostore?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>json</code> - Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. The field id is not included.<br />
* <code>file</code> – File metadata as per <input type=”file” /><br />
<br />
Request Body: Body of content-type “multipart/form-data” or “multipart/mixed” containing the above mentioned fields and file-data.<br />
<br />
Response: Object ID of the newly created infoitem. The response is sent as a HTML document (see introduction).<br />
<br />
=== Save an attachment in the infostore ===<br />
<br />
PUT <code>/ajax/infostore?action=saveAs</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>attached</code> – The Object ID of the Object with the attachment<br />
* <code>folder</code> – The Folder ID of the Object with the attachment<br />
* <code>module</code> – The Module type of the Object with the attachment.<br />
* <code>Attachment</code> – The id of the attachement to save.<br />
<br />
Request body: Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. The field id is not included. The fields in this infoitem object override values from the attachment. The folder_id must be given.<br />
<br />
Response: Object ID of the newly created infoitem.<br />
<br />
=== Delete infoitems ===<br />
<br />
PUT <code>/ajax/infostore?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted infoitems.<br />
* <code>hardDelete</code> - Optional, defaults to \"false\". If set to \"true\", the file is deleted permanently. Otherwise, and if the underlying storage supports a trash folder and the file is not yet located below the trash folder, it is moved to the trash folder.<br />
<br />
Request body: An array with objects to delete. The fields for the object are described in [[#FullIdentifierForAnInfostoreDocument|Full identifier for an infostore document]].<br />
<br />
Response: An array with [[]]. <br />
<br />
{| id="FullIdentifierForAnInfostoreDocument" cellspacing="0" border="1"<br />
|+ align="bottom" | Full identifier for an infostore document<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || Object ID<br />
|-<br />
| folder || Number || Folder ID<br />
|}<br />
<br />
=== Delete versions of infostore documents ===<br />
<br />
PUT <code>/ajax/infostore?action=detach</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the base Object<br />
* <code>folder</code> – The Folder of the Object<br />
* <code>timestamp</code> - Timestamp of the infostore object<br />
<br />
Request body: A List of arrays with the version numbers of the infoitems to detach.<br />
<br />
Response: An array with version numbers that were not deleted.<br />
<br />
Note: When the current version of a document is deleted the new current version will be the newest version.<br />
<br />
=== Delete all versions of infostore documents ===<br />
<br />
PUT <code>/ajax/infostore?action=revert</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the base Object<br />
* <code>folder</code> – The Folder of the Object<br />
* <code>timestamp</code> - Timestamp of the infostore object<br />
<br />
Removes all versions of the infostore document leaving only the base object.<br />
<br />
=== Copy an infostore document via PUT ===<br />
<br />
PUT <code>/ajax/infostore?action=copy</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the base Object<br />
* <code>folder</code> – The Folder of the Object<br />
* <code>timestamp</code> - Timestamp of the infostore object<br />
<br />
Request body: Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. Only modified fields are present.<br />
<br />
Response: The id of the newly created object<br />
<br />
Note: Only the fields (and the file) of the current document will be copied. Those fields present in the request are modified accordingly.<br />
<br />
=== Copy an infostore document via POST ===<br />
<br />
POST <code>/ajax/infostore?action=copy</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated infoitem.<br />
* <code>timestamp</code> – Timestamp of the updated infoitem. If the infoitem was modified after the specified timestamp, then the update must fail.<br />
* <code>json</code> - Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. Only modified fields are present.<br />
* <code>file</code> – File Metadata as per <input type=”file” /><br />
<br />
Request Body: Body of content-type “multipart/form-data” or “multipart/mixed” containing the above mentioned fields and file-data.<br />
<br />
Response: The response is sent as a HTML document (see introduction).<br />
<br />
Note: Only the fields (and the file) of the current document will be copied. Those fields present in the request are modified accordingly.<br />
<br />
=== Lock an infoitem ===<br />
<br />
GET <code>/ajax/infostore?action=lock</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the infoitem that should be locked.<br />
* <code>diff</code> (optional) – If present the value is added to the current time on the server (both in ms). The document will be locked until that time. If this parameter is not present, the document will be locked for a duration as configured on the server.<br />
<br />
Response with timestamp: Can only include errors.<br />
<br />
=== Unlock an infoitem ===<br />
<br />
GET <code>/ajax/infostore?action=unlock</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the infoitem that should be unlocked.<br />
<br />
Response with timestamp: Can only contain errors.<br />
<br />
<br />
== Module "Attachments" ==<br />
<br />
The Attachment Module allows file attachments to arbitrary objects. An Attachment always belongs to an object (called 'attached') in a certain folder of a certain module. <br />
<br />
=== Get All Attachments for an Object ===<br />
<br />
GET <code>/ajax/attachment?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>attached</code> – The Object ID of the Object<br />
* <code>folder</code> – The Folder ID of the Object<br />
* <code>module</code> – The Module type of the Object<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for attachment's are defined in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response: An array with attachment data. Each array element describes one attachment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a list of attachments ===<br />
<br />
PUT <code>/ajax/attachment?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for attachments are defined in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]].<br />
* <code>attached</code> – The Object ID of the Object<br />
* <code>folder</code> – The Folder ID of the Object<br />
* <code>module</code> – The Module type of the Object<br />
<br />
Request body: An array of with object IDs of requested tasks.<br />
<br />
Response with timestamp: An array with attachment data. Each array element describes one attachment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Create an Attachment ===<br />
<br />
POST <code>/ajax/attachment?action=attach</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>json_[index]</code> – The JSON representation of an attachment object as described in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]].<br />
* <code>file_[index]</code> – The file metadata as per <input type=file /> upload.<br />
<br />
Note: The JSON Object and file fields describe the corresponding attachment. For ex.: json_0 contains metadata for file_0, json_1 for file_1 and so on. Indexes start with 0.<br />
<br />
Request body: multipart/form-data or multipart/mixed containing the file data of the attached file and the above fields.<br />
<br />
Response: HTML page with javascript callback as per introduction. Contains a JSON-Array of ids of the newly created attachments. The order of the ids corresponds to the indexes in the request.<br />
<br />
{| id="AttachmentObject" cellspacing="0" border="1"<br />
|+ align="bottom" | Attachment Object<br />
! ID !! Name !! Type !! Description<br />
|-<br />
| 800 || folder || Number || The ID of the first Folder in which the attached object resides.<br />
|-<br />
| 801 || attached || Number || The object id of the object this attachement is attached to.<br />
|-<br />
| 802 || module || Number || The Module of this Object Possible Values:<br />
{| cellspacing="0" border="1"<br />
| 1 || Appointment<br />
|-<br />
| 4 || Task<br />
|-<br />
| 7 || Contact<br />
|-<br />
| 137 || Infostore<br />
|}<br />
|-<br />
| 803 || filename || String || The filename of the attached file.<br />
|-<br />
| 804 || file_size || Number || The file size (in bytes) of the attached file.<br />
|-<br />
| 805 || file_mimetype || String || The MIME-Type of the attached file<br />
|-<br />
| 806 || rft_flag || Boolean || If the attachment is a RTF Attachment of Outlook. (Outlook descriptions can be stored as RTF Documents).<br />
|}<br />
<br />
=== Delete Attachment ===<br />
<br />
PUT <code>/ajax/attachment?action=detach</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>attached</code> – The ID of the base Object<br />
* <code>module</code> – The type of the Object<br />
* <code>folder</code> – The Folder of the Object<br />
<br />
Request body: An array with the ids of the attachments to delete.<br />
<br />
=== Get updated attachments ===<br />
<br />
GET <code>/ajax/attachment?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>attached</code> – Object ID of the object to which the attachments are attached.<br />
* <code>module</code> – Module ID (as per [[#AttachmentObject | Attachment object]]) of the attached object.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for attachments are defined in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested infoitems.<br />
ignore (optional) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
<br />
Response with timestamp: An array with new and deleted attachments for the specified object. New attachments are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted attachments (should the <code>ignore</code> parameter be ever implemented) would be identified by their object IDs as plain numbers, without being part of a nested array.<br />
<br />
=== Get an attachment ===<br />
<br />
GET <code>/ajax/attahment?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>attached</code> – Object ID of the object to which the attachments are attached.<br />
* <code>module</code> – Module ID (as per [[#AttachmentObject | Attachment object]]) of the attached object.<br />
* <code>id</code> – Object ID of the requested attachment.<br />
<br />
Response with timestamp: An object containing all data of the requested attachment. The fields of the object are listed in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]]. <br />
<br />
=== Get an attachments filedata ===<br />
<br />
GET <code>/ajax/attachment/[filename]?action=document</code><br />
<br />
Parameters:<br />
<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>attached</code> – Object ID of the object to which the attachments are attached.<br />
* <code>module</code> – Module ID (as per [[#AttachmentObject | Attachment object]]) of the attached object.<br />
* <code>id</code> – Object ID of the requested attachment.<br />
* <code>content_type</code> (optional) – If set the responses Content-Type header is set to this value, not the attachements file mime type.<br />
<br />
Response body: The raw byte data of the document. The response type for the HTTP Request is set accordingly to the defined mimetype for this infoitem.<br />
Note: The Filename may be added to the customary infostore path to suggest a filename to a Save-As dialog.<br />
<br />
== Module "reminder" ==<br />
<br />
The reminder module provides the ability to fetch all active reminders for a user between two dates.<br />
<br />
=== Get reminder range ===<br />
<br />
GET <code>/ajax/reminder?action=range</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>end</code> – The End date of the reminder range<br />
<br />
Response: An Array with all reminders which are scheduled until the specified time. Each reminder is described in [[#ReminderResponse | Reminder response]].<br />
<br />
{| id="ReminderResponse" cellspacing="0" border="1"<br />
|+ align="bottom" | Reminder response<br />
! Field !! Type !! Description<br />
|-<br />
| id || Number || The ID of the reminder.<br />
|-<br />
| target_id || Number || The target_id where this reminder is attached to<br />
|-<br />
| alarm || Time || The time of the alarm<br />
|-<br />
| module || Number || The module of the reminder<br />
|-<br />
| servertime || Time || The time on the server<br />
|-<br />
| user_id || Number || The ID of the user.<br />
|-<br />
| last_modified || Time || The last modification timestamp of the reminder<br />
|-<br />
| recurrence_position || Number || The recurrence position for series appointments or 0 if no series<br />
|-<br />
| folder || Number || The ID of the folder through that the object can be read<br />
|-<br />
|}<br />
<br />
=== Delete a Reminder===<br />
<br />
PUT <code>/ajax/reminder?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An object with the field “id”.<br />
<br />
Response body: An JSON array with the id that was not deleted.<br />
<br />
=== Delete Reminders (since v6.22)===<br />
<br />
PUT <code>/ajax/reminder?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An array of objects with the field “id”.<br />
<br />
Response body: An JSON array with the ids that were not deleted.<br />
<br />
=== Remind again (since v6.18.1) ===<br />
<br />
PUT <code>/ajax/reminder?action=remindAgain</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the reminder whose date shall be changed.<br />
<br />
Request body: The JSON representation of the reminder; mainly containing the field “alarm” which provides the new reminder date.<br><br />
E.g. <code>{ "alarm": 1283418027381 }</code><br />
<br />
Response body: The JSON representation of the updated reminder.<br />
<br />
== Module "multiple" ==<br />
<br />
The multiple module allows to bundle multiple requests to most other modules in a single request. Not supported are:<br />
* modules login and multiple,<br />
* POST requests with a multipart encoding (uploads),<br />
* GET requests which do not use an object as described in [[#ResponseBody | Response body]] as response body (downloads).<br />
<br />
=== Multiple requests ===<br />
<br />
PUT <code>/ajax/multiple</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>continue</code> – Specifies whether processing of requests should stop when an error occurs, or whether all request should be processed regardless of errors.<br />
<br />
Request body: An array with request objects. Each request object contains all URI parameters of the "normal" request as fields. The module name of the "normal" request is included in the field module. The parameter session is not included. If the "normal" request has a request body, the object which is represented by that request body is includes as the value of the field data.<br />
<br />
Response: An array with reply objects as described in [[#ResponseBody | Response body]]. The order of reply objects corresponds to the order of requests in the request body. Unlike with all other modules, this response is itself not part of a response object as described in [[#ResponseBody | Response body]].<br />
<br />
== Module "quota" ==<br />
<br />
The filestore module allows accesssing information about the use and quota of the filestore.<br />
<br />
=== Get quota information (Since 7.6.1, Preliminary) ===<br />
<br />
GET <code>/ajax/quota?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>module</code> (optional) – The module identifier to get quota information for, required if <code>account</code> is set.<br />
* <code>account</code> (optional) – The account identifier within the module to get quota information for.<br />
<br />
Response: A JSON object containing the requested quota information. If no <code>module</code> was specified, all defined [[#ModuleQuota | module quotas]] are set in the JSON object, each one mapped to it's module identifier. If the quota from a <code>module</code> was requested, a JSON array containing all [[#AccountQuota | account quotas]] of this module are returned. If both a <code>module</code> and <code>account</code> were requested, a JSON object representing this specific [[#AccountQuota | account auota]] is returned. <br />
<br />
Note: In case there is no quota limitation defined for a module or account, no corresponding JSON object is included in the response. <br />
<br />
<br />
{| id="ModuleQuota" cellspacing="0" border="1"<br />
|+ align="bottom" | Module Quota<br />
! Field !! Type !! Description<br />
|-<br />
| display_name || String || The display name of the module<br />
|-<br />
| accounts|| Array || Each element identifies an account quota within the module, as described in [[#AccountQuota | Account Quota]]<br />
|-<br />
|}<br />
<br />
<br />
{| id="AccountQuota" cellspacing="0" border="1"<br />
|+ align="bottom" | Account Quota<br />
! Field !! Type !! Description<br />
|-<br />
| account_id || String || Identifier of the account<br />
|-<br />
| account_name || String || Name of the account<br />
|-<br />
| countquota || Number || The account's quota limit for the number of items, or not set if not defined<br />
|-<br />
| countuse || Number || The account's actual usage for the number of items, or not set if no count quota defined<br />
|-<br />
| quota || Number || The account's quota limit for the storage in bytes, or not set if not defined<br />
|-<br />
| use || Number || The account's actual usage for the storage in bytes, or not set if no storage quota defined<br />
|-<br />
|}<br />
<br />
<br />
=== Get the filestore usage data ===<br />
<br />
GET <code>/ajax/quota?action=filestore</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: A JSON Object containing the fields “use” and “quota”. “use” represents the uploaded files sizes sum and the field “quota” represents the maximum.<br />
<br />
=== Get the mail usage data ===<br />
<br />
GET <code>/ajax/quota?action=mail</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: A JSON Object containing the fields “use” and “quota”. “use” represents the use mail quota and the field “quota” represents the maximum. -1 represents an unlimited quota.<br />
<br />
== Module "import"==<br />
The module import allows to import specific module data (like Contacts, Tasks or Appointments) in several formats (iCal, vCard, CSV) into a folder. Please note: The callback for all actions of this bundle is callback_import, not callback_$actionname for legacy purposes.<br />
<br />
=== Import CSV ===<br />
POST <code>/ajax/import?action=CSV</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder into which data should be imported. This must be a Contact folder.<br />
* <code>charset</code> (preliminary, since 7.6.2) – Optional. A fixed character encoding to use when parsing the uploaded file, overriding the built-in defaults, following the conventions documented in RFC 2278.<br />
<br />
Request body: A "multipart/form-data" encoded .CSV file. The field name for the file is "file". The column titles of the table are those used within the OX, see column ''Displayed Name'' in [[#DetailedContactData]].<br />
<br />
Response: An array of JSON-Objects, one for each entry in the list, containing: The Object ID of the entry, the Object ID of the folder the data was written into, a timestamp of the modification (in case of error, of modification attempt) and an error in case the data could not be entered.<br />
<br />
=== Import Outlook CSV ===<br />
POST <code>/ajax/import?action=OUTLOOK_CSV</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder into which data should be imported. This must be a Contact folder.<br />
* <code>charset</code> (preliminary, since 7.6.2) – Optional. A fixed character encoding to use when parsing the uploaded file, overriding the built-in defaults, following the conventions documented in RFC 2278.<br />
<br />
Request body: An .CSV file with Windows' default encoding Windows-1252. The column titles of the table may be those used by the English, French or German version of Outlook.<br />
<br />
Response: An array of JSON-Objects, one for each entry in the list, containing: The Object ID of the entry, the Object ID of the folder the data was written into, a timestamp of the modification (in case of error, of modification attempt) and an error in case the data could not be entered.<br />
<br />
=== Import iCAL ===<br />
POST <code>/ajax/import?action=ICAL</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder into which data should be imported. This may be an Appointment or a Task folder. May even be a list containing both.<br />
* <code>suppressNotification</code> – This optional parameter can be used to disable the notifications for new appointments that are imported through the given iCal file. This help keeping the Inbox clean if a lot of appointments need to be imported. The value of this parameter does not matter because only for the existence of the parameter is checked.<br />
* <code>ignoreUIDs</code> – Optional. When set to "true", UIDs are partially ignored during import of tasks and appointments from iCal. Internally, each UID is replaced statically by a random one to preserve possibly existing relations between recurring appointments in the same iCal file, but at the same time to avoid collisions with already existing tasks and appointments.<br />
<br />
Request body: An iCalendar file.<br />
<br />
Response: An array of JSON-Objects, one for each entry in the list, containing: The Object ID of the entry, the Object ID of the folder the data was written into, a timestamp of the modification (in case of error, of modification attempt) and an error in case the data could not be entered, and warnings (under the key "warnings") containing an Array of objects with the warning data, containing all customary error fields.<br />
<br />
=== Import vCard ===<br />
POST <code>/ajax/import?action=VCARD</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder into which data should be imported. This must be a Contact folder.<br />
<br />
Request body: An vCard file, maybe of the formats: vCard 2.1, vCard 3.0 or vCalendar 1.0<br />
<br />
Response: An array of JSON-Objects, one for each entry in the list, containing: The Object ID of the entry, the Object ID of the folder the data was written into, a timestamp of the modification (in case of error, of modification attempt) and an error in case the data could not be entered.<br />
<br />
== Module "export" ==<br />
The module export allows to export specific module data (like Contacts, Tasks or Appointments) from a folder in several formats (iCal, vCard, CSV).<br />
<br />
=== Exporting CSV ===<br />
GET <code>/ajax/export?action=CSV</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder whose contents are to be exported. This must be a Contact folder.<br />
* <code>columns</code> – (optional) Columns to be imported from the given file, given as an array of column numbers. See [[#DetailedContactData | Detailed contact data]] for numbers.<br />
* <code>export_dlists</code> – (optional) toggles whether distribution lists are exported, too. Default is false. Option exists since 7.4.1.<br />
Response: An InputStream containing the file of the MIME type <code>text/csv</code>.<br />
<br />
=== Exporting iCAL ===<br />
GET <code>/ajax/export?action=ICAL</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder whose contents are to be exported. This must be a Calendar folder.<br />
<br />
Response: An InputStream containing the file, of the MIME type <code>text/calendar</code>.<br />
<br />
=== Exporting vCard ===<br />
GET <code>/ajax/export?action=VCARD</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder whose contents are to be exported. This must be a Contact folder.<br />
<br />
Response: An InputStream containing the file, of the MIME type <code>text/x-vcard</code>.<br />
<br />
== Module "sync" ==<br />
The module sync delivers several core API extensions to support common operations used in a mobile synchronization environment.<br />
<br />
=== Clearing a folder's content ===<br />
PUT <code>/ajax/sync?action=refresh_server</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON array containing the folder ID(s) whose content should be cleared. '''NOTE:''' Although the requests offers to clear multiple folders at once it is recommended to clear only one folder per request since if any exception occurs<br />
(e.g. missing permissions) the complete request is going to be aborted.<br />
<br />
Response: A JSON array containing the IDs of folders that could not be cleared due to a concurrent modification. Meaning you receive an empty JSON array if everything worked well.<br />
<br />
== Module "token" (since 7.4.0) ==<br />
The module token delivers several core API extensions to support token based logins.<br />
<br />
=== Get a login token ===<br />
GET <code>/ajax/token?action=acquireToken</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response:<br />
A JSON object with the timestamp of the creation date and a token which can be used to create a new session.<br />
<br />
== Module "mailfilter" ==<br />
The module mailfilter describes how to add, update or delete mail filter rules or to check which actions are supported by the underlying system.<br />
<br />
A detailed description can be found here [[ HTTP_API_MailFilter | Mail Filter HTTP API]]<br />
<br />
== Module "ajax file upload" ==<br />
This module offers to store files in server's dedicated download directory for a configureable amount of time. The files are then accessible for further operations like inline images in (html) mails<br />
<br />
=== Uploading a file ===<br />
POST <code>/ajax/file?action=new</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>module</code> – The module for which the file is uploaded to determine proper upload quota constraints (e.g. "mail", "infostore", etc.).<br />
* <code>type</code> – The file type filter to define which file types are allowed during upload. Currently supported filters are: <code>file=all, text=text/*, media=image OR audio OR video, image=image/*, audio=audio/*, video=video/*, application=application/*</code><br />
<br />
Request body: A common POST request body of MIME type "multipart/*" which holds the file(s) to upload<br />
<br />
Response: A JSON array containing the IDs of the uploaded files. The files are accessible through the returned IDs for future use.<br />
<br />
=== Updating a file's last access timestamp (keep alive) ===<br />
By updating the last access timestamp it's prevented from being deleted from both session and disk storage.<br />
<br />
GET <code>/ajax/file?action=keepalive</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the uploaded file whose timestamp should be updated<br />
<br />
Response: The string "null" in response's data element<br />
<br />
=== Requesting a formerly uploaded file ===<br />
GET <code>/ajax/file?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the uploaded file<br />
<br />
Response: The content of the requested file is directly written into output stream<br />
<br />
== Module "image" ==<br />
This module allows to download images from Open-Xchange server without providing a session ID in request's URL parameters.<br />
<br />
=== Requesting an image ===<br />
Open-Xchange Server supports multiple image sources that are identified through request's path identifier<br />
<br />
* Inline images from mails<br />
** Request path needs to be <code>"/mail/picture"</code><br><br><br />
* Contact profile image<br />
** Request path needs to be <code>"/contact/picture"</code><br><br><br />
* User profile image<br />
** Request path needs to be <code>"/user/picture"</code><br><br><br />
* MP3 cover image<br />
** Request path needs to be <code>"/file/mp3cover"</code><br><br><br />
* Fetch a previously uploaded image using <code>"/ajax/file"</code> interface<br />
** Request path needs to be <code>"/mfile/picture"</code><br><br><br />
<br />
Each image source requires an individual set of required parameters<br />
<br />
==== Inline images from mails ====<br />
GET <code>/mail/picture</code> <br />
<br />
Parameters:<br />
* <code>accountId</code> – The mail account identifier<br />
* <code>folder</code> – The identifier of the folder in which the mail resides<br />
* <code>id</code> – The mail identifier<br />
* <code>uid</code> – The identifier of the image inside the referenced mail<br />
<br />
Response: The content of the requested image is directly written into output stream<br />
<br />
<br />
==== Contact profile images ====<br />
GET <code>/contact/picture</code> <br />
<br />
Parameters:<br />
* <code>folder</code> – The identifier of the folder in which the contact resides<br />
* <code>id</code> – The contact identifier<br />
<br />
Response: The content of the requested image is directly written into output stream<br />
<br />
<br />
==== User profile images ====<br />
GET <code>/user/picture</code> <br />
<br />
Parameters:<br />
* <code>id</code> – The user identifier<br />
<br />
Response: The content of the requested image is directly written into output stream<br />
<br />
<br />
==== MP3 cover image ====<br />
GET <code>/file/mp3cover</code> <br />
<br />
Parameters:<br />
* <code>id</code> – The identifier of the uploaded image<br />
<br />
Response: The content of the requested image is directly written into output stream<br />
<br />
<br />
==== Managed Image File ====<br />
GET <code>/image/mfile/picture</code> <br />
<br />
Parameters:<br />
* <code>uid</code> – The identifier of the uploaded image<br />
<br />
Response: The content of the requested image is directly written into output stream<br />
<br />
== Module "conversion" (preliminary) ==<br />
<br />
A generic module to request data from a data source and to process obtained/submitted data with a data handler. Thus data is converted from a data source by a data handler.<br />
<br />
=== Converting data ===<br />
PUT <code>/ajax/conversion?action=convert</code><br><br />
or<br><br />
POST <code>/ajax/conversion?action=convert</code> <br />
<br />
Parameters: &lt;no parameters required&gt;<br />
<br />
Request body: A [[#ConversionRequest | conversion request]] JSON object containing nested JSON objects for [[#DataSource | data source]] and [[#DataHandler | data handler]]<br />
<br />
<br />
{| id="ConversionRequest" cellspacing="0" border="1"<br />
|+ align="bottom" | Conversion request object<br />
! Field !! Type !! Description<br />
|-<br />
| datasource || JSON object || The data source object.<br />
|-<br />
| datahandler || JSON object || The data handler object.<br />
|-<br />
|}<br />
<br />
<br />
{| id="DataSource" cellspacing="0" border="1"<br />
|+ align="bottom" | Data source object<br />
! Field !! Type !! Description<br />
|-<br />
| identifier || String || The identifier of the data source.<br />
|-<br />
| args || JSON array or JSON object || The '''optional''' name-value-pairs as a single JSON object or a JSON object for each kept inside a JSON array for data source<br />
|-<br />
|}<br />
<br />
<br />
{| id="DataHandler" cellspacing="0" border="1"<br />
|+ align="bottom" | Data handler object<br />
! Field !! Type !! Description<br />
|-<br />
| identifier || String || The identifier of the data handler.<br />
|-<br />
| args || JSON array or JSON object || The '''optional''' name-value-pairs as a single JSON object or a JSON object for each kept inside a JSON array for data handler<br />
|-<br />
|}<br />
<br />
Response: The result of converted data ready as an appropriate JSON response<br />
<br />
==== Saving an ICal email attachment ====<br />
<br />
If an ICal file is attached to an email, its content can be saved as appointments and tasks into given calendar and task folder.<br />
If the fields "com.openexchange.groupware.calendar.confirmstatus" and "com.openexchange.groupware.calendar.confirmmessage" are set, the data handler inserts the appointment with the given status for the user, if the appointment does not exist. If it is already existing, the handler just updates the participant status.<br />
<br />
Data source's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.mail.ical&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.fullname&quot;:&quot;&lt;folder-fullname&gt;&quot;},<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.mailid&quot;:&quot;&lt;mail-id&gt;&quot;},<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.sequenceid&quot;:&quot;&lt;attachment-sequence-id&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Data handler's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.ical&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.groupware.calendar.folder&quot;:&quot;&lt;calendar-folder-id&gt;&quot;},<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.task.folder&quot;:&quot;&lt;task-folder-id&gt;&quot;},<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.calendar.confirmstatus&quot;:&quot;&lt;status&gt;&quot;},<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.calendar.confirmmessage&quot;:&quot;&lt;message&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Response: A JSON array of JSON objects each providing folder and object ID of added appointment/task; e.g. <code>[{&quot;folder_id&quot;:2567, &quot;id&quot;:7689}, ...]</code><br />
<br />
==== Converting an ICal email attachment into JSON objects ====<br />
<br />
If an ICal file is attached to an email, its content can converted to JSON appointments and tasks.<br />
<br />
Data source's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.mail.ical&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.fullname&quot;:&quot;&lt;folder-fullname&gt;&quot;}<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.mailid&quot;:&quot;&lt;mail-id&gt;&quot;}<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.sequenceid&quot;:&quot;&lt;attachment-sequence-id&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Data handler's JSON object.<br><br />
'''Note''' that all arguments are optional: Default is user time zone and zero recurrence position<br><br />
"com.openexchange.groupware.calendar.searchobject" triggers a search for the uid, and replaces the object_id and folder_id with the data of the corresponding ox-object id, if existing. The returned objects are still the ical objects and NOT the ox-objects.<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.ical.json&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.groupware.calendar.timezone&quot;:&quot;&lt;timezone-id&gt;&quot;}<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.calendar.recurrencePosition&quot;:&quot;&lt;recurrence-position&gt;&quot;}<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.calendar.searchobject&quot;:&quot;&lt;true|false&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Response: A JSON array of JSON objects for each appointment/task as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]]/[[##DetailedAppointmentData | Detailed appointment data]]<br />
<br />
==== Saving a VCard email attachment ====<br />
<br />
If a VCard file is attached to an email, its content can be saved as contacts into given contact folder.<br />
<br />
Data source's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.mail.vcard&quot;,<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.fullname&quot;:&quot;&lt;folder-fullname&gt;&quot;},<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.mailid&quot;:&quot;&lt;mail-id&gt;&quot;},<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.sequenceid&quot;:&quot;&lt;attachment-sequence-id&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Data handler's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.contact&quot;,<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.groupware.contact.folder&quot;:&quot;&lt;contact-folder-id&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Response: A JSON array of JSON objects each providing folder and object ID of added contact; e.g. <code>[{&quot;folder_id&quot;:2567, &quot;id&quot;:7689}, ...]</code><br />
<br />
==== Contact(s) attached to a new email as a VCard file ====<br />
<br />
Obtain VCard data from specified contact object(s).<br />
<br />
Data source's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.contact&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;folder&quot;:&quot;&lt;folder-id1&gt;&quot;,&quot;id&quot;:&quot;&lt;id1&gt;&quot;}<br><br />
&nbsp;&nbsp;&nbsp;...<br><br />
&nbsp;&nbsp;&nbsp;{&quot;folder&quot;:&quot;&lt;folder-idn&gt;&quot;,&quot;id&quot;:&quot;&lt;idn&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Get a new email's JSON object with specified VCard data source attached.<br />
<br />
Data handler's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.mail.vcard&quot;<br><br />
&nbsp;&quot;args&quot;:[]<br><br />
}<br><br />
</code><br />
<br />
Response: A [[#DetailedMailData | mail]] JSON object.<br />
<br />
== Module "search" (preliminary) ==<br />
<br />
The search module is an enhancement to each search request as an optional JSON object via PUT method to filter elements; e.g.<br />
<br />
<code><br />
PUT /ajax/contacts?action=all&...<br />
<br />
{"filter":{search-term-object}}<br />
</code><br />
<br />
This section describes the syntax of the optional JSON object representing the search term.<br><br />
In general the structure of a search term is in prefix notation; meaning the operator is written before its operands:<br />
<br />
<code>{"operation":"equals","operands":[...]}</code><br />
<br />
Moreover there are two different types of a search terms:<br />
* A single search term<br />
* A composite search term<br />
<br />
A single search term reflects an operation which cannot hold nested search terms as operands; e.g. "equals". In opposite to this a composite search term holds one or more nested search terms as operands; e.g. "not" or the logical junctors "and"/"or".<br />
<br />
By now the following operations are supported:<br />
* composite operations<br />
** "and" - The AND junctor<br />
** "or" - The OR junctor<br />
** "not" - Negation<br />
* single operations<br />
** "equals" - Equals comparison<br />
** "lt" - Less-than comparison<br />
** "gt" - Greater-than comparison<br />
<br />
Furthermore following operand types are supported for single search terms:<br />
* Column - Providing a name referring to a field/column<br />
* Constant - A constant<br />
<br />
Example of an EQUALS search term:<br><br />
<code><br />
{"operation":"equals","operands":[{"type":"column","value":"first_name"},"Jane"]}<br />
</code><br />
<br />
Example of an OR search term:<br><br />
<code><br />
{"operation":"or","operands":<br><br />
&nbsp;[<br><br />
&nbsp;&nbsp;{"operation":"equals","operands":[{"type":"column","value":"first_name"},"Jane"]},<br><br />
&nbsp;&nbsp;{"operation":"gt","operands":[{"type":"column","value":"birthday"},"1975-05-01"]}<br><br />
&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
<br />
Refer to object data tables introduced by different modules to know which field names are supported; e.g. for tasks it is [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]], and [[#DetailedTaskData | Detailed task data]].<br />
<br />
== Module "search" (alternative suggestion, still preliminary) ==<br />
<br />
The search module is an enhancement to each search request as an optional JSON object via PUT method to filter elements; e.g.<br />
<br />
<code><br />
PUT /ajax/contacts?action=all&...<br />
<br />
{"filter":<i>[search term]</i>}<br />
</code><br />
<br />
This section describes the syntax of the optional JSON object representing the search term.<br />
In general the structure of a search term is in prefix notation; meaning the operator is written before its operands:<br />
<br />
<code>[">", 5, 2]</code><br />
<br />
The available operators are:<br />
* Comparison operators ">", "<", "=", "<=", ">=", "<>"<br />
* logic operators "not", "and", "or"<br />
<br />
Comparison operators have exactly two operands. Each operand can be either a field name or a constant. A field name is an object with the member "field" specifying the field name, e.g. <code>{ field: "first_name" }</code>. The available field names depend on the searched module. Primitive JSON types are interpreted as constants. Arrays are not valid operands for comparison operators.<br />
<br />
The logic operator "not" has exactly one operand, the other logic operators can have any number of operands. Each operand must be an array representing a nested search expression.<br />
<br />
== Module "mail account" (available with v6.12) ==<br />
<br />
The mail account module is used to manage multiple mail accounts held by a user.<br />
<br />
=== Get All mail accounts ===<br />
<br />
GET <code>/ajax/account?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for mail account's are defined in [[#MailAccountData | mail account data]].<br />
<br />
Response: An array with attachment data. Each array element describes one mail account and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a mail account ===<br />
<br />
GET <code>/ajax/account?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the account to return.<br />
<br />
Response: A JSON object representing the desired mail account. See [[#MailAccountData | mail account data]].<br />
<br />
{| id="MailAccountData" cellspacing="0" border="1"<br />
|+ align="bottom" | Mail account data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 1001 || id || Number || Account ID<br />
|-<br />
| 1002 || login || String || The login.<br />
|-<br />
| 1003 || password || String || The (optional) password.<br />
|-<br />
| 1004 || mail_url || String || The mail server URL; e.g. "imap://imap.somewhere.com:143". '''URL is preferred over single fields''' (like mail_server, mail_port, etc.)<br />
|-<br />
| 1005 || transport_url || String || The transport server URL; e.g. "smtp://smtp.somewhere.com:25". '''URL is preferred over single fields''' (like transport_server, transport_port, etc.)<br />
|-<br />
| 1006 || name || String || Account's display name.<br />
|-<br />
| 1007 || primary_address || String || User's primary address in account; e.g. "someone@somewhere.com"<br />
|-<br />
| 1008 || spam_handler || String || The name of the spam handler used by account.<br />
|-<br />
| 1009 || trash || String || The name of the default trash folder.<br />
|-<br />
| 1010 || sent || String || The name of the default sent folder.<br />
|-<br />
| 1011 || drafts || String || The name of the default drafts folder.<br />
|-<br />
| 1012 || spam || String || The name of the default spam folder.<br />
|-<br />
| 1013 || confirmed_spam || String || The name of the default confirmed-spam folder.<br />
|-<br />
| 1014 || confirmed_ham || String || The name of the default confirmed-ham folder.<br />
|-<br />
| 1015 || mail_server || String || The mail server's hostname or IP address.<br />
|-<br />
| 1016 || mail_port || Number || The mail server's port.<br />
|-<br />
| 1017 || mail_protocol || String || The mail server's protocol. '''Always use basic protocol name.''' E.g. use "imap" instead of "imaps"<br />
|-<br />
| 1018 || mail_secure || Boolean || Whether to establish a secure connection to mail server (SSL, TLS).<br />
|-<br />
| 1019 || transport_server || String || The transport server's hostname or IP address.<br />
|-<br />
| 1020 || transport_port || Number || The transport server's port.<br />
|-<br />
| 1021 || transport_protocol || String || The transport server's protocol. '''Always use basic protocol name.''' E.g. use "smtp" instead of "smtps"<br />
|-<br />
| 1022 || transport_secure || Boolean || Whether to establish a secure connection to transport server (SSL, TLS).<br />
|-<br />
| 1023 || transport_login || String || The transport login. '''Please see "transport_auth" for the handling of this field.'''<br />
|-<br />
| 1024 || transport_password || String || The transport password. '''Please see "transport_auth" for the handling of this field.'''<br />
|-<br />
| 1025 || unified_inbox_enabled || Boolean || If enabled for Unified INBOX<br />
|-<br />
| 1026 || trash_fullname || String || Path to default trash folder. Preferred over "trash"<br />
|-<br />
| 1027 || sent_fullname || String || Path to default sent folder. Preferred over "sent"<br />
|-<br />
| 1028 || drafts_fullname || String || Path to default drafts folder. Preferred over "drafts"<br />
|-<br />
| 1029 || spam_fullname || String || Path to default spam folder. Preferred over "spam"<br />
|-<br />
| 1030 || confirmed_spam_fullname || String || Path to default confirmed-spam folder. Preferred over "confirmed_spam"<br />
|-<br />
| 1031 || confirmed_ham_fullname || String || Path to default confirmed-ham folder. Preferred over "confirmed_ham"<br />
|-<br />
| 1032 || pop3_refresh_rate || Number || The interval in minutes the POP3 account is refreshed<br />
|-<br />
| 1033 || pop3_expunge_on_quit || Boolean || Whether POP3 messages shall be deleted on actual POP3 account after retrieval or not<br />
|-<br />
| 1034 || pop3_delete_write_through || Boolean || If option "pop3_expunge_on_quit" is disabled, this property defines whether a delete in local INBOX also deletes affected message in actual POP3 account<br />
|-<br />
| 1035 || pop3_storage || String || The name of POP3 storage provider, default is "mailaccount"<br />
|-<br />
| 1036 || pop3_path || String || Path to POP3's virtual root folder in storage, default is name of the POP3 account beside default folders<br />
|-<br />
| 1037 || personal || String || The customizable personal part of email address<br />
|-<br />
| 1038 || reply_to || String || The customizable reply-to email address<br />
|-<br />
| 1039 || addresses || String || The comma-separated list of available E-Mail addresses including aliases. !! Only available for primary mail account !!<br />
|-<br />
| 1040 || meta || JSON data || Stores arbitrary JSON data as specified by client associated with the mail account<br />
|-<br />
| 1041 || archive || String || The name of the archive folder. Currently not functional!<br />
|-<br />
| 1042 || archive_fullname || String || The full name of the archive folder. Currently not functional!<br />
|-<br />
| 1043 || transport_auth || String || '''Available since v7.6.1''' Specifies the source for mail transport (SMTP) credentials. Possible values: "mail", "custom", and "none".<br>- "mail" signals to use the same credentials as given in associated mail store (IMAP, POP3).<br>- "custom" signals that individual credentials are supposed to be used (fields "transport_login" and "transport_password" are considered).<br>- "none" means the mail transport does not support any authentication mechanism (rare case!)<br />
|}<br />
<br />
=== Create a new mail account ===<br />
<br />
PUT <code>/ajax/account?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request: A JSON object describing the new account to create. See [[#MailAccountData | mail account data]].<br />
<br />
Response: A JSON object representing the inserted mail account. See [[#MailAccountData | mail account data]].<br />
<br />
=== Update a mail account ===<br />
<br />
PUT <code>/ajax/account?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request: A JSON object identifiying (field ID is present) and describing the account to update. See [[#MailAccountData | mail account data]].<br />
<br />
Response: A JSON object representing the updated mail account. See [[#MailAccountData | mail account data]].<br />
<br />
=== Delete a mail account ===<br />
<br />
PUT <code>/ajax/account?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An array with the ID of the mail account to delete.<br />
<br />
=== Validate a mail account (which shall be created) ===<br />
<br />
PUT <code>/ajax/account?action=validate</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>tree</code> - An optional boolean parameter which indicates whether on successful validation the folder tree shall be returned (NULL on failure) or if set to "false" or missing only a boolean is returned which indicates validation result<br />
<br />
Request: A JSON object describing the new account to validate. See [[#MailAccountData | mail account data]].<br />
<br />
Response: Dependent on optional "tree" parameter a JSON folder object or a boolean value indicating the validation result<br />
<br />
The JSON folder object corresponding to [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
Additionally a field "subfolder_array" is added which contains possible subfolders. This field is missing if a folder contains no subfolders.<br />
<br />
[[Category: OX6]]<br />
<br />
== Module Auto Configuration (since 6.22) ==<br />
<br />
=== Get Auto Configuration ===<br />
<br />
GET <code>/ajax/autoconfig?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>email</code> – Email Adress for which a mail configuration will be discovered.<br />
* <code>password</code> – Corresponding password for the mail account (optional)<br />
<br />
Response: A JSON Object containing the best available settings for an appropriate mail Server for the given email address. The fields are described in [[#MailAccountData | mail account data]]. The Data may be incomplete or even empty.<br />
<br />
== Module "user" (available with v6.14) ==<br />
<br />
The user module is used to access user information.<br />
<br />
=== Get all users ===<br />
<br />
GET <code>/ajax/user?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for users are defined in [[#CommonObjectData | Common object data]], [[#DetailedContactData | Detailed contact data]] and [[#DetailedUserData | Detailed user data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response with timestamp: An array with user data. Each array element describes one user and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedUserData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed user data<br />
! ID !! Displayed name !! Name !! Type !! Value<br />
|-<br />
| 610 || Aliases || aliases || Array || The user's aliases<br />
|-<br />
| 611 || Time zone || timezone || String || The time zone ID.<br />
|-<br />
| 612 || Locale || locale || String || The name of user's entire locale, with the language, country and variant separated by underbars. E.g. "en", "de_DE"<br />
|-<br />
| 613 || Groups || groups || Array || The IDs of user's groups<br />
|-<br />
| 614 || Contact ID || contact_id || Number || The contact ID of the user<br />
|-<br />
| 615 || Login info || login_info || String || The user's login information<br />
|-<br />
| 616 || Guest Created By || guest_created_by || Number || The ID of the user who has created this guest in case this user represents a guest user; it is 0 for regular users (preliminary, available with v7.8.0)<br />
|}<br />
<br />
=== Get a list of users ===<br />
<br />
PUT <code>/ajax/user?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for users are defined in [[#CommonObjectData | Common object data]], [[#DetailedContactData | Detailed contact data]] and [[#DetailedUserData | Detailed user data]].<br />
<br />
Request body: An array of numbers. Each number is the ID of requested user. Since v6.18.1, a <code>null</code> value in the array is interpreted as the currently logged in user.<br />
<br />
Response with timestamp: An array with user data. Each array element describes one user and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a user ===<br />
<br />
GET <code>/ajax/user?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested user. Since v6.18.1, this parameter is optional: the default is the currently logged in user.<br />
<br />
Response with timestamp: An object containing all data of the requested user. The fields of the object are listed in [[#CommonObjectData | Common object data]], [[#DetailedContactData | Detailed contact data]] and [[#DetailedUserData | Detailed user data]].<br />
<br />
=== Update a user ===<br />
<br />
PUT <code>/ajax/user?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated user.<br />
* <code>timestamp</code> – Timestamp of the updated user. If the user was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: User object as described in [[#CommonObjectData | Common object data]], [[#DetailedContactData | Detailed contact data]] and [[#DetailedUserData | Detailed user data]]. Only modified fields are present.<br />
<br />
'''Note''': "timezone" and "locale" are the only fields from [[#DetailedUserData | Detailed user data]] which are allowed to be updated.<br />
<br />
Response with timestamp: An empty object.<br />
<br />
=== Search users ===<br />
<br />
PUT <code>/ajax/user?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified. In case of use of column 609 (use count depending order for collected users with global address book) the parameter "order" ist NOT necessary and will be ignored.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Request body: An Object as described in [[#SearchUsers | Search users]].<br />
<br />
{| id="SearchUsers" cellspacing="0" border="1"<br />
|+ align="bottom" | Search users<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find users. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|-<br />
| startletter || String || Search users with the given startletter. If this field is present, the pattern is matched against the user field which is specified by the property contact_first_letter_field on the server (default: last name). Otherwise, the pattern is matched against the display name.<br />
|}<br />
<br />
Alternative request body: An Object as described in [[#SearchUsersAlternative | Search users alternative]].<br />
<br />
{| id="SearchUsersAlternative" cellspacing="0" border="1"<br />
|+ align="bottom" | Search users alternative<br />
! Name !! Type !! Value<br />
|-<br />
| last_name || String || Searches users where the last name match with the given last name.<br />
|-<br />
| first_name || String || Searches users where the first name match with the given first name.<br />
|-<br />
| display_name || String || Searches users where the display name match with the given display name.<br />
|-<br />
| orSearch || Boolean || If set to true, the fields are connected through an OR search habit.<br />
|-<br />
| emailAutoComplete || Boolean || If set to true, results are guaranteed to contain at least one email adress and the search is performed by connecting the relevant fields through an OR search habit.<br />
|}<br />
<br />
Response: An array with user data. Each array element describes one user and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get user attribute (available with v6.20) ===<br />
<br />
GET <code>/ajax/user?action=getAttribute</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – ID of the user. <br />
* <code>name</code> – The attribute name. <br />
<br />
Response without timestamp: A JSON object providing name and value of the requested attribute<br />
<pre><br />
{ "name":"somename", "value":"somevalue"}<br />
</pre><br />
<br />
=== Set user attribute (available with v6.20) ===<br />
<br />
PUT <code>/ajax/user?action=setAttribute</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – ID of the user. <br />
* <code>setIfAbsent</code> - Set to "true" to put the value only if the specified name is not already associated with a value, otherwise "false" to put value in any case<br />
<br />
Request body: A JSON object providing name and value of the attribute. If the <code>"value"</code> field id missing or NULL, the attribute is removed.<br />
<pre><br />
{ "name":"somename", "value":"somevalue"}<br />
</pre><br />
<br />
Response: The boolean value "true" if PUT was successful; otherwise "false"<br />
<br />
== Module "user/me" (available with v7.6.2) ==<br />
<br />
The user/me module is used to access formal information about current user.<br />
<br />
=== Get user information ===<br />
<br />
GET <code>/ajax/user/me</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response with timestamp: A JSON object providing information for current user<br />
<br />
<code><br />
{<br />
"data": {<br />
"context_id": 1234,<br />
"user_id": 5,<br />
"is_context_admin": false,<br />
"login_name": "user5",<br />
"display_name": "User Five"<br />
},<br />
"timestamp": 1400855683800<br />
}<br />
</code><br />
<br />
== Module "OAuth" ==<br />
<br />
The Open-Xchange server can act as an OAuth client (starting with v6.20) or be an OAuth provider itself (starting with v7.8.0). The OAuth module supports both aspects:<br />
<br />
* Manage multiple OAuth accounts for certain online services for a user. The OAuth mechanism allows the Open-Xchange application to act as behalf of this user using previously obtained access tokens granted by user. The according interface is divided into two parts: Account access and service's meta data access.<br />
* Manage granted accesses of external services that can access a users data on his behalf, called "grants".<br />
<br />
=== OAuth account access (available with v6.20) ===<br />
<br />
The OAuth service account access description.<br />
<br />
<br />
==== Get all OAuth accounts ====<br />
<br />
GET <code>/ajax/oauth/accounts?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – The <b>optional</b> service meta data identifier. If missing all accounts of all services are returned; otherwise all accounts of specified service are returned<br />
<br />
Response: An array with account data. Each array element is a JSON object describing an OAuth account as specified in [[#OAuthAccountData | OAuth account data]].<br />
<br />
==== Get an OAuth account ====<br />
<br />
GET <code>/ajax/oauth/accounts?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The account identifier.<br />
<br />
Response: A JSON object describing an OAuth account as specified in [[#OAuthAccountData | OAuth account data]].<br />
<br />
{| id="OAuthAccountData" cellspacing="0" border="1"<br />
|+ align="bottom" | OAuth account<br />
! Field !! Type !! Description<br />
|-<br />
| id || Number || The numeric identifier of the OAuth account.<br />
|-<br />
| displayName || String || The account display name<br />
|-<br />
| serviceId || String || The identifier of the associated service meta data; e.g. <code>"com.openexchange.oauth.twitter"</code><br />
|-<br />
| token || String || The token<br />
|-<br />
| secret || String || The token secret<br />
|-<br />
|}<br />
<br />
==== Delete an OAuth account ====<br />
<br />
PUT <code>/ajax/oauth/accounts?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The account identifier.<br />
<br />
Response: The boolean value "true" if successful<br />
<br />
==== Update an OAuth account ====<br />
<br />
PUT <code>/ajax/oauth/accounts?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The account identifier. May also be provided in request body's JSON OAuth account representation by <code>"id"</code> field.<br />
<br />
Request body: A JSON object providing the OAuth account fields to update. See [[#OauthAccountData | OAuth account data]]. Currently the only values which make sende being updated are <code>"displayName"</code> and the <code>"token"</code>-<code>"secret"</code>-pair.<br />
<br />
Response: The boolean value "true" if successful<br />
<br />
==== Initialize creation of an OAuth account ====<br />
<br />
GET <code>/ajax/oauth/accounts?action=init</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – The service meta data identifier; e.g. <code>"com.openexchange.oauth.twitter"</code><br />
<br />
Response: An JSON representation of the resulting interaction providing needed information to complete account creation. See [[#OauthInteractionData | OAuth interaction data]].<br />
<br />
{| id="OauthInteractionData" cellspacing="0" border="1"<br />
|+ align="bottom" | OAuth interaction<br />
! Field !! Type !! Description<br />
|-<br />
| authUrl || String || The numeric identifier of the OAuth account.<br />
|-<br />
| type || String || The interaction type name; <code>"outOfBand"</code> or <code>"callback"</code><br />
|-<br />
| token || String || The token<br />
|-<br />
| uuid || String || The UUID for this OAuth interaction<br />
|-<br />
|}<br />
<br />
==== Create an OAuth account ====<br />
<br />
Note: This action is typically called by provided call-back URL and is ony intended for manual invocation if "outOfBand" interaction is returned by preceeding <code>/ajax/oauth/account?action=init</code> step.<br />
<br />
PUT <code>/ajax/oauth/accounts?action=create</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module<br />
* <code>oauth_token</code> – The request token from preceeding OAuth interaction<br />
* <code>uuid</code> – The UUID of the preceeding OAuth interaction<br />
* <code>oauth_verfifier</code> – The verifier string which confirms that user granted access<br />
* <code>displayName</code> – The display name for the new account<br />
<br />
Response: A JSON object describing the newly created OAuth account as specified in [[#OAuthAccountData | OAuth account data]].<br />
<br />
=== OAuth service meta data access (available with v6.20) ===<br />
<br />
The OAuth service meta data access description.<br />
<br />
<br />
==== Get all OAuth services' meta data ====<br />
<br />
GET <code>/ajax/oauth/services?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: An array with service data. Each array element is a JSON object describing an OAuth service's meta data as specified in [[#OAuthServiceMetaData | OAuth service meta data]].<br />
<br />
==== Get an OAuth service's meta data ====<br />
<br />
GET <code>/ajax/oauth/services?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The service's identifier.<br />
<br />
Response: A JSON object describing an OAuth service's meta data as specified in [[#OAuthServiceMetaData | OAuth service meta data]].<br />
<br />
{| id="OAuthServiceMetaData" cellspacing="0" border="1"<br />
|+ align="bottom" | OAuth service meta data<br />
! Field !! Type !! Description<br />
|-<br />
| id || Number || The numeric identifier of the OAuth account.<br />
|-<br />
| displayName || String || The account display name<br />
|-<br />
|}<br />
<br />
=== Manage OAuth grants (available with v7.8.0) ===<br />
<br />
==== Get all grants ====<br />
<br />
GET <code>/ajax/oauth/grants?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: A JSON array containing one object for every granted access as specified in [[#OAuthGrants | OAuth grants]].<br />
<br />
{| id="OAuthGrants" cellspacing="0" border="1"<br />
|+ align="bottom" | OAuth grants<br />
! Field !! Type !! Description<br />
|-<br />
| client || Object || A JSON object describing the external service as in [[#OAuthClient | OAuth client]].<br />
|-<br />
| scopes || Array || A translated (according to the users locale) human-readable description for every scope that was granted to the external service.<br />
|-<br />
| date || Time || The time when the access was granted.<br />
|-<br />
|}<br />
<br />
{| id="OAuthClient" cellspacing="0" border="1"<br />
|+ align="bottom" | OAuth client<br />
! Field !! Type !! Description<br />
|-<br />
| id || String || The clients ID.<br />
|-<br />
| name || String || The clients/services name.<br />
|-<br />
| description || String || A description of the client.<br />
|-<br />
| website || String || A URL to the clients website.<br />
|-<br />
| icon || String || A URL or path to obtain the clients icon via the "image" module.<br />
|-<br />
|}<br />
<br />
==== Revoke access ====<br />
<br />
GET <code>oauth/grants?action=revoke</code><br />
<br />
Parameters:<br />
* <code>client</code> - The ID of the client whose access shall be revoked.<br />
<br />
Response: Nothing.<br />
<br />
== Module "JSlob" (available with v6.22) ==<br />
<br />
The JSlob module is used to store&retrieve arbitrary JSON-structured configuration for a single user.<br />
<br />
<br />
=== Get all JSLobs ===<br />
<br />
GET <code>/ajax/jslob?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
<br />
<br />
Response: An array with JSON configurations. Each array element is a JSON object representing a certain configuration consisting if a "id" and "jslob" field. See [[#JSlobData | JSlob data ]]<br />
<br />
{| id="JSlobData" cellspacing="0" border="1"<br />
|+ align="bottom" | JSlob data<br />
! Field !! Type !! Description<br />
|-<br />
| id || String or Number || The identifier of the JSlob.<br />
|-<br />
| jslob || JSON object || The JSON configuration.<br />
|-<br />
|}<br />
<br />
=== List denoted JSLobs ===<br />
<br />
PUT <code>/ajax/jslob?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
<br />
<br />
Request body: A JSON array of JSlob identifiers; e.g. <code>[ "1", "2", … ]</code><br />
<br />
Response: An array with JSON configurations. Each array element is a JSON object representing a certain configuration consisting if a "id" and "jslob" field. See [[#JSlobData | JSlob data ]]<br />
<br />
=== Delete a JSlob ===<br />
<br />
PUT <code>/ajax/jslob?action=set</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
* <code>id</code> – The JSlob identifier.<br />
<br />
<br />
Request body: An empty request body<br />
<br />
Response: Nothing<br />
<br />
=== Store a JSlob ===<br />
<br />
PUT <code>/ajax/jslob?action=set</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
* <code>id</code> – The identifier for the new JSlob to create<br />
<br />
<br />
Request body: A JSON object containing the "path" and "value" of the JSON configuration to store. If "path" is missing the current configuration<br />
is merged with given JSON object.<br />
<br />
Response: Nothing<br />
<br />
=== Update a single value inside a JSlob ===<br />
<br />
PUT <code>/ajax/jslob?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
* <code>id</code> – The identifier for the new JSlob to create<br />
<br />
<br />
Request body: The new value to store inside specified JSlob<br />
<br />
Response: A JSlob representation according to [[#JSlobData | JSlob data ]]<br />
<br />
=== REST-like access to JSlob module ===<br />
<br />
to be done...<br />
<br />
<br />
== Module "freebusy" (available with v6.22.1) ==<br />
<br />
Provides access to free/busy information.<br />
<br />
<br />
=== Get free/busy information ===<br />
<br />
GET <code>/ajax/freebusy?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>participant</code> – The participant to get the free/busy data for. May be either an internal user-, group- or resource-ID, or an e-mail address for external participants.<br />
* <code>from</code> – The lower (inclusive) limit of the requested time-range.<br />
* <code>until</code> – The upper (exclusive) limit of the requested time-range.<br />
* <code>merged</code> (optional) – True or False. Whether to pre-process the free/busy data on the server or not. This includes sorting as well as merging overlapping free/busy intervals.<br />
<br />
Response: An array of free/busy intervals as described in [[#FreeBusyInterval | Free/Busy interval]]<br />
<br />
{| id="FreeBusyInterval" cellspacing="0" border="1"<br />
|+ align="bottom" | Free/Busy interval<br />
! Name !! Type !! Value<br />
|-<br />
| start_date || Time || Start time of the interval.<br />
|-<br />
| end_date || Time || End time of the interval.<br />
|-<br />
| shown_as || Number || The busy status of this interval, one of:<br />
{| cellspacing="0" border="1"<br />
| 1 || unknown<br />
|-<br />
| 1 || reserved<br />
|-<br />
| 2 || temporary<br />
|-<br />
| 3 || absent<br />
|-<br />
| 4 || free<br />
|}<br />
|-<br />
| id || String || Object ID of the corresponding appointment if available.<br />
|-<br />
| folder_id || String || Folder ID of the corresponding appointment if available.<br />
|-<br />
| title || String || Title of the corresponding appointment if available.<br />
|-<br />
| location || String || Location of the corresponding appointment if available.<br />
|-<br />
| full_time || Boolean || True if the corresponding appointment is a whole day appointment, not present otherwise.<br />
|}<br />
<br />
<br />
=== Get a list of free/busy information ===<br />
<br />
PUT <code>/ajax/freebusy?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>from</code> – The lower (inclusive) limit of the requested time-range.<br />
* <code>until</code> – The upper (exclusive) limit of the requested time-range.<br />
* <code>merged</code> (optional) – True or False. Whether to pre-process the free/busy data on the server or not. This includes sorting as well as merging overlapping free/busy intervals.<br />
<br />
Request body: An array of participants to get the free/busy data for. Each participant may be either an internal user-, group- or resource-ID, or an e-mail address for external participants.<br />
<br />
Response: The free/busy data for all requested participants inside a JSON object with the participants as keys. Besides a combined data element for a requested group, all group members are resolved and listed seperately in the result. If the 'merged' view was requested, an additional data element named 'merged' representing a combined view for all requested participants is added to the results implicitly.<br />
<br />
<br />
== Messaging Services ==<br />
<br />
Messaging Services represent a messaging backend. The messaging services add a new folder module "messaging". <br />
<br />
A *Messaging Service* Object has the following structure:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Messaging Service<br />
! Field !! Type !! Description<br />
|-<br />
| id || String || Identifies a messagingService. Usually a String in reverse domain name notation. Example: "com.openexchange.messaging.twitter"<br />
|-<br />
| displayName || String || Human readable display name of the service. Example: "Twitter" <br />
|-<br />
| formDescription || Array || A description for dynamic form fields. Same as in PubSub <br />
|-<br />
| messagingActions || Array || An array of Strings a dynamic set of actions that are possible with messages of this service. Described in detail later on. <br />
|-<br />
|}<br />
<br />
The available JSON calls are:<br />
<br />
GET /ajax/messaging/service?action=all<br />
<br />
* session - A session ID previously obtained from the login module. <br />
<br />
Response: A standard response object containing an array of messaging service objects. <br />
<br />
<br />
GET /ajax/messaging/service?action=get<br />
<br />
* session - A session ID previously obtained from the login module. <br />
* id - The ID of the messaging service to load<br />
<br />
Response: A standard response object containing a messaging service object.<br />
<br />
== Messaging Accounts ==<br />
<br />
A messaging account represents the concrete configuration of an account of a given messaging service.<br />
A *messaging account* has the following structure:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Messaging Account<br />
! Field !! Type !! Description<br />
|-<br />
| id || Number || Identifies a given messaging account. This is not writeable and is generated by the server <br />
|-<br />
| messagingService || String || The messaging service id of the messaging service this account belongs to <br />
|-<br />
| displayName || String || User chosen String to identify a given account. Will also be translated into the folder name of the folder representing the accounts content <br />
|-<br />
| configuration || Object || Configuration data according to the formDescription of the relevant messagingService <br />
|-<br />
|}<br />
<br />
The available JSON calls are:<br />
<br />
PUT /ajax/messaging/account?action=new<br />
<br />
* session - A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON Object describing the account to be created.<br />
Response: A response object containing the new account id as its data.<br />
<br />
<br />
PUT /ajax/messaging/account?action=update<br />
<br />
* session - A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON Object describing the update to the account. Note that the "id" and "messagingService" must always be set.<br />
Response: A response object containing the number 1 as its data on success.<br />
<br />
GET /ajax/messaging/account?action=get<br />
<br />
* session - A session ID previously obtained from the login module.<br />
* messagingService - The messaging service id that the account belongs to<br />
* id - An account ID to load<br />
<br />
Response: A response object containing the JSON Object representing the loaded account as its data.<br />
<br />
GET /ajax/messaging/account?action=delete<br />
<br />
* session - A session ID previously obtained from the login module.<br />
* messagingService - The messaging service id that the account belongs to<br />
* id - An account ID to delete<br />
<br />
Response: A response object containing 1 as its data on success.<br />
<br />
GET /ajax/messaging/account?action=all<br />
<br />
* session - A session ID previously obtained from the login module<br />
* messagingService - (optional) list only those accounts that belong to the given messagingService.<br />
<br />
Response: A response object containing a JSON array of account objects in its data section.<br />
<br />
<br />
== Messaging Messages ==<br />
<br />
A Messaging Message represents a single message. It consists of some metadata, headers and a content. The content attribute varies by the content-type header. <br />
If the content type is text/* it is a string, if it is a multipart/* it is an array of objects, each representing a part of the multipart. If it is anything else<br />
it is considered binary and is a Base64 encoded string (ToDo : This is not smart enough yet. I suppose we'll have to include encoding options for binaries much like in our EAVJSONProposal).<br />
<br />
The folder id of a message follows a predefined format:<br />
<br />
<pre><br />
[messagingService]://[accountId]/[path]<br />
</pre><br />
<br />
for an imaginary example consider: "com.openexchange.messaging.twitter://535/defaultTimeline/directMessages"<br />
<br />
The structure of a Messaging Message is as follows:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Messaging Message<br />
! Field !! Type !! Description<br />
|-<br />
|id ||String || The id of this message. Only unique in the given folder. <br />
|-<br />
|folder ||String || The folder id. <br />
|-<br />
|threadLevel ||Number || The nesting level of this message according to the conversation it's belonged to. May not be set. <br />
|-<br />
|flags ||Number || Bitmask showing the state of this message. The same as in the module "mail". <br />
|-<br />
|receivedDate ||Time || The time this message was received. <br />
|-<br />
|colorLabel ||Number || An arbitrary number marking this message in a certain color. The same as the colorLabel common to all groupware objects (see HTTP API)<br />
|-<br />
|user ||Array || An array of strings. Represents user flags. <br />
|-<br />
|size ||Number || The binary size of this message in bytes. <br />
|-<br />
|picture || String || A string depicting the URL to a picture for this message <br />
|-<br />
|url || String || A string that contains a link to the messages origin. Currently used in RSS messages.<br />
|-<br />
|headers ||JSONObject || A JSON Object of header data. Usually the value is either a String or an Array (if the headers has more than one value). Certain headers are rendered as more complex structures, see the section "Complex Headers". <br />
|-<br />
|content ||String or Array || See introductory note for Messaging Messages. <br />
|-<br />
|}<br />
<br />
The structure of a Multipart Part (an element of the content array in a multipart/* message) is a s follows:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Multipart Element<br />
! Field !! Type !! Description<br />
|-<br />
|sectionId || String || The sectionId of this part.<br />
|-<br />
|headers || JSONObject || Same as above. <br />
|-<br />
|content || String or Array || Same as above. <br />
|-<br />
|}<br />
<br />
Some *Complex Headers* have a structure differing from simple key/value(s) pairs. These are:<br />
<br />
=== Content-Type ===<br />
<br />
The Content-Type header is represented as a JSON Object with the following structure:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Content Type Header<br />
! Field !! Type !! Description<br />
|-<br />
| type || String || The type string (eg. text/plain). This governs the rendering of the content of a message. <br />
|-<br />
| params || Object || An Object with the keys "charset", containing the charset of this message and "name" pointing to the filename this part or message should have. <br />
|-<br />
|}<br />
<br />
When setting the content-type header in a messaging messages generated on the client the header may also be sent in it's short form. The short form is the type followed by a semi-colon separated list of key=value pairs<br />
of the params. For example: "text/plain;charset=utf-8;name=something.txt".<br />
<br />
=== Address Headers ===<br />
<br />
Address headers ( From, To,Cc,Bcc,Reply-To,Resent-Reply-To,Disposition-Notification-To,Resent-To,Sender,Resent-Sender,Resent-To,Resent-Cc,Resent-Bcc ) are formatted as an array of objects, or in case of "From" as a single object, with the attributes *address* and *personal*:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Address Headers<br />
! Field !! Type !! Description<br />
|-<br />
| address || String || The technical part of the address<br />
|-<br />
| personal || String || A displayable description of the addressee. May be unset.<br />
|-<br />
|}<br />
<br />
When setting an address header the header may also be sent by clients in the short form <code>"personal &lt;address&gt;"</code>, for example <code>"Clark Kent &lt;clark.kent@dailyplanet.com&gt;"</code>. <br />
<br />
=== List renderings of Messaging Messages ===<br />
<br />
Actions returning lists of messages usually return only a selection of attributes of a message driven by a "columns" parameter. The columns that are addressable point either to attributes of the top-level message or its headers. <br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Header Equivalence<br />
! Column !! Refers To<br />
|-<br />
| *column* | *refers to* <br />
|-<br />
| id || The id attribute <br />
|-<br />
| folderId || The folder attribute <br />
|-<br />
| contentType || The "Content-Type" header <br />
|-<br />
| from || The "From" header <br />
|-<br />
| to || The "To" header <br />
|-<br />
| cc || The "Cc" header <br />
|-<br />
| bcc || The "Bcc" header <br />
|-<br />
| subject || The "Subject" header <br />
|-<br />
| size || The size attribute <br />
|-<br />
| sentDate || The "Date" header <br />
|-<br />
| receivedDate || The receivedDate attribute <br />
|-<br />
| flags || The flags attribute <br />
|-<br />
| threadLevel || The threadLevel attribute <br />
|-<br />
| dispositionNotificationTo || The "Disposition-Notification-To" header. <br />
|-<br />
| priority || The "X-Priority" header <br />
|-<br />
| colorLabel || The colorLabel attribute <br />
|-<br />
| url || The url attribute <br />
|-<br />
| body || The content attribute <br />
|-<br />
| headers || The headers attribute <br />
|-<br />
|}<br />
<br />
=== JSON calls ===<br />
<br />
GET /ajax/messaging/message?action=get<br />
<br />
* session - A session ID previously obtained from the login module<br />
* id - The ID of the message to load<br />
* peek - (optional) if set to "true" the read/unread state of the message will not change. Defaults to false.<br />
* folder - The folder id<br />
<br />
Response: An Object representing the loaded message.<br />
<br />
PUT /ajax/messaging/message?action=send<br />
<br />
* session - A session ID previously obtained from the login module<br />
* recipients - (optional) If set the message is sent to the given list of recipients, otherwise this defaults to the "To" header of the message.<br />
<br />
Request Body: The Request Body should contain the JSON Object representing the message to be sent.<br />
Response: "1" as the data of a regular response on success.<br />
<br />
GET or PUT /ajax/messaging/message?action=perform<br />
<br />
* session - A session ID previously obtained from the login module<br />
* action - The messaging action to invoke<br />
* id - The id of the message the action should be invoked on. Only used on actions of type "storage".<br />
* folder - The folder id.<br />
<br />
Request Body: On actions of type "message" the body should contain the JSON representation of the message the action should be applied to.<br />
Response: Either 1 if no further user interaction is needed or a messaging message that, after having the user modify it has to be supplied back to the follower action of this action.<br />
<br />
Thus, to invoke a messaging action of type "storage" the folder and id are needed. Messaging actions of type "message" need a folder and message in the body. <br />
Messaging actions of type "none" need a messaging message and account. <br />
<br />
==== List style requests ====<br />
<br />
GET /ajax/messaging/message?action=all<br />
<br />
* session - A session ID previously obtained from the login module<br />
* columns - A comma-separated list of column names.<br />
* sort - (optional) A column to sort by.<br />
* order - (optional) The order direction. "asc" for ascending or "desc" for descending. Defaults to "asc"<br />
* folder - The folder id.<br />
<br />
Response: An array of arrays with the sub arrays containing the values of the fields asked for by the the columns parameter.<br />
<br />
<br />
PUT /ajax/messaging/messages?action=list<br />
<br />
* session - A session ID previously obtained from the login module<br />
* columns - A comma-separated list of column names.<br />
<br />
Request Body: An array of arrays with the folder and id as elements each identifying a message. <br />
<br />
Response: An array of arrays with the sub arrays containing the values of the fields asked for by the columns parameter.<br />
<br />
== Snippet module (available with v7.0.0/v6.22.0) ==<br />
<br />
=== Gets a certain snippet by identifier ===<br />
<br />
GET /ajax/snippet?action=get<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
<br />
Response:<br />
The snippet's JSON representation; e.g.<br />
<br />
{<br />
"id": "1",<br />
"type": "signature",<br />
"props": {"x-custom": "any value"},<br />
"module": "mail",<br />
"displayname": "My signature",<br />
"misc": {"foo": "bar"},<br />
"createdby": 17,<br />
"content": "-- \\nMy name and position here",<br />
"accountid": 0,<br />
"shared": false,<br />
"files":<br />
[<br />
{<br />
"mimetype": "image/png; name=pic.png",<br />
"filename": "pic.png",<br />
"id": "46f49f8a-40d5-4f29-8bc9-728f3420864c",<br />
"size": 6074<br />
}<br />
]<br />
}<br />
<br />
=== Gets all snippets associated with the current user and context ===<br />
<br />
GET /ajax/snippet?action=all<br />
<br />
* session - The session identifier<br />
* type - Optional CSV of types to filter by; e.g. "signature"<br />
<br />
Response:<br />
A JSON array of snippets' JSON representations<br />
<br />
<br />
<br />
=== Gets certain snippets by identifiers ===<br />
<br />
GET /ajax/snippet?action=list<br />
<br />
* session - The session identifier<br />
<br />
Request body:<br />
A JSON array of snippet identifiers<br />
<br />
Response:<br />
A JSON array of snippets' JSON representations<br />
<br />
<br />
<br />
=== Gets a certain snippet's attachment by identifier ===<br />
<br />
GET /ajax/snippet?action=getattachment<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
* attachmentid - The attachment identifier<br />
<br />
Response:<br />
The attachment's raw data<br />
<br />
<br />
<br />
=== Creates a new snippet ===<br />
<br />
PUT /ajax/snippet?action=new<br />
<br />
* session - The session identifier<br />
<br />
Request body:<br />
A JSON representation of the snippet.<br />
Excluding its attachments (see attach/detach actions)<br />
<br />
Response:<br />
The created snippet's identifier<br />
<br />
<br />
<br />
=== Updates a certain snippet by identifier ===<br />
<br />
PUT /ajax/snippet?action=update<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
<br />
Request body:<br />
A JSON representation of the snippet providing the fields that should be changed.<br />
Excluding its attachments (see attach/detach actions)<br />
<br />
Response:<br />
The updated snippet's JSON representation<br />
<br />
<br />
<br />
=== Deletes a certain snippet by identifier ===<br />
<br />
PUT /ajax/snippet?action=delete<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier (otherwise provide one or more identifiers through request body's JSON array)<br />
<br />
Request body:<br />
A JSON array of identifiers denoting the snippets to delete<br />
<br />
Response:<br />
An empty/dummy result (don't care)<br />
<br />
<br />
<br />
=== Attaches one or more files to an existing snippet ===<br />
<br />
POST /ajax/snippet?action=attach<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
<br />
Request body:<br />
Multipart form data providing the upload files to attach to the snippet.<br />
<br />
Response:<br />
The updated snippet's identifier<br />
<br />
<br />
<br />
=== Detaches open or more files from an existing snippet ===<br />
<br />
PUT /ajax/snippet?action=detach<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
<br />
Request body:<br />
A JSON array providing the identifiers of the attachments to remove from snippet<br />
<br />
Response:<br />
The updated snippet's identifier<br />
<br />
== Picture Halo (since 7.4.1) ==<br />
<br />
GET /appsuite/api/halo/contact/picture<br />
* session - (optional) falls back to the public session cookie<br />
* internal_userid - (optional) The internal user id of a user whose picture you want to load<br />
* userid - (optional) an alias for internal_userid<br />
* user_id - (optional) an alias for internal_userid<br />
* id - (optional) a contact id<br />
* email - (optional) an email to search for. Will pick global address book matches before regular matches. After that picks the most recently changed contact<br />
* email1 - (optional) an alias for email<br />
* email2 - (optional) another email address to use to find matches<br />
* email3 - (optional) and yet another email address to use to find matches<br />
<br />
''At least one of the optional search parameters should be set. All parameters are connected by OR during the search. More specific parameters like user_id or id are prioritized in case of multiple matches.''<br />
<br />
Response:<br />
The picture with proper eTag and caching headers set, or an HTTP Status 404 response, if no picture could be found.<br />
<br />
<br />
== Module "capabilities" (available with v7.4.2) ==<br />
<br />
Provides access to capabilities, i.e. modules or features that are available on the backend and the user has access to.<br />
<br />
=== Get a capability ===<br />
<br />
GET <code>/ajax/capabilities?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The identifier of the capability<br />
<br />
Response: The requested capability as described in [[#Capability| Capability]], if available, otherwise an empty result<br />
<br />
{| id="Capability" cellspacing="0" border="1"<br />
|+ align="bottom" | Capability<br />
! Name !! Type !! Value<br />
|-<br />
| id || String || The identifier of the capability<br />
|-<br />
| attributes || Object || A JSON object holding optional properties of the capability <br />
|}<br />
<br />
=== Get all capabilities ===<br />
<br />
GET <code>/ajax/capabilities?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: An array of capability objects as described in [[#Capability| Capability]].<br />
<br />
<br />
== Module "jump" (available with v7.6.0) ==<br />
<br />
The jump module is used to pass an acquired identity token for an authenticated user from one system to another for a single sign-on.<br />
<br />
=== Acquire an identity token ===<br />
<br />
GET <code>/ajax/jump?action=identityToken</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>system</code> – The identifier for the external service/system<br />
<br />
Response: The acquired identity token wrapped by a simple JSON object as described in [[#Jump| Jump]]<br />
<br />
{| id="Jump" cellspacing="0" border="1"<br />
|+ align="bottom" | Jump<br />
! Name !! Type !! Value<br />
|-<br />
| token || String || The identifier of the token<br />
|}<br />
<br />
== Module "find" (preliminary, available with v7.6.1) ==<br />
The Find API consists of calls for performing searches within the modules mail, contacts, calendar, tasks and drive. It was designed to provide an iterative approach where the search criteria can be refined step-wise until the desired items are found. The starting point is always an "autocomplete" request, that suggests possible search filters based on a users input. Those filters are grouped into categories, called "facets". A facet may provide one or more "values" with every value being a possible filter. A client is meant to remember every value that was selected by a user and include it within the following "autocomplete" and "query" requests, while "query" performs the actual search and returns the found items.<br />
<br />
Every request is bound to a module that must be specified via the URL-Parameter "module". Possible modules are<br />
* mail<br />
* contacts<br />
* calendar<br />
* tasks<br />
* drive<br />
<br />
=== General assumptions ===<br />
Some of the objects returned by the server contain former user input. A client must never interpret strings as HTML but always as plain text to be not vulnerable for CSS attacks!<br />
<br />
=== Calls ===<br />
The find API provides two dedicated calls under the servlet path <code>find</code>:<br />
* action=autocomplete<br />
* action=query<br />
<br />
=== Facets ===<br />
The style of a facet is responsible for how the according object is structured, how it is handled on the server-side and how the client has to handle it.<br />
We distinguish three styles of facets:<br />
* simple<br />
* default<br />
* exclusive<br />
<br />
Every facet value contains an embedded "filter" object. The filter must not be changed by the client, it has to be seen as a black-box. Instead the filters<br />
of selected facet values have to be copied and sent to the server with the subsequent requests.<br />
<br />
==== Simple Facets ====<br />
A simple facet is a special facet that has exactly one value. The facets<br />
type and its value are strictly coupled, in a way that a display name for both,<br />
facet and value would be redundant. A simple facet generally denotes a logical field like<br />
'phone number'. Internally this logical field can map to several internal fields<br />
(e.g. 'phone_private', 'phone_mobile', 'phone_business'). In clients the facet as<br />
a whole can be displayed as a single item. Example: "Search for 'term' in field 'phone<br />
number'".<br />
<br />
<br />
{| id="Facet Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Facet Structure<br />
! Field !! Type !! Description<br />
|-<br />
| style || "simple" || Denotes that this is a facet of style simple<br />
|-<br />
| id || <string> || The id of this facet. Unique within an autocomplete response. Can be used to distinguish and filter certain facets.<br />
|-<br />
| name || <string> || A displayable (and localized) name for this facet. If absent, an "item" attribute is present.<br />
|-<br />
| item (optional) || <object> || A more complex object to display this facet. Attributes are "name", "detail" (optional) and "image_url" (optional).<br />
|-<br />
| filter || <object> || The filter to refine the search.<br />
|-<br />
| flags || <array> || An array of flags, represented as strings.<br />
|}<br />
<br />
Example:<br />
<pre><br />
{<br />
"id":"global",<br />
"style":"simple",<br />
"name":"test",<br />
"filter":{},<br />
"flags":[]<br />
}<br />
</pre><br />
<br />
==== Default Facets ====<br />
A default facet contains multiple values and may be present<br />
multiple times in search requests to filter results by a combination of different<br />
values (e.g. "mails with 'foo' and 'bar' in subject").<br />
<br />
Facet values may be one- or two-dimensional. A one-dimensional value can be displayed as is and contains an according filter object.<br />
A two-dimensional value contains an array "options" with every option defining different semantics of how the value is used to filter the search results.<br />
<br />
{| id="Default Facet Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Facet Structure<br />
! Field !! Type !! Description<br />
|-<br />
| style || "default" || Denotes that this is a facet of style default<br />
|-<br />
| id || <string> || The id of this facet. Unique within an autocomplete response. Can be used to distinguish and filter certain facets.<br />
|-<br />
| name || <string> || A displayable (and localized) name for this facet. If absent, an "item" attribute is present.<br />
|-<br />
| item (optional) || <object> || A more complex object to display this facet. Attributes are "name", "detail" (optional) and "image_url" (optional).<br />
|-<br />
| values || <array> || An array of facet values.<br />
|-<br />
| flags || <array> || An array of flags, represented as strings.<br />
|}<br />
<br />
{| id="Default Facet Value Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Value Structure<br />
! Field !! Type !! Description<br />
|-<br />
| id || <string> || The values id. Unique within one facet.<br />
|-<br />
| name || <string> || A displayable (and localized) name for this value. May be superseded with an "item" attribute. Absent if the value contains options.<br />
|-<br />
| item (optional) || <object> || A more complex object to display this value. Attributes are "name", "detail" (optional) and "image_url" (optional). Absent if the value contains options.<br />
|-<br />
| filter || <object> || The filter to refine the search. Absent if the value contains options.<br />
|-<br />
| options (optional) || <array> || An array of options.<br />
|}<br />
<br />
{| id="Default Facet Option Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Option Structure<br />
! Field !! Type !! Description<br />
|-<br />
| id || <string> || The options id. Unique within a set of options.<br />
|-<br />
| name || <string> || The displayable (and localized) name for this option.<br />
|-<br />
| filter || <object> || The filter to refine the search.<br />
|-<br />
|}<br />
<br />
Example:<br />
<pre><br />
{<br />
"id":"contacts",<br />
"style":"default",<br />
"name":"People",<br />
"values":[<br />
{<br />
"id":"contact/424242669/525793",<br />
"item":{<br />
"name":"Test Usere2123",<br />
"detail":"testuse1212r@example.com"<br />
},<br />
"options":[<br />
{<br />
"id":"from",<br />
"name":"From",<br />
"filter":{}<br />
},<br />
{<br />
"id":"to",<br />
"name":"To",<br />
"filter":{}<br />
},<br />
{<br />
"id":"all",<br />
"name":"From/To",<br />
"filter":{}<br />
}<br />
]<br />
}<br />
],<br />
"flags":[]<br />
}<br />
</pre><br />
<br />
==== Exclusive Facets ====<br />
An exclusive facet is a facet where the contained values are<br />
mutually exclusive. That means that the facet must only be present once<br />
in an autocomplete or query request.<br />
<br />
Facet values may be one- or two-dimensional. A one-dimensional value can be displayed as is and contains an according filter object.<br />
A two-dimensional value contains an array "options" with every option defining different semantics of how the value is used to filter the search results. <br />
<br />
{| id="Exclusive Facet Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Facet Structure<br />
! Field !! Type !! Description<br />
|-<br />
| style || "exclusive" || Denotes that this is a facet of style exclusive<br />
|-<br />
| id || <string> || The id of this facet. Unique within an autocomplete response. Can be used to distinguish and filter certain facets.<br />
|-<br />
| name || <string> || A displayable (and localized) name for this facet. If absent, an "item" attribute is present.<br />
|-<br />
| item (optional) || <object> || A more complex object to display this facet. Attributes are "name", "detail" (optional) and "image_url" (optional).<br />
|-<br />
| options || <array> || An array of facet values.<br />
|-<br />
| flags || <array> || An array of flags, represented as strings.<br />
|}<br />
<br />
{| id="Exclusive Facet Value Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Value Structure<br />
! Field !! Type !! Description<br />
|-<br />
| id || <string> || The values id. Unique within one facet.<br />
|-<br />
| name || <string> || A displayable (and localized) name for this value. May be superseded with an "item" attribute. Absent if the value contains options.<br />
|-<br />
| item (optional) || <object> || A more complex object to display this value. Attributes are "name", "detail" (optional) and "image_url" (optional). Absent if the value contains options.<br />
|-<br />
| filter || <object> || The filter to refine the search. Absent if the value contains options.<br />
|-<br />
| options (optional) || <array> || An array of options.<br />
|}<br />
<br />
{| id="Exclusive Facet Option Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Option Structure<br />
! Field !! Type !! Description<br />
|-<br />
| id || <string> || The options id. Unique within a set of options.<br />
|-<br />
| name || <string> || The displayable (and localized) name for this option.<br />
|-<br />
| filter || <object> || The filter to refine the search.<br />
|-<br />
|}<br />
<br />
Example:<br />
<pre><br />
{<br />
"id":"time",<br />
"style":"exclusive",<br />
"name":"Time",<br />
"options":[<br />
{<br />
"id":"last_week",<br />
"name":"last week",<br />
"filter":{}<br />
},<br />
{<br />
"id":"last_month",<br />
"name":"last month",<br />
"filter":{}<br />
},<br />
{<br />
"id":"last_year",<br />
"name":"last year",<br />
"filter":{}<br />
}<br />
],<br />
"flags":[]<br />
}<br />
</pre><br />
<br />
<br />
==== Active Facets ====<br />
Every value that has been selected by a user must be remembered and provided with every subsequent request. The representation of a facet within a request body differs from the one within an autocomplete response. We call those "active facets". Their representation is independent from their style.<br />
<br />
{| id="Active Facet Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Active Facet Structure<br />
! Field !! Type !! Description<br />
|-<br />
| facet || <string> || The id of the according facet.<br />
|-<br />
| value || <string> || The id of the according value. Must always be copied from the value object, not from a possibly according option (in the two-dimensional case).<br />
|-<br />
| filter || <object> || The filter object, copied from the value or option.<br />
|}<br />
<br />
<br />
=== Configuration ===<br />
According to the users configuration, some restrictions may apply that have to be heeded by clients. Those restrictions can be retrieved via the "config" or the "jslob" modules. The following restrictions may apply:<br />
<br />
* A user might have limited access to modules and therefore the Find API may only serve requests for a subset of all possible modules. The configuration object may contain an object with key "modules". Its value is an array containing all module identifiers that the user is allowed to use.<br />
<br />
* Some facets can be mandatory, i.e. they must be pre-defined by the client and provided with every request. Whether a facet is mandatory or not is decided on a per-module basis. The configuration object may contain an object with key "mandatory". Every facet that may be mandatory is specified via its id in that object (e.g. mandatory.folder). The value of such a key is either an array containing all module identifiers, where the facet is mandatory or null, if it is not manadatory in any module.<br />
<br />
* Due to performance reasons the service provider can enforce a minimium number of characters that have to be provided before an autocomplete request may be issued. That property is called "minimumQueryLength" and its value is an integer that specifies the minimum number of characters. If a client does not heed this property, the server will respond with an error if the provided user input is too short.<br />
<br />
==== Config Example ====<br />
<pre><br />
GET http://localhost/appsuite/api/config/search?session={{session}}<br />
Response:<br />
{<br />
"data": {<br />
"mandatory": {<br />
"folder": [<br />
"mail"<br />
]<br />
},<br />
"modules": [<br />
"mail",<br />
"contacts",<br />
"calendar",<br />
"tasks",<br />
"drive"<br />
]<br />
}<br />
}<br />
<br />
GET http://localhost/appsuite/api/config/minimumSearchCharacters?session={{session}}<br />
Response:<br />
{<br />
"data": 0<br />
}<br />
</pre><br />
<br />
==== JSLob Example ====<br />
<pre><br />
GET http://localhost/appsuite/api/jslob?action=get&id=io.ox/core&session={{session}}<br />
Response:<br />
{<br />
"data": {<br />
"id": "io.ox/core",<br />
"tree": {<br />
"search": {<br />
"modules": [<br />
"mail",<br />
"contacts",<br />
"calendar",<br />
"tasks",<br />
"drive"<br />
],<br />
"mandatory": {<br />
"folder": [<br />
"mail"<br />
]<br />
},<br />
"minimumQueryLength": 0<br />
}<br />
}<br />
}<br />
}<br />
</pre><br />
<br />
=== autocomplete ===<br />
Mandatory URL parameters:<br />
* action=autocomplete<br />
* module=<module-name><br />
* session=<session-id><br />
<br />
Optional URL parameters:<br />
* limit=<int> - The maximum number of values returned per facet<br />
<br />
Request body: A JSON object containing the users input (specified as "prefix"), already selected facets and possible options.<br />
<br />
<br />
==== Example ====<br />
<pre><br />
PUT http://localhost/appsuite/api/find?action=autocomplete&module=mail&limit=3&session={{session}}<br />
{<br />
"prefix":"test", <br />
"facets":[<br />
{<br />
"facet":"folder",<br />
"value":"default0/INBOX"<br />
}<br />
],<br />
"options":{<br />
"timezone":"UTC",<br />
"admin":false<br />
}<br />
}<br />
<br />
Response:<br />
{<br />
"data":{<br />
"facets":[<br />
{<br />
"id":"global",<br />
"style":"simple",<br />
"name":"test",<br />
"filter":{},<br />
"flags":[]<br />
}, <br />
{<br />
"id":"contacts",<br />
"style":"default",<br />
"name":"People",<br />
"values":[<br />
{<br />
"id":"contact/424242669/525793",<br />
"item":{<br />
"name":"Test Usere2123",<br />
"detail":"testuse1212r@example.com"<br />
},<br />
"options":[<br />
{<br />
"id":"from",<br />
"name":"From",<br />
"filter":{}<br />
},<br />
{<br />
"id":"to",<br />
"name":"To",<br />
"filter":{}<br />
},<br />
{<br />
"id":"all",<br />
"name":"From/To",<br />
"filter":{}<br />
}<br />
]<br />
}<br />
],<br />
"flags":[]<br />
},<br />
{<br />
"id":"time",<br />
"style":"exclusive",<br />
"name":"Time",<br />
"options":[<br />
{<br />
"id":"last_week",<br />
"name":"last week",<br />
"filter":{}<br />
},<br />
{<br />
"id":"last_month",<br />
"name":"last month",<br />
"filter":{}<br />
},<br />
{<br />
"id":"last_year",<br />
"name":"last year",<br />
"filter":{}<br />
}<br />
],<br />
"flags":[]<br />
}<br />
]<br />
}<br />
}<br />
</pre><br />
<br />
=== query ===<br />
Mandatory URL parameters:<br />
* action=query<br />
* module=<module-name><br />
* session=<session-id><br />
<br />
Optional URL parameters:<br />
* columns=<column-ids> - A comma-separated list of the module-specific columns that shall be contained in the response items.<br />
<br />
Request body: A JSON object containing the selected facets and possible options. For pagination the keys "start" and "size" can be set.<br />
<br />
==== Example ====<br />
<pre><br />
PUT http://localhost/appsuite/api/find?action=query&module=mail&columns=102,600,601,602,603,604,605,607,608,610,611,614,652&session={{session}}<br />
{<br />
"facets":[<br />
{<br />
"facet":"folder",<br />
"value":"default0/INBOX",<br />
"filter":null<br />
},<br />
{<br />
"facet":"subject",<br />
"value":1409579708116,<br />
"filter":{<br />
"fields":[<br />
"subject"<br />
],<br />
"queries":[<br />
"lorem"<br />
]<br />
}<br />
}<br />
],<br />
"options":{<br />
"timezone":"UTC",<br />
"admin":false<br />
},<br />
"start":0,<br />
"size":101<br />
}<br />
<br />
Response:<br />
{<br />
"data":{<br />
"num_found":-1,<br />
"start":0,<br />
"size":1,<br />
"results":[<br />
{<br />
"color_label":0,<br />
"id":"110458",<br />
"folder_id":"default0/INBOX",<br />
"attachment":false,<br />
"from":[<br />
[<br />
"John Doe",<br />
"john.doe@example.com"<br />
]<br />
],<br />
"to":[<br />
[<br />
"Jane Doe",<br />
"jane.doe@example.com"<br />
]<br />
],<br />
"cc":[<br />
<br />
],<br />
"subject":"Lorem Ipsum",<br />
"size":7501,<br />
"received_date":1408531387000,<br />
"flags":32,<br />
"priority":3,<br />
"account_name":"E-Mail",<br />
"account_id":0<br />
}<br />
]<br />
}<br />
}<br />
</pre><br />
<br />
=== Available Options ===<br />
Every request body may contain an "options" object to finetune some specific behavior. Currently possible options are:<br />
* timezone: <tz-name> - The timezone to use if any dates are returned.<br />
* admin: <boolean> - true to include the context admin if it matches any search criteria. If the context admin shall always be ignored (i.e. not returned), false has to be set.<br />
<br />
=== Possible Flags ===<br />
Every facet may carry one or more flags that describe further aspects of that facet. Currently possible flags are:<br />
* conflicts - Specified in the form of "conflicts:<other-id>". A facet carrying this flag must not be combined with a facet of type <other-id>.<br />
<br />
<br />
== Module "share/management" (preliminary, available with v7.8.0) ==<br />
<br />
Existing shares can be accessed via different actions in the "share/management" module. <br />
<br />
=== Get all shares ===<br />
<br />
GET <code>/ajax/share/management?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>module</code> – (optional) The module identifier to list all shares for.<br />
<br />
Response with timestamp: An array with share data. Each array element is a JSON object as described Share Info.<br />
<br />
{| id="ShareInfo" cellspacing="0" border="1"<br />
|+ align="bottom" | Share Info<br />
! Name !! Type !! Value<br />
|-<br />
| share_url || String || The URL to access the share.<br />
|-<br />
| token || String || The (fully qualified) token of the share target.<br />
|-<br />
| authentication || String || The authentication type used to access the share, one of ''guest_password'', ''anonymous'' or ''anonymous_password''. <br />
|-<br />
| created || Time || The time the share was created. <br />
|-<br />
| created_by || Number || The identifier of the user who created the share. <br />
|-<br />
| last_modified || Time || The time the share was last modified. <br />
|-<br />
| modified_by || Time || The identifier of the user who modified the share. <br />
|-<br />
| target || Object || The share target as described in Share Target <br />
|-<br />
| recipient || Object || Information about the recipient of the share, i.e. the guest user, as described in Share Recipient <br />
|}<br />
<br />
{| id="ShareTarget" cellspacing="0" border="1"<br />
|+ align="bottom" | Share Target<br />
! Name !! Type !! Value<br />
|-<br />
| module || String || The folder's module name, i.e. one of "tasks", "calendar", "contacts", "infostore" <br />
|-<br />
| folder || String || The folder identifier <br />
|-<br />
| item || String || (Optional) The object identifier, in case the share targets a single item <br />
|-<br />
| expiry_date || Time || (Optional) The end date / expiration time after which the share link is no longer accessible. Must be given in milliseconds after 01-01-1970 in the users time zone or the time zone contained as URL parameter <br />
|-<br />
| meta || JSON || Stores arbitrary JSON data as specified by client. <br />
|}<br />
<br />
{| id="ShareRecipient" cellspacing="0" border="1"<br />
|+ align="bottom" | Share Recipient<br />
! Name !! Type !! Value<br />
|-<br />
| type || String || The recipient type, one of ''guest'' or ''anonymous''. <br />
|-<br />
| base_token || String || The base token associated with the guest user. <br />
|-<br />
| password || String || The password to access the share, in case the used authentication mode is ''anonymous_password''. <br />
|-<br />
| email_address || String || The email address of the named guest user, in case the recipient type is ''guest''. <br />
|-<br />
| entity || Number || The identifier of the underlying guest user entity. <br />
|}<br />
<br />
=== Get a share ===<br />
<br />
GET <code>/ajax/share/management?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>token</code> – The (fully qualified) token of the share.<br />
<br />
Response with timestamp: A JSON object as described in Share Info.<br />
<br />
=== Delete shares ===<br />
<br />
PUT <code>/ajax/share/management?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An array containing the tokens of the shares to delete.<br />
<br />
Response with timestamp: An empty JSON result in case of no errors.<br />
<br />
=== Get a link ===<br />
<br />
PUT <code>/ajax/share/management?action=getLink</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON object describing the shares to be created as described in Get a link. It contains an array holding the share "targets" as well as some properties of the guest user to be created.<br />
<br />
Response with timestamp: Basic information about the created share as described in GetALinkResponse.<br />
<br />
{| id="GetALink" cellspacing="0" border="1"<br />
|+ align="bottom" | Get a link<br />
! Name !! Type !! Value<br />
|-<br />
| targets || Array || An array of objects as described in Share Target <br />
|-<br />
| bits || Number || (Optional) A number as described in Permission flags. For single items, the bits for reading, writing and deleting objects in folders are taken into account. At least one of those must grant permissions to all objects, not only own ones. The highest value will be chosen based on the following sequence: delete all > write all > read all. If not set, only read permissions are granted. <br />
|-<br />
| password || String || (Optional) An additional secret / pin number an anonymous user needs to enter when accessing the share <br />
|}<br />
<br />
{| id="GetALinkResponse" cellspacing="0" border="1"<br />
|+ align="bottom" | Get a link response<br />
! Name !! Type !! Value<br />
|-<br />
| url || String || The link to the share<br />
|-<br />
| token || String || The share token as a reference for consecutive requests <br />
|}<br />
<br />
=== Update a link ===<br />
<br />
PUT <code>/ajax/share/management?action=updateLink</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – The last modified timestamp of the share to be updated. Used to detect concurrent modifications.<br />
<br />
Request body: A JSON object describing the share to be updated as described in UpdateALink.<br />
<br />
Response with timestamp: An empty JSON result in case of no errors.<br />
<br />
{| id="UpdateALink" cellspacing="0" border="1"<br />
|+ align="bottom" | Update a link<br />
! Name !! Type !! Value<br />
|-<br />
| token || String || The token of the share to update<br />
|-<br />
| expiry_date || Time || (Optional) The end date / expiration time after which the share link is no longer accessible. Must be given in milliseconds after 01-01-1970 in the users time zone or the time zone contained as URL parameter.<br />
|-<br />
| password || String || (Optional) An additional secret / pin number an anonymous user needs to enter when accessing the share<br />
|-<br />
| bits || Number || (Optional) A number as described in Permission flags. For single items, the bits for reading, writing and deleting objects in folders are taken into account. At least one of those must grant permissions to all objects, not only own ones. The highest value will be chosen based on the following sequence: delete all > write all > read all. If not set, only read permissions are granted.<br />
|-<br />
| meta || JSON || Stores arbitrary JSON data as specified by client<br />
|}<br />
<br />
=== Delete a link ===<br />
<br />
GET <code>/ajax/share/management?action=deleteLink</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>token</code> – The token of the share to delete.<br />
<br />
Response with timestamp: An empty JSON result in case of no errors.<br />
<br />
=== Invite ===<br />
<br />
PUT <code>/ajax/share/management?action=invite</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON object representing the shares to be created as described in Invite Data.<br />
<br />
Response with timestamp: An array of share tokens for all created external recipients. The tokens are in the same order as the recipients in the request array. For internal users and groups a NULL value is set in the array.<br />
<br />
{| id="InviteData" cellspacing="0" border="1"<br />
|+ align="bottom" | Invite data<br />
! Name !! Type !! Value<br />
|-<br />
| targets || Array || An array of objects as described in Share Target <br />
|-<br />
| recipients || Array || An array of objects as described in Invited Recipient<br />
|-<br />
| message || String || (Optional) A custom message that will be contained in the notification mails for guests with mail addresses and password.<br />
|}<br />
<br />
{| id="InvitedRecipient" cellspacing="0" border="1"<br />
|+ align="bottom" | Invited recipient<br />
! Name !! Type !! Value<br />
|-<br />
| type || String || The recipient type, i.e. one of "user", "group", "guest", "anonymous"<br />
|-<br />
| bits || Number || A number as described in Permission flags. For single items, the bits for reading, writing and deleting objects in folders are taken into account. At least one of those must grant permissions to all objects, not only own ones. The highest value will be chosen based on the following sequence: delete all > write all > read all.<br />
|-<br />
| entity || Number || (for type "user" or "group") The user or group identifier of the recipient<br />
|-<br />
| password || String || (for type "anonymous", optional) An additional secret / pin number an anonymous user needs to enter when accessing the share<br />
|-<br />
| email_address || String || (for type "guest") The e-mail address of the recipient<br />
|-<br />
| display_name || String || (for type "guest", optional) The display name of the recipient<br />
|-<br />
| contact_id || String || (for type "guest", optional) The object identifier of the corresponding contact entry if the recipient was chosen from the address book<br />
|-<br />
| contact_folder || String || (for type "guest", required if "contact_id" is set) The folder identifier of the corresponding contact entry if the recipient was chosen from the address book<br />
|}<br />
<br />
== Module "drive" ==<br />
The module <code>drive</code> is used to synchronize files and folders between server and client, using a server-centric approach to allow an easy implementation on the client-side. <br />
<br />
A detailed description can be found in a sepearet article: [[OX_Drive_API|OX Drive API]].<br />
<br />
<br />
== Module "passwordchange" ==<br />
<br />
Users can change their password via the "passwordchange" module. <br />
<br />
=== Update password ===<br />
<br />
Note: The new password will be set without any checks. The client must ensure that it is the password the user wants to set. <br />
<br />
PUT <code>/ajax/passwordchange?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON object as described in PasswordChange.<br />
<br />
Response: An empty JSON result in case of no errors.<br />
<br />
{| id="PasswordChange" cellspacing="0" border="1"<br />
|+ align="bottom" | Password change<br />
! Name !! Type !! Value<br />
|-<br />
| old_password || String || The users' current password<br />
|-<br />
| new_password || String || The new password the user wants to set<br />
|-<br />
|}</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=HTTP_API&diff=19137HTTP API2015-03-03T09:45:15Z<p>Viktor.Pracht: /* Module "folders" */ Explained the scope of capabilities</p>
<hr />
<div>== Introduction ==<br />
<br />
This document defines the Open-Xchange HTTP API which is used by the new AJAX GUI. The first chapter describes general definitions and conventions which apply to all server modules. All other chapters describe individual server modules.<br />
<br />
=== Low level protocol ===<br />
<br />
The client accesses the server through HTTP GET, POST and PUT requests. HTTP cookies are used for authentication and must therefore be processed and sent back by the client as specified by [http://tools.ietf.org/html/rfc6265 RFC 6265]. The HTTP API is accessible at URIs starting with <code>/ajax</code>. Each server module has a unique name and its own sub-namespace with that name below <code>/ajax</code>, e. g. all access to the module "tasks" is via URIs starting with <code>/ajax/tasks</code>.<br />
<br />
Text encoding is always UTF-8. Data is sent from the server to the client as <code>text/javascript</code> and interpreted by the client to obtain an ECMAScript object. The HTTP API uses only a small subset of the ECMAScript syntax. This subset is roughly described by the following BNF:<br />
<br />
Value ::= "null" | Boolean | Number | String | Array | Object<br />
Boolean ::= "true" | "false"<br />
Number ::= see NumericLiteral in ECMA 262 3rd edition<br />
String ::= \"([^"\n\\]|\\["\n\\])*\"<br />
Array ::= "[]" | "[" Value ("," Value)* "]"<br />
Object ::= "{}" | "{" Name ":" Value ("," Name ":" Value)* "}"<br />
Name ::= [A-Fa-f][0-9A-Fa-f_]*<br />
<br />
Numbers are the standard signed integer and floating point numbers. Strings can contain any character, except double quotes, newlines and backslashes, which must be escaped by a backslash. Control characters in strings (other than newline) are not supported. Whitespace is allowed between any two tokens. See [http://json.org JSON] and [http://www.ecma-international.org/publications/standards/Ecma-262.htm ECMA 262, 3<sup>rd</sup> edition] for the formal definition.<br />
<br />
The response body consists of an object, which contains up to four fields as described in [[#ResponseBody | Response body]]. The field <code>data</code> contains the actual payload which is described in following chapters. The fields <code>timestamp</code>, <code>error</code> and <code>error_params</code> are present when data objects are returned, if an error occurred and if the error message contains conversion specifiers, respectively. Following sections describe the contents of these fields in more detail.<br />
<br />
{| id="ResponseBody" cellspacing="0" border="1"<br />
|+ align="bottom" | Response body<br />
! Name !! Type !! Value<br />
|-<br />
| data || Value || Payload of the response.<br />
|-<br />
| timestamp || Timestamp || The latest timestamp of the returned data (see [[HTTP_API#Updates|Updates]]).<br />
|-<br />
| error || String || The translated error message. Present in case of errors.<br />
|-<br />
| error_params || Array || As o 7.4.2: Empty JSON array. Before that: Parameters for the error message that would need to be replaced in the error string (in a printf-format style).<br />
|-<br />
| error_id || String || Unique error identifier to help finding this error instance in the server logs.<br />
|-<br />
| error_desc || String || The technical error message (always English) useful for debugging the problem. Might be the same as error message if there is no more information available<br />
|-<br />
| code || String || Error code consisting of an upper-case module identifier and a four-digit message number, separated by a dash; e.g. "MSG-0012"<br />
|-<br />
| error_stack || Array || If configured (see "com.openexchange.ajax.response.includeStackTraceOnError" in 'server.properties') this field provides the stack trace of associated Java exception represented as a JSON array<br />
|-<br />
| categories || String OR Array || Either a single (String) or list (Array) of upper-case category identifiers to which the error belongs. E.g.<br />
{| cellspacing="0" border="1"<br />
| "USER_INPUT" || An error resulting from wrong or missing input from front-end (e.g. mandatory field missing).<br />
|-<br />
| "CONFIGURATION" || An error related to user/system configuration which denies requested operation.<br />
|-<br />
| "PERMISSION_DENIED" || An error related to insufficient permission settings.<br />
|-<br />
| "TRY_AGAIN" || A requested operation could not be accomplished because a needed resource is temporary down or missing (e.g. imap server rejects connection because of too many established connections).<br />
|-<br />
| "SERVICE_DOWN" || A subsystem or third party service is down and therefore does not respond (e.g. database is down).<br />
|-<br />
| "CONNECTIVITY" || The underlying socket connection is corrupt, empty or closed. Only a temporary error that does not affect the whole system.<br />
|-<br />
| "ERROR" || A programming error which was caused by incorrect program code.<br />
|-<br />
| "CONFLICT" || A concurrent modification.<br />
|-<br />
| "CAPACITY" || The requested operation could not be performed cause an underlying resource is full or busy (e.g. IMAP folder exceeds quota).<br />
|-<br />
| "TRUNCATED" || The given data could not be stored into the database because an attribute contains a too long value.<br />
|-<br />
| "WARNING" || Action was at least partially successful, but a condition occurred that merited a warning<br />
|}<br />
|-<br />
| category || Number || Maintained for legacy reasons: The numeric representation of the first category:<br />
{| cellspacing="0" border="1"<br />
| 1 || An error resulting from wrong or missing input from front-end (e.g. mandatory field missing).<br />
|-<br />
| 2 || An error strictly related to user configuration which denies requested operation.<br />
|-<br />
| 3 || An error related to insufficient permission settings.<br />
|-<br />
| 4 || A requested operation could not be accomplished because a needed resource is temporary down or missing (e.g. imap server rejects connection because of too many established connections).<br />
|-<br />
| 5 || A subsystem or third party service is down and therefore does not respond (e.g. database is down).<br />
|-<br />
| 6 || The underlying socket connection is corrupt, empty or closed. Only a temporary error that does not affect the whole system.<br />
|-<br />
| 8 || A programming error which was caused by incorrect programm code.<br />
|-<br />
| 9 || A concurrent modification.<br />
|-<br />
| 11 || The requested operation could not be performed cause an underlying resource is full or busy (e.g. IMAP folder exceeds quota).<br />
|-<br />
| 12 || The given data could not be stored into the database because an attribute contains a too long value.<br />
|-<br />
| 13 || Action was at least partially successful, but a condition occurred that merited a warning<br />
|}<br />
|}<br />
<br />
Data from the client to the server can be sent in several formats. Small amounts of data are sent as <code>application/x-www-urlencoded</code> in query parameters in the request URI. For POST requests, some or all parameters may be sent in the request body instead of in the URI using any valid encoding for POST requests. Alternatively, some requests specify that data is sent as <code>text/javascript</code> in the body of a PUT request. The format of the request body for PUT requests is the same as for sending data from the server to the client, except that the payload is sent directly, without being wrapped in another object.<br />
<br />
When updating existing data, the client sends only fields that were modified. To explicitly delete a field, the field is sent with the value <code>null</code>. For fields of type <code>String</code>, the empty string <code>""</code> is equivalent to <code>null</code>.<br />
<br />
=== Error handling ===<br />
<br />
If the session of the user times out, if the client doesn't send a session ID or if the session for the specified session ID can not be found then the server returns the above described response object, that contains an error code and an error message. If the request URI or the request body is malformed or incomplete then the server returns the reponse object with an error message, too. In case of internal server errors, especially Java exceptions, or if the server is down, it returns the HTTP status code 503, Service Unavailable. Other severe errors may return other HTTP status values.<br />
<br />
Application errors, which can be caused by a user and are therefore expected during the operation of the groupware, are reported by setting the field error in the returned object, as described in [[#ResponseBody | Response body]]. Since the error messages are translated by the client, they can not be composed of multiple variable parts. Instead, the error message can contain simplified printf()-style conversion specifications, which are replaced by elements from the array in the field error_params. If error_params is not present, no replacement occurs, even if parts of the error message match the syntax of a conversion specification.<br />
<br />
A simplified conversion specification, as used for error messages, is either of the form %s or %''n''$s, where ''n'' is a 1-based decimal parameter index. The conversion specifications are replaced from left to right by elements from error_params, starting at the first element. %s is replaced by the current element and the current index is incremented. %''n''$s is replaced by the ''n''th element and the current index is set to the (''n'' + 1)th element.<br />
<br />
Some error message contain data sizes which must be expressed in Bytes or Kilobytes etc., depending on the actual value. Since the unit must be translated, this conversion is performed by the client. Unfortunately, standard printf()-style formatting does not have a specifier for this kind of translation. Therefore, the conversion specification for sizes is the same as for normal strings, and the client has to determine which parameters to translate based on the error code. The current error codes and the corresponding size parameters are listed in [[#DataSizeParameters | Data size parameters]]<br />
<br />
{| id="DataSizeParameters" cellspacing="0" border="1"<br />
|+ align="bottom" | Data size parameters<br />
! Error code !! Parameter indices<br />
|-<br />
| CON-0101 || 2, 3<br />
|-<br />
| FLS-0003 || 1, 2, 3<br />
|-<br />
| MSG-0065 || 1, 3<br />
|-<br />
| MSG-0066 || 1<br />
|-<br />
| NON-0005 || 1, 2<br />
|-<br />
|}<br />
<br />
<br />
=== Date and time ===<br />
<br />
Dates without time are transmitted as the number of milliseconds between 00:00 UTC on that date and 1970-01-01 00:00 UTC. Leap seconds are ignored, therefore this number is always an integer multiple of 8.64e7.<br />
<br />
Because ECMAScript Date objects have no way to explicitly specify a timezone for calculations, timezone correction must be performed on the server. Dates with time are transmitted as the number of milliseconds since 1970-01-01 00:00 UTC (again, ignoring leap seconds) plus the offset between the ''user's'' timezone and UTC at the time in question. (See the Java method java.util.TimeZone.getOffset(long)). Unless optional URL parameter <code>'''timezone'''</code> is present. Then dates with time are transmitted as the number of milliseconds since 1970-01-01 00:00 UTC (again, ignoring leap seconds) plus the offset between the ''specified'' timezone and UTC at the time in question.<br />
<br />
For some date and time values, especially timestamps, monotonicity is more important than the actual value. Such values are transmitted as the number of milliseconds since 1970-01-01 00:00 UTC, ignoring leap seconds and without timezone correction. If possible, a unique strictly monotonic increasing value should be used instead, as it avoids some race conditions described below.<br />
<br />
This specification refers to these three interpretations of the type Number as separate data types. The types are described in [[#DateAndTimeTypes | Date and time types]].<br />
<br />
{| id="DateAndTimeTypes" cellspacing="0" border="1"<br />
|+ align="bottom" | Date and time types<br />
! Type !! Time !! Timezone !! Comment<br />
|-<br />
| Date || No || UTC || Date without time.<br />
|-<br />
| Time || Yes || User || Date and time.<br />
|-<br />
| Timestamp || Yes || UTC || Timestamp or unique sequence number.<br />
|-<br />
|}<br />
<br />
=== Updates ===<br />
<br />
To allow efficient synchronization of a client with changes made by other clients and to detect conflicts, the server stores a timestamp of the last modification for each object. Whenever the server transmits data objects to the client, the response object described in [[#ResponseBody | Response body]] includes the field timestamp. This field contains a timestamp value which is computed as the maximum of the timestamps of all transmitted objects.<br />
<br />
When requesting updates to a previously retrieved set of objects, the client sends the last timestamp which belongs to that set of objects. The response contains all updates with timestamps greater than the one specified by the client. The field timestamp of the response contains the new maximum timestamp value.<br />
<br />
If multiple different objects may have the same timestamp values, then a race condition exists when an update is processed between two such objects being modified. The first, already modified object will be included in the update response and its timestamp will be the maximum timestamp value sent in the timestamp field of the response. If the second object is modified later but gets the same timestamp, the client will never see the update to that object because the next update request from the client supplies the same timestamp value, but only modifications with greater timestamp values are returned.<br />
<br />
If unique sequence numbers can't be used as timestamps, then the risk of the race condition can be at least minimized by storing timestamps in the most precise format and/or limiting update results to changes with timestamp values which are measurably smaller than the current timestamp value.<br />
<br />
=== Editing ===<br />
<br />
Editing objects is performed one object at a time. There may be multiple objects being edited by the same client simulataneously, but this is achieved by repeating the steps required for editing a single object. There is no batch edit or upload command.<br />
<br />
To edit an object, a client first requests the entire object from the server. The server response contains the timestamp field described in the previous section. For in-place editing inside a view of multiple objects, where only already retrieved fields can be changed, retrieving the entire object is not necessary, and the last timestamp of the view is used as the timestamp of each object in it.<br />
<br />
When sending the modified object back to the server, only modified fields need to be included in the sent object. The request also includes the timestamp of the edited object. The timestamp is used by the server to ensure that the object was not edited by another client in the meantime. If the current timestamp of the object is greater than the timestamp supplied by the client, then a conflict is detected and the field error is set in the response. Otherwise, the object gets a new timestamp and the response to the client is empty.<br />
<br />
If the client displays the edited object in a view together with other objects, then the client will need to perform an update of that view immediately after successfully uploading an edited object.<br />
<br />
=== File uploads ===<br />
<br />
File uploads are made by sending a POST request that submits both the file and the needed fields as parts of a request of content-type “multipart/form-data” or “multipart/mixed”. The file metadata are stored in a form field “file” (much like an <input type=”file” name=”file” /> would do). In general a call that allows file uploads via POST will have a corresponding call using PUT to send object data. The JSON-encoded object-data that is send as the body of a corresponding PUT call is, when performed as a POST with file uploads, put into the request parameter “json”.<br />
<br />
Since the upload is performed directly by the browser and is not an Ajax call, the normal callback mechanism for asynchronous Javascript calls cannot be used to obtain the result. For this reason the server responds to these POST calls with a complete HTML page that performs the callback and should not be displayed to the user. The HTML response is functionally equivalent to:<br />
<br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html><br />
<head><br />
<META http-equiv="Content-Type" content=\"text/html; charset=UTF-8\"><br />
<script type="text/javascript"><br />
(parent["callback_<b>action</b>"] || window.opener && window.opener["callback_<b>action</b>"])<br />
(<b>{json}</b>)<br />
</script><br />
</head><br />
</html><br />
<br />
The placeholders <code>{json}</code> is replaced by the response with the timestamp that would be expected from the corresponding PUT method. The placeholder <code>action</code> is replaced by the value of the parameter <code>action</code> of the request (except for the import bundle, which is named "import" instead of the action name for legacy purposes). The content-type of the answer is <code>text/html</code>.<br />
<br />
Non-browser clients don't need to interpret HTML or JavaScript. The JSON data can be recognized by the outermost <code>({</code> and <code>})</code>, where the inner braces are part of the JSON value. For example, the regular expression <code>\((\{.*\})\)</code> captures the entire JSON value in its first capturing group.<br />
<br />
=== Documentation conventions ===<br />
<br />
The rest of this document describes all available requests for each module. A module usually supports several different requests, which are differentiated by the used HTTP method, URI path and supplied URI parameters. The description of each method generally contains the following elements:<br />
* the HTTP method followed by the request URI, inclusing the URI parameter action, which is used to differentiate methods,<br />
* a list of URI parameters which can or must be supplied by the client,<br />
* for PUT requests, content of the request body,<br />
* "Response with timestamp:"if the timestamp field is required in the response body or simply "Response:" if not,<br />
* content of the response payload, unless it is supposed to be empty.<br />
<br />
=== Common object data ===<br />
<br />
This table contains common fields which apply for any module's data type and is referenced throughout this document whenever a module's data type is described.<br />
<br />
{| id="CommonObjectData" cellspacing="0" border="1"<br />
|+ align="bottom" | Common object data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 1 || id || String || Object ID<br />
|-<br />
| 2 || created_by || String || User ID of the user who created this object.<br />
|-<br />
| 3 || modified_by || String || User ID of the user who last modified this object.<br />
|-<br />
| 4 || creation_date || Time || Date and time of creation.<br />
|-<br />
| 5 || last_modified || Time || Date and time of the last modification.<br />
|-<br />
| 20 || folder_id || String || Object ID of the parent folder.<br />
|-<br />
| 100 || categories || String || String containing comma separated the categories. Order is preserved. Changing the order counts as modification of the object. Not present in folder objects.<br />
|-<br />
| 101 || private_flag || Boolean || Overrides folder permissions in shared private folders: When true, this object is not visible to anyone except the owner. Not present in folder objects.<br />
|-<br />
| 102 || color_label || Number || Color number used by Outlook to label the object. The assignment of colors to numbers is arbitrary and specified by the client. The numbers are integer numbers between 0 and 10 (inclusive). Not present in folder objects.<br />
|-<br />
| 104 || number_of_attachments || Number || Number of attachments <br />
|-<br />
| 105 || lastModifiedOfNewestAttachmentUTC || Time || Date and time of the newest attachment written with UTC time zone.<br />
|}<br />
<br />
== Module "login" ==<br />
<br />
The login module is used to obtain a session from the user's login credentials. To understand the details of the different login methods, see the article titled "[[Login variations]]".<br />
<br />
=== Login ===<br />
<br />
POST <code>/ajax/login?action=login</code><br />
<br />
Parameters:<br />
* <code>name</code> – The login name.<br />
* <code>password</code> – The password.<br />
* <code>authId</code> (optional) – Identifier for tracing every single login request passed between different systems in a cluster. The value should be some token that is unique for every login request. This parameter must be given as URL parameter and not inside the body of the POST request.<br />
* <code>client</code> (optional) – Identifier of the client using the HTTP/JSON interface. This is for statistic evaluations what clients are used with Open-Xchange.<br />
* <code>version</code> (optional) – Used version of the HTTP/JSON interface client.<br />
* <code>clientIP</code> (optional) – IP address of the client host for that the session is created. If this parameter is not specified the IP address of the HTTP client doing this request is used.<br />
* <code>clientUserAgent</code> (optional) – Value of the User-Agent header of the client host for that the session is created. If this parameter is not specified the User-Agent of the current HTTP client doing this request is used.<br />
<br />
Response: A JSON object containing the session ID used for all subsequent requests. Additionally a random token is contained to be used for the Easy Login method.<br />
<br />
=== Form Login (since 6.20) ===<br />
<br />
POST <code>/ajax/login?action=formlogin</code><br />
<br />
This request implements a possible login to the web frontend by only using a simple HTML form. An example for such a form can be found in the backend's documentation folder (<code>/usr/share/doc/open-xchange-core</code>) under <code>examples/login.html</code>.<br />
<br />
Parameters:<br />
* <code>login</code> – The login name.<br />
* <code>password</code> – The password.<br />
* <code>authId</code> – Identifier for tracing every single login request passed between different systems in a cluster. The value should be some token that is unique for every login request. This parameter must be given as URL parameter and not inside the body of the POST request.<br />
* <code>client</code> – Identifier of the client using the HTTP/JSON interface. This is for statistic evaluations what clients are used with Open-Xchange. If the autologin request should work the client must be the same as the client sent by the UI in the normal login request.<br />
* <code>version</code> – Used version of the HTTP/JSON interface client.<br />
* <code>autologin</code> – True or false. True tells the UI to issue a store request for the session cookie. This store request is necessary if you want the autologin request not to fail.<br />
* <code>uiWebPath</code> (optional) – Defines another path on the web server where the UI is located. If this parameter is not defined the configured default of the backend is used.<br />
* <code>clientIP</code> (optional) – IP address of the client host for that the session is created. If this parameter is not specified the IP address of the HTTP client doing this request is used.<br />
* <code>clientUserAgent</code> (optional) – Value of the User-Agent header of the client host for that the session is created. If this parameter is not specified the User-Agent of the current HTTP client doing this request is used.<br />
<br />
Response: A redirect to the web UI. The URL of the web UI is either taken from the given parameter or from the configured default of the backend.<br />
<br />
For a complete description of the FormLogin-Process please see [[FormLogin|this documentation]]<br />
<br />
=== Token Login (since 7.0.1) ===<br />
<br />
POST <code>/ajax/login?action=tokenLogin</code><br />
<br />
This request allows every possible client to create a very short living session. This session can then be transferred to any other client preferably a browser entering then the normal web interface. Then the sessions life time will be extended equally to every other session.<br />
<br />
Compared to the login mechanism using the random token, this request is more secure because two tokens are used. One of these tokens is only known to the client and one is generated by the server. Only the combination of both tokens allows to use the session. The combination of both tokens must be done by the client creating the session.<br />
<br />
Parameters:<br />
* <code>login</code> – The login information.<br />
* <code>password</code> – The password.<br />
* <code>clientToken</code> – Client side identifier for accessing the session later. The value should be some token that is unique for every login request.<br />
* <code>authId</code> – Identifier for tracing every single login request passed between different systems in a cluster. The value should be some token that is unique for every login request. This parameter must be given as URL parameter and not inside the body of the POST request.<br />
* <code>client</code> – Identifier of the client using the HTTP/JSON interface. This is for statistic evaluations what clients are used with Open-Xchange. If the autologin request should work the client should be the same as the client sent by the UI in the normal login request. For security considerations it can become necessary to define here the correct client that will use the session.<br />
* <code>version</code> – Version of the HTTP/JSON interface client. Only for statistic evaluations.<br />
* <code>autologin</code> – True or false. True tells the UI to issue a store request for the session cookie. This store request is necessary if you want the autologin request not to fail. This must be enabled on the server and a client can test with the autologin request if it is enabled or not.<br />
* <code>uiWebPath</code> (optional) – Defines another path on the web server where the UI is located. If this parameter is not defined the configured default of the backend is used.<br />
* <code>clientIP</code> (optional) – IP address of the client host for that the session is created. If this parameter is not specified the IP address of the HTTP client doing this request is used. Currently the IP address may change when using the session with both tokens. This can be disabled in future releases for security considerations.<br />
* <code>clientUserAgent</code> (optional) – Value of the User-Agent header of the client host for that the session is created. If this parameter is not specified the User-Agent of the current HTTP client doing this request is used. Currently the User-Agent may change when using the session. This can be disabled in future releases for security considerations.<br />
<br />
<br />
Response: A redirect to the web UI. The URL of the web UI is either taken from the given parameter or from the configured default of the backend. This redirect will only contain the server side token. The client side token sent in the request must be appended by the client creating the session. The final URL must have the form <code style="white-space: nowrap"><var>redirect_URL</var>&amp;clientToken=<var>token</var></code>. Both tokens are necessary to use the session and both tokens must match. Otherwise the session is terminated.<br />
<br />
=== Tokens (since 7.0.1) ===<br />
<br />
POST <code>/ajax/login?action=tokens</code><br />
<br />
This request allows clients to access a session created with the [[#Token_Login_.28since_7.0.1.29 | tokenLogin]] request. When accessing the session its life time is extended equally to every other session.<br />
<br />
Parameters:<br />
* <code>serverToken</code> – Server side identifier for accessing the session. This identifier was created by the server and is contained in the tokenLogin response.<br />
* <code>clientToken</code> – Client side identifier for accessing the session. This identifier was created by the client and passed within the POST data of the tokenLogin request.<br />
* <code>client</code> – Identifier of the client using the HTTP/JSON interface. Currently this request allows to change the client identifier for the session. This eases creating the session because the identifier of the client using the session must not be known. For security considerations it can become necessary to drop this parameter.<br />
<br />
<br />
Response: A JSON object conform to the normal [[#ResponseBody | response body]] contrary to the JSON object of the normal login request. This JSON object contains the session identifier, the login, the identifier and the locale of the user.<br />
<br />
=== Logout ===<br />
<br />
GET <code>/ajax/login?action=logout</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
=== Refresh secret cookie (since 6.18.2) ===<br />
<br />
GET <code>/ajax/login?action=refreshSecret</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
=== Refresh auto-login cookie ===<br />
<br />
GET <code>/ajax/login?action=store</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
=== Redirect ===<br />
<br />
GET <code>/ajax/login;jsessionid=1157370816112.OX1?action=redirect</code><br />
<br />
'''SECURITY WARNING!''' Utilizing this request is '''INSECURE'''! This request allows to access a session with a single one time token. This one time token may be delivered to the wrong client if the protocol has an error or Apache or the load balancer make a mistake. This will cause a wrong user to be in a wrong session. '''IMMEDIATELY''' consider not to use this request anymore. You have been warned. Use instead the FormLogin that does not need to use the redirect request.<br />
<br />
Parameters:<br />
* <code>random</code> – A session random token to jump into the session. This random token is part of the login response. Only a very short configurable time after the login it is allowed to jump into the session with the random token.<br />
* <code>client</code> (optional) – The client can be defined here newly if it is not correct on the login request itself.<br />
* <code>store</code> (optional) – Tells the UI to do a store request after login to be able to use autologin request.<br />
* <code>uiWebPath</code> (optional) – The optional path on the webserver to the UI. If this parameter is not given the configured uiWebPath is used.<br />
<br />
=== Change IP ===<br />
<br />
The following request is especially for integration with systems located in the providers infrastructure. If those systems create a session with the following request the client host IP address in the session can be changed. The IP check for following requests will be done using this newly set client host IP address.<br />
<br />
POST <code>/ajax/login?action=changeip</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>clientIP</code> – New IP address of the client host for the current session.<br />
<br />
Response: A JSON object containing the string "1" as data attribute.<br />
<br />
=== Redeem Token (since 7.4.0)===<br />
<br />
POST <code>/ajax/login?action=redeemToken</code><br />
<br />
Parameters:<br />
* <code>token</code> – The token created with [[#Get_a_login_token | acquireToken]].<br />
* <code>authId</code> – Identifier for tracing every single login request passed between different systems in a cluster. The value should be some token that is unique for every login request. This parameter must be given as URL parameter and not inside the body of the POST request. <br />
* <code>client</code> – Identifier of the client using the HTTP/JSON interface. The client must identifier must be the same for each request after creating the login session. <br />
* <code>secret</code> – The value of the secret string for token logins. This is configured through the tokenlogin-secrets configuration file.<br />
<br />
Response: A JSON object containing the session ID used for all subsequent requests. Additionally a random token is contained to be used for the Easy Login method. If configured within tokenlogin-secrets configuration file even the user password will be returned.<br />
<br />
== Module "config" ==<br />
<br />
The config module is used to retrieve and set user-specific configuration. The configuration is stored in a tree. Each node of the tree has a name and a value. The values of leaf nodes are strings which store the actual configuration data. The values of inner nodes are defined recursively as objects with one field for each child node. The name and the value of each field is the name and the value of the corresponding child node, respectively.<br />
<br />
The namespace looks like the following:<br />
<br />
* <code>/ajax/config/</code><br />
** <code>gui</code> – A string containing GUI-specific settings (currently, it is a huge [[#Low_level_protocol | JSON]] object).<br />
** <code>fastgui</code> - A string containing GUI-specific settings. This is a JSON object that must be kept small for performance.<br />
** <code>context_id</code> - the unique identifier of the context (read-only, added 2008-01-28).<br />
** <code>cookielifetime</code> - the cookie life time in seconds or <code>-1</code> for session cookie (read-only, added 2010-11-16).<br />
** <code>identifier</code> – the unique identifier of the user (read-only).<br />
** <code>contact_id</code> – the unique identifier of the contact data of the user (read-only).<br />
** <code>language</code> – the configured language of the user.<br />
** <code>timezone</code> – the configured timezone of the user.<br />
** <code>availableTimeZones</code> – a JSON object containing all available time zones. The key is the time zone identifier and the value contains its name in users language. (read-only, added 2010-07-08/v6.18).<br />
** <code>calendarnotification</code> - send a mail notification for appointments (deprecated since 2008-12-11)<br />
** <code>tasknotification</code> - send a mail notification for tasks (deprecated since 2008-12-11)<br />
** <code>reloadTimes</code> - Selectable times for GUI reload<br />
** <code>serverVersion</code> - Version string of the server.<br />
** <code>currentTime</code> - User timezone specific long of the current server time.<br />
** <code>maxUploadIdleTimeout</code> - Timeout after that idle uploads are deleted.<br />
** <code>folder/</code> – the standard folder of the user<br />
*** <code>tasks</code> – the standard task folder (read-only)<br />
*** <code>calendar</code> – the standard calendar folder (read-only)<br />
*** <code>contacts</code> – the standard contacts folder (read-only)<br />
*** <code>infostore</code> – the private infostore folder (read-only, since v6.20.1)<br />
*** <code>eas</code> – whether EAS folder selection is enabled (read-only)<br />
** <code>mail/</code> – settings for the email module (deprecated 2008-04-29)<br />
*** <code>addresses</code> – all email addresses of the user including the primary address (read-only, deprecated 2008-04-29)<br />
*** <code>defaultaddress</code> – primary email address of the user (read-only, deprecated 2008-04-29)<br />
*** <code>sendaddress</code> – one email address out of the addresses list that are email sent with. (deprecated 2008-04-29)<br />
*** <code>folder/</code> – the standard email folders (read-only, deprecated 2008-04-29)<br />
**** <code>inbox</code> – identifier of the folder that gets all incoming mails (read-only, deprecated 2008-04-29)<br />
**** <code>drafts</code> – identifier of the folder with the mail drafts (read-only, deprecated 2008-04-29)<br />
**** <code>trash</code> – identifier of the folder with the deleted mails (read-only, deprecated 2008-04-29)<br />
**** <code>spam</code> – identifier of the folder with the spam mails (read-only, deprecated 2008-04-29)<br />
**** <code>sent</code> – identifier of the folder with the sent mails (read-only, deprecated 2008-04-29)<br />
*** <code>htmlinline</code> – activate inlining of HTML attachments. (deprecated 2008-04-29)<br />
*** <code>colorquote</code> – color quoted lines. (deprecated 2008-04-29)<br />
*** <code>emoticons</code> – display emoticons as graphics. (deprecated 2008-04-29)<br />
*** <code>harddelete</code> – delete emails at once. (deprecated 2008-04-29)<br />
*** <code>inlineforward</code> – forward messages as inline or attachment. (deprecated 2008-04-29)<br />
*** <code>vcard</code> – attach vcard when sending mails. (deprecated 2008-04-29)<br />
*** <code>notifyonreadack</code> – notify on read acknowledgement. (deprecated 2008-04-29)<br />
*** <code>msgpreview</code> – show a message preview. (deprecated 2008-04-29)<br />
*** <code>ignorereplytext</code> (deprecated 2008-04-29)<br />
*** <code>nocopytosent</code> – don't put a copy to the sent folder when sending mails. (deprecated 2008-04-29)<br />
*** <code>spambutton</code> - Spam Button should be displayed in GUI or not. (deprecated 2008-04-29)<br />
** <code>participants</code><br />
*** <code>autoSearch</code> - If a search for all users, groups and resources when participant selection dialog is opened. (read-only, added 2008-10-09/SP5)<br />
*** <code>maximumNumberParticipants</code> – Defines the maximum number of participants for appointments and tasks. (read-only, added 2008-10-20/SP5)<br />
*** <code>showWithoutEmail</code> - If external participants without email should be shown.<br />
*** <code>showDialog</code> – Enables participant selection dialog for appointments and tasks. (read-only, added 2008-04-30/SP4)<br />
** <code>availableModules</code> – Contains a JSON array listing all enabled modules for a user. GUI loads Plugins through this list. To get your plugin listed here, create a subtree below <code>modules/</code> without a <code>module</code> subelement or with a subelement containing <code>true</code> (read-only, added 2008-02-25)<br />
** <code>minimumSearchCharacters</code> – Minimum number of characters a search pattern must have to prevent large responses and slow queries. (read-only, added 2008-10-20/SP5)<br />
** <code>modules</code><br />
*** <code>portal</code><br />
**** <code>gui</code> GUI settings for portal module<br />
**** <code>module</code><br />
*** <code>mail</code><br />
**** <code>addresses</code> – all email addresses of the user including the primary address (read-only, added 2008-02-25)<br />
**** <code>appendmailtext</code> – (added 2008-02-25)<br />
**** <code>allowhtmlimages</code> – Alters default setting whether external images contained in HTML content are allowed or not (added 2008-05-27)<br />
**** <code>colorquoted</code> – color quoted lines (added 2008-02-25)<br />
**** <code>contactCollectFolder</code> – contact folder id to save mail addresses from sent mails (added 2008-10-16)<br />
**** <code>contactCollectEnabled</code> – switch contact collection on/off (added 2008-10-16)<br />
**** <code>contactCollectOnMailAccess</code> – enables/disables contact collection for incoming mails. Default is true. (added 2009-09-24)<br />
**** <code>contactCollectOnMailTransport</code> – enables/disables contact collection for outgoing mails. Default is true. (added 2009-09-24)<br />
**** <code>defaultaddress</code> – primary email address of the user (read-only, added 2008-02-25)<br />
**** <code>deletemail</code> – delete emails or move to trash (added 2008-02-25)<br />
**** <code>emoticons</code> – display emoticons as graphics (added 2008-02-25)<br />
**** <code>defaultFolder</code><br />
***** <code>drafts</code> – identifier of the folder with the mail drafts (read-only, added 2008-02-25)<br />
***** <code>inbox</code> – identifier of the folder that gets all incoming mails (read-only, added 2008-02-25)<br />
***** <code>sent</code> – identifier of the folder with the sent mails (read-only, added 2008-02-25)<br />
***** <code>spam</code> – identifier of the folder with the spam mails (read-only, added 2008-02-25)<br />
***** <code>trash</code> – identifier of the folder with the deleted mails (read-only, added 2008-02-25)<br />
**** <code>forwardmessage</code> – forward messages as inline or attachment (added 2008-02-25)<br />
**** <code>gui</code> GUI settings for mail module<br />
**** <code>inlineattachments</code> – activate inlining of HTML attachments (added 2008-02-25)<br />
**** <code>linewrap</code> – (added 2008-02-25)<br />
**** <code>module</code> – if mail module is enabled or not (added 2008-02-25)<br />
**** <code>phishingheaders</code> – header(s) identifying phishing headers (added 2008-05-27)<br />
**** <code>replyallcc</code> – put all recipients on reply all into CC (added 2008-12-16/SP5)<br />
**** <code>sendaddress</code> – one email address out of the addresses list that are email sent with (added 2008-02-25)<br />
**** <code>spambutton</code> – Spam Button should be displayed in GUI or not (added 2008-02-25)<br />
**** <code>vcard</code> – attach vcard when sending mails (added 2008-02-25)<br />
*** <code>calendar</code><br />
**** <code>calendar_conflict</code><br />
**** <code>calendar_freebusy</code><br />
**** <code>calendar_teamview</code><br />
**** <code>gui</code> GUI settings for the calendar module<br />
**** <code>module</code><br />
**** <code>notifyNewModifiedDeleted</code> receive mail notification for new, modified or deleted appointments (added 2008-12-11/SP5)<br />
**** <code>notifyAcceptedDeclinedAsCreator</code> receive mail notification for accepted or declined appointments created by the user (added 2008-12-11/SP5)<br />
**** <code>notifyAcceptedDeclinedAsParticipant</code> receive mail notification for accepted or declined appointments that the user participates (added 2008-12-11/SP5)<br />
**** <code>defaultStatusPrivate</code> Default status for new appointments in private folders, where the user is participant. This does not affect appointments created by this user, which always have the status "accepted". The status are described in [[#UserParticipantObject | User participant object]]. Default is 0:none (added 2009-07-20/6.12)<br />
**** <code>defaultStatusPublic</code> Default status for new appointments in public folders, where the user is participant. This does not affect appointments created by this user, which always have the status "accepted". The status are described in [[#UserParticipantObject | User participant object]]. Default is 0:none (added 2009-07-20/6.12)<br />
*** <code>contacts</code><br />
**** <code>gui</code> GUI settings for the contacts module<br />
**** <code>mailAddressAutoSearch</code> – Define if a search is triggered when the recipient selection dialog is opened or the folder is changed. (read-only, added 2008-10-20/SP5)<br />
**** <code>module</code> True if the contact module is enabled for the current user, false otherwise.<br />
**** <code>singleFolderSearch</code> – True if the current user is allowed to search for contacts only in a single folder. False if contact searches across all folders are allowed. (read-only, added 2009-02-04/SP5 U1)<br />
**** <code>characterSearch</code> – True if the side bar for searching for contacts by a start letter should be displayed. False if the side bar should be hidden. (read-only, added 2009-05-29/6.10)<br />
**** <code>allFoldersForAutoComplete</code> – true if an auto complete search may omit the folder identifier array and search for contacts in all readable folders. This is configured through the contact.properties configuration file. (read-only, added 2010-07-22/v6.18.0)<br />
*** <code>tasks</code><br />
**** <code>gui</code> GUI settings for the tasks module<br />
**** <code>module</code><br />
**** <code>delegate_tasks</code><br />
**** <code>notifyNewModifiedDeleted</code> receive mail notification for new, modified or deleted tasks (added 2008-12-11/SP5)<br />
**** <code>notifyAcceptedDeclinedAsCreator</code> receive mail notification for accepted or declined tasks created by the user (added 2008-12-11/SP5)<br />
**** <code>notifyAcceptedDeclinedAsParticipant</code> receive mail notification for accepted or declined taks that the user participates (added 2008-12-11/SP5)<br />
*** <code>infostore</code><br />
**** <code>gui</code> GUI settings for the infostore module<br />
**** <code>folder</code> – the standard infostore folders (read-only, since 7.6.0)<br />
***** <code>trash</code> – identifier of the default infostore trash folder (read-only, since 7.6.0)<br />
***** <code>pictures</code> – identifier of the default infostore pictures folder (read-only, since 7.8.0)<br />
***** <code>documents</code> – identifier of the default infostore documents folder (read-only, since 7.8.0)<br />
***** <code>music</code> – identifier of the default infostore music folder (read-only, since 7.8.0)<br />
***** <code>videos</code> – identifier of the default infostore videos folder (read-only, since 7.8.0)<br />
***** <code>templates</code> – identifier of the default infostore templates folder (read-only, since 7.8.0)<br />
**** <code>module</code><br />
*** <code>interfaces</code><br />
**** <code>ical</code><br />
**** <code>vcard</code><br />
**** <code>syncml</code><br />
*** <code>folder</code><br />
**** <code>gui</code> UI settings for the folder tree<br />
**** <code>public_folders</code><br />
**** <code>read_create_shared_folders</code><br />
**** <code>tree</code> – Selected folder tree, the user wants to use. Currents trees are 0 for the known OX folder tree and 1 for the new virtual folder tree. (added 2010-04-09/6.18)<br />
*** <code>com.openexchange.extras</code><br />
**** <code>module</code> – Extras link in the configuration (read only, added 2008-04-29)<br />
*** <code>com.openexchange.user.passwordchange</code><br />
**** <code>module</code> – Will load Plug-In which allows to change the Password within the users configuration (read only, added 2008-07-09)<br />
*** <code>com.openexchange.user.personaldata</code><br />
**** <code>module</code> – Will load Plug-In which allows to edit personal contact information within the users configuration (read only, added 2008-07-09)<br />
*** <code>com.openexchange.group</code><br />
**** <code>enabled</code> – Specifies whether the user is allowed to edit groups and loads the corresponding Plug-In. (read only, added 2008-08-08)<br />
*** <code>com.openexchange.resource</code><br />
**** <code>enabled</code> – Specifies whether the user is allowed to edit resources and loads the corresponding Plug-In. (read only, added 2008-08-08)<br />
*** <code>com.openexchange.publish</code><br />
**** <code>enabled</code> – Specifies whether the user is allowed to publish items. (read only, added 2009-05-27)<br />
*** <code>com.openexchange.subscribe</code><br />
**** <code>enabled</code> – Specifies whether the user is allowed to subscribe sources. (read only, added 2009-05-27)<br />
*** <code>olox20</code><br />
**** <code>active</code> – Tells the UI if the user is allowed to use the OXtender for Microsoft Outlook 2. (read only, added 2011-03-15/6.20)<br />
**** <code>module</code> – Is set to false to prevent the UI from trying to load a plugin. (read only, added 2011-03-15/6.20)<br />
***<code>com.openexchange.oxupdater</code><br />
****<code>module</code> – Is true if the OXUpdater package is installed and started. (read only, added 2011-06-01/6.20)<br />
****<code>active</code> – Is true if the user is allowed to download the OXUpdater. Otherwise it's false. (read only, added 2011-06-01/6.20)<br />
***<code>com.openexchange.passwordchange</code><br />
**** <code>showStrength</code> – Show a widget, which displays the current passwort Strength while entering. (default: false)<br />
**** <code>minLength</code> – The minimum length of an entered password. (default: 4)<br />
**** <code>maxLength</code> – The maximum length of an entered password. 0 for unlimited. (default: 0)<br />
**** <code>regexp</code> – Defines the class of allowed special characters as Regular Expression. (default: [^a-z0-9])<br />
**** <code>special</code> – Shows an example of allowed special characters to the user. Should be a subset of "regexp" in a human readable format. (default: $, _, or %) <br />
<br />
=== Get configuration data ===<br />
<br />
GET <code>/ajax/config/path</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: Value of the node specified by path.<br />
<br />
=== Set configuration data ===<br />
<br />
PUT <code>/ajax/config/path</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: The new value of the node specified by path.<br />
<br />
<br />
=== Get a property (since 7.6.2) ===<br />
<br />
GET <code>/ajax/config?action=get_property</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>name</code> – The name of the property to return.<br />
<br />
Response: A JSON response providing the property's name and its value; e.g.<br />
<code><br />
{<br />
"data": {<br />
"name": "com.openexchange.dummy.prop001",<br />
"value": "test1234"<br />
}<br />
}<br />
</code><br />
<br />
=== Set a property (since 7.6.2) ===<br />
<br />
Note: Only allowed for context administrator!<br />
<br />
PUT <code>/ajax/config?action=set_property</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>name</code> – The name of the property to set.<br />
<br />
Request body: A JSON object providing the value to set; e.g<br />
<code><br />
{"value":"test1237"}<br />
</code><br />
<br />
<br />
Response: A JSON response providing the property's name and its new value; e.g.<br />
<code><br />
{<br />
"data": {<br />
"name": "com.openexchange.dummy.prop001",<br />
"value": "test1237"<br />
}<br />
}<br />
</code><br />
<br />
== Module "folders" ==<br />
<br />
The folders module is used to access the OX folder structure.<br />
<br />
=== Special System Folders ===<br />
<br />
Folders with some kind of special.<br />
<br />
{| cellspacing="0" border="1"<br />
! ID !! Type !! Description<br />
|-<br />
| 6 || contacts || System Users<br />
|}<br />
<br />
=== Get root folders ===<br />
<br />
GET <code>/ajax/folders?action=root</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Response: An array with data for all folders at the root level of the folder structure. Each array element describes one folder and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="CommonFolderData" cellspacing="0" border="1"<br />
|+ align="bottom" | Common folder data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 1 || id || String || Object ID<br />
|-<br />
| 2 || created_by || String || User ID of the user who created this object.<br />
|-<br />
| 3 || modified_by || String || User ID of the user who last modified this object.<br />
|-<br />
| 4 || creation_date || Time || Date and time of creation.<br />
|-<br />
| 5 || last_modified || Time || Date and time of the last modification.<br />
|-<br />
| 6 || last_modified_utc || Timestamp || Timestamp of the last modification. Note that the type is Timestamp, not Time. See [[#Date and time]] for details. (added 2008-10-17, with SP5, temporary workaround)<br />
|-<br />
| 20 || folder_id || String || Object ID of the parent folder.<br />
|}<br />
<br />
{| id="DetailedFolderData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed folder data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 300 || title || String || Name of this folder.<br />
|-<br />
| 301 || module || String || Name of the module which implements this folder; e.g. "tasks", "calendar", "contacts", "infostore", or "mail"<br />
|-<br />
| 302 || type || Number || Type of folder:<br />
{| cellspacing="0" border="1"<br />
| 1 || private<br />
|-<br />
| 2 || public<br />
|-<br />
| 3 || shared<br />
|-<br />
| 5 || system folder<br />
|-<br />
| 7 || This type is no more in use (legacy type). Will be removed with a future update!<br />
|-<br />
| 16 || trash<br />
|-<br />
| 20 || pictures<br />
|-<br />
| 21 || documents<br />
|-<br />
| 22 || music<br />
|-<br />
| 23 || videos<br />
|-<br />
| 24 || templates<br />
|}<br />
|-<br />
| 304 || subfolders || Boolean || true if this folder has subfolders.<br />
|-<br />
| 305 || own_rights || Number or String || Permissions which apply to the current user, as described either in [[#PermissionFlags | Permission flags]] or in RFC 2086.<br />
|-<br />
| 306 || permissions || Array || Each element is an object described in [[#PermissionObject | Permission object]].<br />
|-<br />
| 307 || summary || String || Information about contained objects.<br />
|-<br />
| 308 || standard_folder || Boolean || Indicates whether or not folder is marked as a default folder (only OX folder)<br />
|-<br />
| 309 || total || Number || The number of objects in this Folder.<br />
|-<br />
| 310 || new || Number || The number of new objects in this Folder.<br />
|-<br />
| 311 || unread || Number || The number of unread objects in this Folder.<br />
|-<br />
| 312 || deleted || Number || The number of deleted objects in this Folder.<br />
|-<br />
| 313 || capabilities || Number || Bit mask containing information about mailing system capabilites, as described in [[#Capabilities | capabilities]].<br />
|-<br />
| 314 || subscribed || Boolean || Indicates whether this folder should appear in folder tree or not. '''Note:''' Standard folders cannot be unsubscribed.<br />
|-<br />
| 315 || subscr_subflds || Boolean || Indicates whether subfolders should appear in folder tree or not.<br />
|-<br />
| 316 || standard_folder_type || Number || Indicates the default folder type. Zero for non-default folder. See [[#DefaultTypes | Standard folder types]]<br />
|-<br />
| 317 || supported_capabilities || Array || Each element is a String identifying a supported folder capability as described in [[#SupportedCapabilities | supported capabilities]]. Only applicable for non-mail folders. Read Only, Since 7.4.0.<br />
|-<br />
| 3010 || com.openexchange.publish.publicationFlag || Boolean || Indicates whether this folder is published. Read Only, provided by the com.openexchange.publish plugin, since 6.14.<br />
|-<br />
| 3020 || com.openexchange.subscribe.subscriptionFlag || Boolean || Indicates whether this folder has subscriptions storing their content in this folder. Read Only, provided by the com.openexchange.subscribe plugin, since 6.14.<br />
|-<br />
| 3030 || com.openexchange.folderstorage.displayName || String || Provides the display of the folder's owner. Read Only, Since 6.20.<br />
|}<br />
<br />
<br />
<br />
<br />
{| id="PermissionFlags" cellspacing="0" border="1"<br />
|+ align="bottom" | Permission flags<br />
! Bits !! Value<br />
|-<br />
| 0-6 || Folder permissions:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || See the folder.<br />
|-<br />
| 2 || Create objects in the folder. '''Note''': '''Does not apply to folders of module ''system'''''.<br />
|-<br />
| 4 || Create subfolders.<br />
|-<br />
| 64 || All permissions. This is currently the same as "Create subfolders" but in the future additional permissions may be added that will be given to the user when using this value.<br />
|}<br />
The values are scalars and not bit sets. Any other than the described values should not be used. If they are used expect an exception from the backend. Every value automatically contains the access rights covered by lower values.<br>'''NOTE''': ''Create objects in the folder'' is not covered by ''Create subfolders'' if folder's module is ''system''.<br />
|-<br />
| 7-13 || Read permissions for objects in the folder:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || Read only own objects.<br />
|-<br />
| 2 || Read all objects.<br />
|-<br />
| 64 || All permissions. This is currently the same as "Read all objects" but in the future additional permissions may be added that will be given to the user when using this value.<br />
|}<br />
The values are scalars and not bit sets. Any other than the described values should not be used. If they are used expect an exception from the backend. Every value automatically contains the access rights covered by lower values.<br />
|-<br />
| 14-20 || Write permissions for objects in the folder:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || Modify only own objects.<br />
|-<br />
| 2 || Modify all objects.<br />
|-<br />
| 64 || All permissions. This is currently the same as "Modify all objects" but in the future additional permissions may be added that will be given to the user when using this value.<br />
|}<br />
The values are scalars and not bit sets. Any other than the described values should not be used. If they are used expect an exception from the backend. Every value automatically contains the access rights covered by lower values.<br />
|-<br />
| 21-27 || Delete permissions for objects in the folder:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || Delete only own objects.<br />
|-<br />
| 2 || Delete all objects.<br />
|-<br />
| 64 || All permissions. This is currently the same as "Delete all objects" but in the future additional permissions may be added that will be given to the user when using this value.<br />
|}<br />
The values are scalars and not bit sets. Any other than the described values should not be used. If they are used expect an exception from the backend. Every value automatically contains the access rights covered by lower values.<br />
|-<br />
| 28 || Admin flag:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || Every operation modifying the folder in some way requires this permission. This are e.g. changing the folder name, modifying the permissions, deleting or moving the folder.<br />
|}<br />
|}<br />
<br />
{| id="PermissionObject" cellspacing="0" border="1"<br />
|+ align="bottom" | Permission object<br />
! Name !! Type !! Value<br />
|-<br />
| bits || Number || For non-mail folders, a number as described in [[#PermissionFlags | Permission flags]].<br />
|-<br />
| rights || String || For mail folders, the rights string as defined in RFC 2086.<br />
|-<br />
| entity || Number || User ID of the user or group to which this permission applies (ignored for type "anonymous" or "guest").<br />
|-<br />
| group || Boolean || true if entity refers to a group, false if it refers to a user (ignored for type "anonymous" or "guest").<br />
|-<br />
| type || String || The recipient type, i.e. one of "guest", "anonymous" (required if no internal "entity" defined).<br />
|-<br />
| password || String || An additional secret / pin number an anonymous user needs to enter when accessing the share (for type "anonymous", optional) .<br />
|-<br />
| email_address || String || The e-mail address of the recipient (for type "guest").<br />
|-<br />
| display_name || String || The display name of the recipient (for type "guest", optional).<br />
|-<br />
| contact_id || String || The object identifier of the corresponding contact entry if the recipient was chosen from the address book (for type "guest", optional).<br />
|-<br />
| contact_folder || String || The folder identifier of the corresponding contact entry if the recipient was chosen from the address book (for type "guest", required if "contact_id" is set).<br />
|-<br />
| expiry_date || Time || The end date / expiration time after which the share link is no longer accessible (for type "guest" or "anonymous", optional).<br />
|}<br />
<br />
{| id="Capabilities" cellspacing="0" border="1"<br />
|+ align="bottom" | Capabilities<br />
! Bit !! Description<br />
|-<br />
| 0 || Mailing system supports permissions.<br />
|-<br />
| 1 || Mailing system supports ordering mails by their thread reference.<br />
|-<br />
| 2 || Mailing system supports quota restrictions.<br />
|-<br />
| 3 || Mailing system supports sorting.<br />
|-<br />
| 4 || Mailing system supports folder subscription.<br />
|}<br />
<br />
'''Note''': Capabilities describe the entire mailing system (mail account), not the specific folder in which they are transmitted. E.g. bit 4 of the capabilities on the user's inbox describes whether subscriptions are supported by the default account, even though the inbox itself cannot be unsubscribed because it's a standard folder.<br />
<br />
{| id="DefaultTypes" cellspacing="0" border="1"<br />
|+ align="bottom" | Standard Folder Types<br />
! Bit !! Description<br />
|-<br />
| 0 || No default folder.<br />
|-<br />
| 1 || Task.<br />
|-<br />
| 2 || Calendar.<br />
|-<br />
| 3 || Contact.<br />
|-<br />
| 7 || Inbox.<br />
|-<br />
| 8 || Infostore.<br />
|-<br />
| 9 || Drafts.<br />
|-<br />
| 10 || Sent.<br />
|-<br />
| 11 || Spam.<br />
|-<br />
| 12 || Trash.<br />
|}<br />
<br />
{| id="SupportedCapabilities" cellspacing="0" border="1"<br />
|+ align="bottom" | Supported Capabilities<br />
! Name !! Description<br />
|-<br />
| permissions || Folder storage supports permissions.<br />
|-<br />
| publication || Folder storage supports folder publication.<br />
|-<br />
| quota || Folder storage supports quota restrictions.<br />
|-<br />
| sort || Folder storage supports sorting.<br />
|-<br />
| subscription || Folder storage supports folder subscription.<br />
|}<br />
<br />
=== Get subfolders ===<br />
<br />
GET <code>/ajax/folders?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>parent</code> – Object ID of a folder, which is the parent folder of the requested folders.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
* <code>all</code> – Set to <code>1</code> to list even not subscribed folders.<br />
* <code>tree</code> – The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
* <code>errorOnDuplicateName</code> – An optional flag to enable or disable (default) check for duplicate folder names within returned folder response (since v6.20.1). If a duplicate folder name is detected, an appropriate error is returned as [[#ResponseBody | response]].<br />
<br />
Response with timestamp: An array with data for all folders, which have the folder with the requested object ID as parent. Each array element describes one folder and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get path ===<br />
<br />
GET <code>/ajax/folders?action=path</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of a folder.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Response with timestamp: An array with data for all parent nodes until root folder. Each array element describes one folder and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get updated folders ===<br />
<br />
GET <code>/ajax/folders?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>parent</code> – Object ID of a folder, which is the parent folder of the requested folders.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested folders.<br />
* <code>ignore</code> (optional) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Response with timestamp: An array with data for new, modified and deleted folders. New and modified folders are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted folders (should the <code>ignore</code> parameter be ever implemented) would be identified by their object IDs as plain strings, without being part of a nested array.<br />
<br />
=== Get a folder ===<br />
<br />
GET <code>/ajax/folders?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested folder.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Response with timestamp: An object containing all data of the requested folder. The fields of the object are listed in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]]. The field id is not present. Since OX access controls are folder-based, the folder object also defines the permissions for the objects it contains. The permissions for a given user or group are defined by the object described in [[#PermissionObject | Permission object]]. The format of the actual permissions depends on the type of the folder. The permissions of mail folders are transmitted as a rights string as defined in section 3 of RFC 2086. Permissions of all other folders are transmitted as a single nonnegative integer number. The permissions for any given action on the folder or on contained objects is defined by a group of bits in the binary representation of this number. Each group of bits is interpreted as a separate number. Zero always means "no permissions". Any other values add new permissions and always include the permissions of all lower values. The individual values are described in [[#PermissionFlags | Permission flags]].<br />
<br />
=== Update a folder ===<br />
<br />
PUT <code>/ajax/folders?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated folder.<br />
* <code>timestamp</code> – Timestamp of the updated folder. If the folder was modified after the specified timestamp, then the update must fail.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
* <code>cascadePermissions</code> – (Optional. Defaults to false) Flag to cascade permissions to all sub-folders. The user must have administrative permissions to all sub-folders subject to change. If one permission change fails, the entire operation fails. (Since 7.8.0)<br />
<br />
Request body: Folder object as described in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]]. Only modified fields are present.<br />
<br />
=== Create a folder ===<br />
<br />
PUT <code>/ajax/folders?action=new</code><br />
<br />
Parameters:<br />
* <code>folder_id</code> – The parent folder of the newly created folder<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Request body: Folder object as described in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]]. The field id should not be present.<br />
<br />
Provided that permission is granted to create a folder, its module is bound to the limitation, that the new folder's module must be equal to parent folder's module except that:<br />
* Parent folder is one of the system folders <code>private</code>, <code>public</code>, or <code>shared</code>. Below these folders task, calendar, and contact modules are permitted.<br />
* Parent folder's module is one of task, calendar, or contact. Below this kind of folders task, calendar, and contact modules are permitted.<br />
<br />
Response: Object ID of the newly created folder.<br />
<br />
=== Delete folders ===<br />
<br />
PUT <code>/ajax/folders?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted folders.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered. <br />
* <code>hardDelete</code> - Optional, defaults to \"false\". If set to \"true\", the folders are deleted permanently. Otherwise, and if the underlying storage supports a trash folder and the folders are not yet located below the trash folder, they are moved to the trash folder.<br />
<br />
Request body: An array with object IDs of the folders that shall be deleted.<br />
<br />
Response: An array with object IDs of folders that were '''NOT''' deleted. There may be a lot of different causes for a not deleted folder: A folder has been modified in the mean time, the user does not have the permission to delete it or those permissions have just been removed, the folder does not exist, etc.<br />
<br />
=== Clearing a folder's content ===<br />
PUT <code>/ajax/folders?action=clear</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Request body: A JSON array containing the folder ID(s) whose content should be cleared. '''NOTE:''' Although the requests offers to clear multiple folders at once it is recommended to clear only one folder per request since if any exception occurs<br />
(e.g. missing permissions) the complete request is going to be aborted.<br />
<br />
Response: A JSON array containing the IDs of folders that could not be cleared due to a concurrent modification. Meaning you receive an empty JSON array if everything worked well.<br />
<br />
=== Get all visible folder of a certain module (since v6.18.2) ===<br />
PUT <code>/ajax/folders?action=allVisible</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>tree</code> – The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>content_type</code> – The desired content type (either numbers or strings; e.g. "tasks", "calendar", "contacts", "mail")<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
<br />
Request body: None<br />
<br />
Response with timestamp: A JSON object containing three fields: "private", "public, and "shared". Each field is a JSON array with data for all folders. Each folder is itself described by an array.<br />
<br />
== Module "tasks" ==<br />
<br />
The tasks module is used to access task information.<br />
<br />
=== Get all tasks ===<br />
<br />
GET <code>/ajax/tasks?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for tasks are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response with timestamp: An array with task data. Each array element describes one task and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedTaskAndAppointmentData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed task and appointment data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 200 || title || String || Short description.<br />
|-<br />
| 201 || start_date || Date or Time || Inclusive start of the event as Date for tasks and whole day appointments and Time for normal appointments. For sequencies, this date must be part of the sequence, i. e. sequencies always start at this date. (deprecated for tasks since v7.6.1, replaced by start_time and full_time)<br />
|-<br />
| 202 || end_date || Date or Time || Exclusive end of the event as Date for tasks and whole day appointments and as Time for normal appointments. (deprecated for tasks since v7.6.1, replaced by end_time and full_time)<br />
|-<br />
| 203 || note || String || Long description.<br />
|-<br />
| 204 || alarm || Number or Time || Specifies when to notify the participants as the number of minutes before the start of the appointment (-1 for "no alarm"). For tasks, the Time value specifies the absolute time when the user should be notified.<br />
|-<br />
| 209 || recurrence_type || Number || Specifies the type of the recurrence for a task sequence:<br />
{| cellspacing="0" border="1"<br />
| 0 || none (single event)<br />
|-<br />
| 1 || daily<br />
|-<br />
| 2 || weekly<br />
|-<br />
| 3 || monthly<br />
|-<br />
| 4 || yearly<br />
|}<br />
|-<br />
| 212 || days || Number || Specifies which days of the week are part of a sequence. The value is a bitfield with bit 0 indicating sunday, bit 1 indicating monday and so on. May be present if recurrence_type > 1. If allowed but not present, the value defaults to 127 (all 7 days).<br />
|-<br />
| 213 || day_in_month || Number || Specifies which day of a month is part of the sequence. Counting starts with 1. If the field "days" is also present, only days selected by that field are counted. If the number is bigger than the number of available days, the last available day is selected. Present if and only if recurrence_type > 2.<br />
|-<br />
| 214 || month || Number || Month of the year in yearly sequencies. 0 represents January, 1 represents February and so on. Present if and only if recurrence_type = 4.<br />
|-<br />
| 215 || interval || Number || Specifies an integer multiplier to the interval specified by recurrence_type. Present if and only if recurrence_type > 0. Must be 1 if recurrence_type = 4.<br />
|-<br />
| 216 || until || Date || Inclusive end date of a sequence. May be present only if recurrence_type > 0. The sequence has no end date if recurrence_type > 0 and this field is not present. Note: since this is a Date, the entire day after the midnight specified by the value is included.<br />
|-<br />
| 217 || notification || Boolean || If true, all participants are notified of any changes to this object. This flag is valid for the current change only, i. e. it is not stored in the database and is never sent by the server to the client.<br />
|-<br />
| 220 || participants || Array || Each element identifies a participant, user, group or booked resource as described in [[#Participant | participant table]].<br />
|-<br />
| 221 || users || Array || Each element represents a participant as described in [[#UserParticipantObject | User participant object]]. User groups are resolved and are represented by their members. Any user can occur only once.<br />
|-<br />
| 222 || occurrences || Number || Specifies how often a recurrence should appear. May be present only if recurrence_type > 0.<br />
|-<br />
| 223 || uid || String || Can only be written when the object is created. Internal and external globally unique identifier of the appointment or task. Is used to recognize appointments within iCal files. If this attribute is not written it contains an automatic generated UUID.<br />
|-<br />
| 224 || organizer || String || Contains the email address of the appointment organizer which is not necessarily an internal user. Not implemented for tasks.<br />
|-<br />
| 225 || sequence || Number || iCal sequence number. Not implemented for tasks. Must be incremented on update. Will be incremented by the server, if not set.<br />
|-<br />
| 226 || confirmations || Array || Each element represents a confirming participant as described in [[#ConfirmingParticipant | confirming participant]]. This can be internal and external user. Not implemented for tasks.<br />
|-<br />
| 227 || organizerId || Number || Contains the userIId of the appointment organizer if it is an internal user. Not implemented for tasks. (Introduced with 6.20.1)<br />
|-<br />
| 228 || principal || String || Contains the email address of the appointment principal which is not necessarily an internal user. Not implemented for tasks. (Introduced with 6.20.1)<br />
|-<br />
| 229 || principalId || Number || Contains the userIId of the appointment principal if it is an internal user. Not implemented for tasks. (Introduced with 6.20.1)<br />
|-<br />
| 401 || full_time || Boolean || True if the event is a whole day appointment or task, false otherwise.<br />
|}<br />
<br />
{| id="Participant" cellspacing="0" border="1"<br />
|+ align="bottom" | Participant identifier<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || User ID<br />
|-<br />
| type || Number || Type of participant:<br />
{|<br />
| 1 || user<br />
|-<br />
| 2 || user group<br />
|-<br />
| 3 || resource<br />
|-<br />
| 4 || resource group<br />
|-<br />
| 5 || external user<br />
|}<br />
|-<br />
| mail || String || mail address of an external participant<br />
|}<br />
<br />
{| id="UserParticipantObject" cellspacing="0" border="1"<br />
|+ align="bottom" | User participant object<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || User ID. Confirming for other users only works for appointments and not for tasks.<br />
|-<br />
| display_name || String || Displayable name of the participant.<br />
|-<br />
| confirmation || Number ||<br />
{| cellspacing="0" border="1"<br />
| 0 || none<br />
|-<br />
| 1 || accepted<br />
|-<br />
| 2 || declined<br />
|-<br />
| 3 || tentative<br />
|}<br />
|-<br />
| confirmmessage || String || Confirm Message of the participant<br />
|}<br />
<br />
{| id="ConfirmingParticipant" cellspacing="0" border="1"<br />
|+ align="bottom" | Confirming participant<br />
! Name !! Type !! Value<br />
|-<br />
| type || Number || Type of participant:<br />
{|<br />
| 1 || user<br />
|-<br />
| 5 || external user<br />
|}<br />
|-<br />
| mail || String || email address of external participant<br />
|-<br />
| display_name || String || display name of external participant<br />
|-<br />
| status || Number ||<br />
{|<br />
| 0 || none<br />
|-<br />
| 1 || accepted<br />
|-<br />
| 2 || declined<br />
|-<br />
| 3 || tentative<br />
|}<br />
|-<br />
| message || String || Confirm Message of the participant<br />
|}<br />
<br />
{| id="DetailedTaskData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed task data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 300 || status || Number || Status of the task:<br />
{| cellspacing="0" border="1"<br />
| 1 || not started<br />
|-<br />
| 2 || in progress<br />
|-<br />
| 3 || done<br />
|-<br />
| 4 || waiting<br />
|-<br />
| 5 || deferred<br />
|}<br />
|-<br />
| 301 || percent_completed || Number || How much of the task is completed. An integer number between 0 and 100.<br />
|-<br />
| 302 || actual_costs|| Number || A monetary attribute to store actual costs of a task. Allowed values must be in the range -9999999999.99 and 9999999999.99.<br />
|-<br />
| 303 || actual_duration<br />
|-<br />
| 304 || after_complete || Date || Deprecated. Only present in AJAX interface. Value will not be stored on OX server.<br />
|-<br />
| 305 || billing_information<br />
|-<br />
| 307 || target_costs|| Number || A monetary attribute to store target costs of a task. Allowed values must be in the range -9999999999.99 and 9999999999.99.<br />
|-<br />
| 308 || target_duration<br />
|-<br />
| 309 || priority || Number || 1 = LOW, 2 = MEDIUM, 3 = HIGH<br />
|-<br />
| 312 || currency<br />
|-<br />
| 313 || trip_meter<br />
|-<br />
| 314 || companies<br />
|-<br />
| 315 || date_completed<br />
|-<br />
| 201 || start_time || Date or Time || Inclusive start as Date for whole day tasks and Time for normal tasks. <br />
|-<br />
| 202 || end_time || Date or Time || Exclusive end as Date for whole day tasks and as Time for normal tasks.<br />
|}<br />
<br />
=== Get a list of tasks ===<br />
<br />
PUT <code>/ajax/tasks?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for tasks are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]].<br />
<br />
Request body: An array of with object IDs of requested tasks.<br />
<br />
Response with timestamp: An array with task data. Each array element describes one task and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get updated tasks ===<br />
<br />
GET <code>/ajax/tasks?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for tasks are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested tasks.<br />
* <code>ignore</code> – Which kinds of updates should be ignored. Omit this parameter or set it to "deleted" to not have deleted tasks identifier in the response. Set this parameter to "false" and the response contains deleted tasks identifier.<br />
<br />
Response with timestamp: An array with new, modified and deleted tasks. New and modified tasks are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted tasks would be identified by their object IDs as plain strings, without being part of a nested array.<br />
<br />
=== Get a task ===<br />
<br />
GET <code>/ajax/tasks?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested task.<br />
* <code>folder</code> – Object ID of the task's folder.<br />
<br />
Response with timestamp: An object containing all data of the requested task. The fields of the object are listed in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]]. The field id is not included.<br />
<br />
=== Update a task ===<br />
<br />
PUT <code>/ajax/tasks?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Folder Identifier through that the task is accessed. This is necessary for checking the permissions.<br />
* <code>id</code> – Object ID of the updated task.<br />
* <code>timestamp</code> – Timestamp of the updated task. If the task was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: Task object as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]]. Only modified fields are present.<br />
<br />
=== Create a task ===<br />
<br />
PUT <code>/ajax/tasks?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Task object as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]]. The field id is not present.<br />
<br />
Response: A json objekt with attribute <code>id</code> of the newly created task.<br />
<br />
=== Delete task ===<br />
<br />
PUT <code>/ajax/tasks?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted tasks.<br />
<br />
Request body: An object in the field “id” and “folder”.<br />
<br />
Response: An array with object IDs of tasks which were modified after the specified timestamp and were therefore not deleted.<br />
<br />
=== Delete tasks (since v6.22) ===<br />
<br />
PUT <code>/ajax/tasks?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted tasks.<br />
<br />
Request body: An array of objects with the fields “id” and “folder”.<br />
<br />
Response: An array with object IDs of tasks which were modified after the specified timestamp and were therefore not deleted.<br />
<br />
=== Confirm task ===<br />
<br />
PUT <code>/ajax/tasks?action=confirm</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the to confirm task.<br />
* <code>folder</code> – ID of the folder through that the task is accessed.<br />
* <code>timestamp</code> – Timestamp of the last update of the to confirm task.<br />
<br />
Request body: An object with the fields "confirmation" and "confirmmessage" as described in [[#UserParticipantObject | User participant object]].<br />
<br />
Response: Nothing, except the standard response object with empty data, the timestamp of the confirmed and thereby updated task, and maybe errors.<br />
<br />
=== Search for tasks ===<br />
<br />
PUT <code>/ajax/tasks?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified , then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Request Body: A JSON object with attributes described in [[#SearchTasks | Search tasks]]<br />
<br />
{| id="SearchTasks" cellspacing="0" border="1"<br />
|+ align="bottom" | Search tasks<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find tasks. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|-<br />
| folder || Number || (optional) Defines the folder to search for tasks in. If this is omitted in all task folders will be searched.<br />
|-<br />
| start || Date or Time || (optional) Inclusive start date for a time range the tasks should end in. If start is omitted end is ignored.<br />
|-<br />
| end || Date or Time || (optional) Exclusive end date for a time range the tasks should end in. If this parameter is omitted the time range has an open end.<br />
|}<br />
<br />
Response with timestamp: An array with matching tasks. Tasks are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
== Module "contacts" ==<br />
<br />
The contacts module is used to access contact information.<br />
<br />
=== Get all contacts ===<br />
<br />
GET <code>/ajax/contacts?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried (optional from 6.22.2 on: If not set, the contents of all visible folders are used instead).<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for contacts are defined in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (preliminary, since 6.20) – allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedContactData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed contact data<br />
! ID !! Displayed name !! Name !! Type !! Value<br />
|-<br />
| 223 || || uid || String || Can only be written when the object is created. Internal and external globally unique identifier of the contact. Is used to recognize contacts within vCard files. If this attribute is not written it contains an automatic generated UUID.<br />
|-<br />
| 500 || Display name || display_name || String<br />
|-<br />
| 501 || Given name || first_name || String || First name.<br />
|-<br />
| 502 || Sur name || last_name || String || Last name.<br />
|-<br />
| 503 || Middle name || second_name || String<br />
|-<br />
| 504 || Suffix || suffix || String<br />
|-<br />
| 505 || Title || title || String<br />
|-<br />
| 506 || Street home || street_home || String<br />
|-<br />
| 507 || Postal code home || postal_code_home || String<br />
|-<br />
| 508 || City home || city_home || String<br />
|-<br />
| 509 || State home || state_home || String<br />
|-<br />
| 510 || Country home || country_home || String<br />
|-<br />
| 511 || Birthday || birthday || Date<br />
|-<br />
| 512 || Martial status || marital_status || String<br />
|-<br />
| 513 || Number of children || number_of_children || String<br />
|-<br />
| 514 || Profession || profession || String<br />
|-<br />
| 515 || Nickname || nickname || String<br />
|-<br />
| 516 || Spouse name || spouse_name || String<br />
|-<br />
| 517 || Anniversay || anniversary || Date<br />
|-<br />
| 518 || Note || note || String<br />
|-<br />
| 519 || Department || department || String<br />
|-<br />
| 520 || Position || position || String<br />
|-<br />
| 521 || Employee type || employee_type || String<br />
|-<br />
| 522 || Room number || room_number || String<br />
|-<br />
| 523 || Street business || street_business || String<br />
|-<br />
| 524 || || internal_userid || Number<br />
|-<br />
| 525 || Postal code business || postal_code_business || String<br />
|-<br />
| 526 || City business || city_business || String<br />
|-<br />
| 527 || State business || state_business || String<br />
|-<br />
| 528 || Country business || country_business || String<br />
|-<br />
| 529 || Number of employee || number_of_employees || String<br />
|-<br />
| 530 || Sales volume || sales_volume || String<br />
|-<br />
| 531 || Tax id || tax_id || String<br />
|-<br />
| 532 || Commercial register || commercial_register || String<br />
|-<br />
| 533 || Branches || branches || String<br />
|-<br />
| 534 || Business category || business_category || String<br />
|-<br />
| 535 || Info || info || String<br />
|-<br />
| 536 || Manager's name || manager_name || String<br />
|-<br />
| 537 || Assistant's name || assistant_name || String<br />
|-<br />
| 538 || Street other || street_other || String<br />
|-<br />
| 539 || City other || city_other || String<br />
|-<br />
| 540 || Postal code other || postal_code_other || String<br />
|-<br />
| 541 || Country other || country_other || String<br />
|-<br />
| 542 || Telephone business 1 || telephone_business1 || String<br />
|-<br />
| 543 || Telephone business 2 || telephone_business2 || String<br />
|-<br />
| 544 || FAX business || fax_business || String<br />
|-<br />
| 545 || Telephone callback || telephone_callback || String<br />
|-<br />
| 546 || Telephone car || telephone_car || String<br />
|-<br />
| 547 || Telephone company || telephone_company || String<br />
|-<br />
| 548 || Telephone home 1 || telephone_home1 || String<br />
|-<br />
| 549 || Telephone home 2 || telephone_home2 || String<br />
|-<br />
| 550 || FAX home || fax_home || String<br />
|-<br />
| 551 || Cellular telephone 1 || cellular_telephone1 || String<br />
|-<br />
| 552 || Cellular telephone 2 || cellular_telephone2 || String<br />
|-<br />
| 553 || Telephone other || telephone_other || String<br />
|-<br />
| 554 || FAX other || fax_other || String<br />
|-<br />
| 555 || Email 1 || email1 || String<br />
|-<br />
| 556 || Email 2 || email2 || String<br />
|-<br />
| 557 || Email 3 || email3 || String<br />
|-<br />
| 558 || URL || url || String<br />
|-<br />
| 559 || Telephone ISDN || telephone_isdn || String<br />
|-<br />
| 560 || Telephone pager || telephone_pager || String<br />
|-<br />
| 561 || Telephone primary || telephone_primary || String<br />
|-<br />
| 562 || Telephone radio || telephone_radio || String<br />
|-<br />
| 563 || Telephone telex || telephone_telex || String<br />
|-<br />
| 564 || Telephone TTY/TDD || telephone_ttytdd || String<br />
|-<br />
| 565 || Instantmessenger 1 || instant_messenger1 || String<br />
|-<br />
| 566 || Instantmessenger 2 || instant_messenger2 || String<br />
|-<br />
| 567 || Telephone IP || telephone_ip || String<br />
|-<br />
| 568 || Telephone assostant || telephone_assistant || String<br />
|-<br />
| 569 || Company || company || String<br />
|-<br />
| 570 || || image1 || String<br />
|-<br />
| 571 || Dynamic Field 1 || userfield01 || String<br />
|-<br />
| 572 || Dynamic Field 2 || userfield02 || String<br />
|-<br />
| 573 || Dynamic Field 3 || userfield03 || String<br />
|-<br />
| 574 || Dynamic Field 4 || userfield04 || String<br />
|-<br />
| 575 || Dynamic Field 5 || userfield05 || String<br />
|-<br />
| 576 || Dynamic Field 6 || userfield06 || String<br />
|-<br />
| 577 || Dynamic Field 7 || userfield07 || String<br />
|-<br />
| 578 || Dynamic Field 8 || userfield08 || String<br />
|-<br />
| 579 || Dynamic Field 9 || userfield09 || String<br />
|-<br />
| 580 || Dynamic Field 10 || userfield10 || String<br />
|-<br />
| 581 || Dynamic Field 11 || userfield11 || String<br />
|-<br />
| 582 || Dynamic Field 12 || userfield12 || String<br />
|-<br />
| 583 || Dynamic Field 13 || userfield13 || String<br />
|-<br />
| 584 || Dynamic Field 14 || userfield14 || String<br />
|-<br />
| 585 || Dynamic Field 15 || userfield15 || String<br />
|-<br />
| 586 || Dynamic Field 16 || userfield16 || String<br />
|-<br />
| 587 || Dynamic Field 17 || userfield17 || String<br />
|-<br />
| 588 || Dynamic Field 18 || userfield18 || String<br />
|-<br />
| 589 || Dynamic Field 19 || userfield19 || String<br />
|-<br />
| 590 || Dynamic Field 20 || userfield20 || String || Contains a UUID if one was assigned (after 6.18.2)<br />
|-<br />
| 592 || || distribution_list || Array || If this contact is a distribution list, then this field is an array of objects. Each object describes a member of the list as defined in [[#DistributionListMember | Distribution list member]].<br />
|-<br />
| 594 || Number of distributionlists || number_of_distribution_list || Number<br />
|-<br />
| 596 || || number_of_images || Number<br />
|-<br />
| 597 || || image_last_modified || Timestamp<br />
|-<br />
| 598 || State other || state_other || String<br />
|-<br />
| 599 || || file_as || String<br />
|-<br />
| 601 || || image1_content_type || String<br />
|-<br />
| 602 || || mark_as_distributionlist || Boolean<br />
|-<br />
| 605 || Default address || default_address || Number<br />
|-<br />
| 606 || || image1_url || String<br />
|-<br />
| 608 || || useCount || Number || In case of sorting purposes the column 609 is also available, which places global address book contacts at the beginning of the result. If 609 is used, the order direction (ASC, DESC) is ignored.<br />
|-<br />
| 610 || || yomiFirstName || String || Kana based representation for the First Name. Commonly used in japanese environments for searchin/sorting issues. (since 6.20)<br />
|-<br />
| 611 || || yomiLastName || String || Kana based representation for the Last Name. Commonly used in japanese environments for searchin/sorting issues. (since 6.20)<br />
|-<br />
| 612 || || yomiCompany || String || Kana based representation for the Company. Commonly used in japanese environments for searchin/sorting issues. (since 6.20)<br />
|-<br />
| 613 || || addressHome || String || Support for Outlook 'home' address field. (since 6.20.1)<br />
|-<br />
| 614 || || addressBusiness || String || Support for Outlook 'business' address field. (since 6.20.1)<br />
|-<br />
| 615 || || addressOther || String || Support for Outlook 'other' address field. (since 6.20.1)<br />
|}<br />
<br />
<br />
{| id="DistributionListMember" cellspacing="0" border="1"<br />
|+ align="bottom" | Distribution list member<br />
! Name !! Type !! Value<br />
|-<br />
| id || String || Object ID of the member's contact if the member is an existing contact.<br />
|-<br />
| folder_id || String || Parent folder ID of the member's contact if the member is an existing contact (preliminary, from 6.22 on).<br />
|-<br />
| display_name || String || Display name<br />
|-<br />
| mail || String || Email address (mandatory before 6.22, afterwards optional if you are referring to an internal contact)<br />
|-<br />
| mail_field || Number || Which email field of an existing contact (if any) is used for the mail field.<br />
{| cellspacing="0" border="1"<br />
| 0 || independent contact<br />
|-<br />
| 1 || default email field (email1)<br />
|-<br />
| 2 || second email field (email2)<br />
|-<br />
| 3 || third email field (email3)<br />
|}<br />
|}<br />
<br />
=== Get a list of contacts ===<br />
<br />
PUT <code>/ajax/contacts?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for contacts are defined in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]].<br />
<br />
Request body: An array with objects. Each object contains fields “id” and “folder” of requested contacts.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a list of users ===<br />
<br />
PUT <code>/ajax/contacts?action=listuser</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for contacts are defined in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]].<br />
<br />
Request body: An array with id<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
Available with SP4<br />
<br />
=== Get updated contacts ===<br />
<br />
GET <code>/ajax/contacts?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for contacts are defined in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested contacts.<br />
* <code>ignore</code> (mandatory - should be set to "deleted") (deprecated) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
<br />
Response with timestamp: An array with new, modified and deleted contacts. New and modified contacts are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted contacts (should the <code>ignore</code> parameter be ever implemented) would be identified by their object IDs as plain strings, without being part of a nested array.<br />
<br />
=== Get a contact ===<br />
<br />
GET <code>/ajax/contacts?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested contact.<br />
* <code>folder</code> – Object ID of the contact's folder.<br />
<br />
Response with timestamp: An object containing all data of the requested contact. The fields of the object are listed in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]]. The field id is not included.<br />
<br />
=== Get contact by user ID ===<br />
<br />
GET <code>/ajax/contacts?action=getuser</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – User ID (not Object ID) of the requested user.<br />
<br />
Response with timestamp: An object containing all data of the requested contact. The fields of the object are listed in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]]. <br />
<br />
Available with SP4 package.<br />
<br />
=== Update a contact ===<br />
<br />
PUT <code>/ajax/contacts?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Folder identifier through that the contact is accessed. This is necessary for checking the permissions.<br />
* <code>id</code> – Object ID of the updated contact.<br />
* <code>timestamp</code> – Timestamp of the updated contact. If the contact was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: Contact object as described in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]]. Only modified fields are present.<br />
<br />
To remove some contact image send the image attribute set to <code>null</code>.<br />
<br />
To change or add some contact image the PUT command must be replaced with a POST command and all data must be provided within a <code>multipart/form-data</code> body. The normal request body must be placed into a form field named <code>json</code> while the image file must be placed in a file field named <code>file</code>. The response is then an HTML page as described in section [[#File_uploads | File uploads]].<br />
<br />
=== Create a contact ===<br />
<br />
PUT <code>/ajax/contacts?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Contact object as described in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]]. The field id is not included.<br />
<br />
Response: A json objekt with attribute <code>id</code> of the newly created contact.<br />
<br />
To add some contact image the PUT command must be replaced with a POST command and all data must be provided within a <code>multipart/form-data</code> body. The normal request body must be placed into a form field named <code>json</code> while the image file must be placed in a file field named <code>file</code>. The response is then an HTML page as described in section [[#File uploads | File uploads]].<br />
<br />
=== Delete a contact ===<br />
<br />
PUT <code>/ajax/contacts?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted contacts.<br />
<br />
Request body: An object with the fields “id” and “folder”.<br />
<br />
=== Delete contacts (since v6.22)===<br />
<br />
PUT <code>/ajax/contacts?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted contacts.<br />
<br />
Request body: An array of objects with the fields “id” and “folder”.<br />
<br />
=== Search contacts ===<br />
<br />
PUT <code>/ajax/contacts?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified. In case of use of column 609 (use count depending order for collected contacts with global address book) the parameter "order" ist NOT necessary and will be ignored.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (preliminary, since 6.20) – allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Request body: An Object as described in [[#SearchContacts | Search contacts]].<br />
<br />
{| id="SearchContacts" cellspacing="0" border="1"<br />
|+ align="bottom" | Search contacts<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find contacts. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves. Matching is performed against any substring of the field <code>display_name</code>.<br />
|-<br />
| startletter || String || Search contacts with the given startletter. If this field is present, the pattern is matched against the contact field which is specified by the property contact_first_letter_field on the server (default: last name). Otherwise, the pattern is matched against the display name.<br />
|-<br />
| folder || Array of Number || If a list of folder identifiers or at least a single folder identifier is given, only in that folders will be searched for contacts. This paramenter is optional but searching in all contact folders that are viewable and where objects can be read in is more expensive on that database than searching in a dedicated number of them. The possibility to provide here an array of folder identifier has been added with 6.10.<br />
|}<br />
<br />
Alternative request body: An Object as described in [[#SearchContactsAlternative | Search contacts alternative]].<br />
<br />
{| id="SearchContactsAlternative" cellspacing="0" border="1"<br />
|+ align="bottom" | Search contacts alternative<br />
! Name !! Type !! Value<br />
|-<br />
| last_name || String || Searches contacts where the last name match with the given last name.<br />
|-<br />
| first_name || String || Searches contacts where the first name match with the given first name.<br />
|-<br />
| display_name || String || Searches contacts where the display name match with the given display name.<br />
|-<br />
| email1 || String || Searches contacts where the email1 address match with the given search pattern. (requires version >= 6.12)<br />
|-<br />
| email2 || String || Searches contacts where the email2 address match with the given search pattern. (requires version >= 6.12)<br />
|-<br />
| email3 || String || Searches contacts where the email3 address match with the given search pattern. (requires version >= 6.12)<br />
|-<br />
| company || String || Searches contacts where the company match with the given search pattern. (requires version >= 6.12)<br />
|-<br />
| categories || String || Searches contacts where the categories match with the given search pattern. <br />
|-<br />
| orSearch || Boolean || If set to true, a contact is returned if any specified pattern matches at the start of the corresponding field. Otherwise, a contact is returned if all specified patterns match any substring of the corresponding field.<br />
|-<br />
| emailAutoComplete || Boolean || If set to true, results are guaranteed to contain at least one email adress and the search is performed as if orSearch were set to true. The actual value of orSearch is ignored.<br />
|-<br />
| exactMatch || Boolean || If set to true, contacts are returned where the specified patterns match the corresponding fields exactly. Otherwise, a 'startsWith' or 'substring' comparison is used based on the 'orSearch' parameter. (requires version > 6.22.1)<br />
|}<br />
<br />
Response: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Search contacts by filter (since 6.20) ===<br />
<br />
PUT <code>/ajax/contacts?action=advancedSearch</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified. <br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (preliminary, since 6.20) – allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Request body: An Object as described in [[#Module_.22search.22_.28alternative_suggestion.2C_still_preliminary.29 | Search Filter]]<br />
<br />
Response: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Search contacts by anniversary (Since 6.22.1, Preliminary) ===<br />
<br />
Find contacts whose anniversary falls into a timerange.<br />
<br />
GET <code>/ajax/contacts?action=anniversaries</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>start</code> – The lower (inclusive) limit of the requested time-range.<br />
* <code>end</code> – The upper (exclusive) limit of the requested time-range.<br />
* <code>columns</code> – The requested fields.<br />
* <code>folder</code> (optional) – Object ID of the parent folder that is searched. If not set, all visible folders are used.<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If not specified, the results are sorted ascending by their anniversary in the supplied timerange. If this parameter is specified, then the parameter order must be also specified. <br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (optional) – Allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Search contacts by birthday (Since 6.22.1, Preliminary) ===<br />
<br />
Find contacts whose birthday falls into a timerange.<br />
<br />
GET <code>/ajax/contacts?action=birthdays</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>start</code> – The lower (inclusive) limit of the requested time-range.<br />
* <code>end</code> – The upper (exclusive) limit of the requested time-range.<br />
* <code>columns</code> – The requested fields.<br />
* <code>folder</code> (optional) – Object ID of the parent folder that is searched. If not set, all visible folders are used.<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If not specified, the results are sorted ascending by their birthday in the supplied timerange. If this parameter is specified, then the parameter order must be also specified. <br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (optional) – Allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Auto-complete contacts (Since 7.6.1, Preliminary) ===<br />
<br />
Find contacts based on a prefix, usually used to auto-complete e-mail recipients while the user is typing.<br />
<br />
GET <code>/ajax/contacts?action=autocomplete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>query</code> – The query to search for.<br />
* <code>folder</code> (optional) – Object ID of the parent folder that is searched. If not set, all visible folders are used.<br />
* <code>email</code> (optional) – Whether to only include contacts with at least one e-mail address. Defaults to "true".<br />
* <code>columns</code> – The requested fields.<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is <br />
* <code>collation</code> (optional) – Allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
* <code>left_hand_limit</code> (optional) – A positive integer number to specify the "left-hand" limit of the range to return.<br />
* <code>right_hand_limit</code> (optional) – A positive integer number to specify the "right-hand" limit of the range to return.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
== Module "calendar" ==<br />
<br />
The calendar module is used to access calendar data.<br />
<br />
=== Get all appointments ===<br />
<br />
GET <code>/ajax/calendar?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> (optional) – Object ID of the folder, whose contents are queried. If not specified, defaults to all calendar folders.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]].<br />
* <code>start</code> – Lower inclusive limit of the queried range as a Date. Only appointments which start on or after this date are returned.<br />
* <code>end</code> – Upper exclusive limit of the queried range as a Date. Only appointments which end before this date are returned.<br />
* <code>recurrence_master</code> – Extract the recurrence to several appointments. The default value is false so every appointment of the recurrence will be calculated.<br />
* <code>showPrivate</code> (optional) – only works in shared folders: When enabled, shows private appointments of the folder owner. Such appointments are anonymized by stripping away all information except start date, end date and recurrence information (since 6.18)<br />
<br />
Response with timestamp: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Appointment sequencies are broken up into individual appointments and each occurrence of a sequence in the requested range is returned separately. The appointments are sorted in ascending order by the field start_date.<br />
<br />
{| id="DetailedAppointmentData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed appointment data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 206 || recurrence_id || Number || Object ID of the entire appointment sequence. Present on series and change exception appointments. Equals to object identifier on series appointment and is different to object identifier on change exceptions.<br />
|-<br />
| 207 || recurrence_position || Number || 1-based position of an individual appointment in a sequence. Present if and only if recurrence_type > 0.<br />
|-<br />
| 208 || recurrence_date_position || Date || Date of an individual appointment in a sequence. Present if and only if recurrence_type > 0.<br />
|-<br />
| 210 || change_exceptions || Array || An array of Dates, representing all change exceptions of a sequence.<br />
|-<br />
| 211 || delete_exceptions || Array || An array of Dates, representing all delete exceptions of a sequence.<br />
|-<br />
| 400 || location || String || Location<br />
|-<br />
| 402 || shown_as || Number || Describes, how this appointment appears in availability queries:<br />
{| cellspacing="0" border="1"<br />
| 1 || reserved<br />
|-<br />
| 2 || temporary<br />
|-<br />
| 3 || absent<br />
|-<br />
| 4 || free<br />
|}<br />
|-<br />
| 408 || timezone || String || Timezone<br />
|-<br />
| 410 || recurrence_start || Date || Start of a sequence without time<br />
|-<br />
| || ignore_conflicts || Boolean || Ignore soft conflicts for the new or modified appointment. This flag is valid for the current change only, i. e. it is not stored in the database and is never sent by the server to the client. <br />
|}<br />
<br />
=== Get appointment information ===<br />
<br />
GET <code>/ajax/calendar?action=has</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>start</code> – Lower inclusive limit of the queried range as a Date. Only appointments which end on or after this date are returned.<br />
* <code>end</code> – Upper exclusive limit of the queried range as a Date. Only appointments which start before this date are returned.<br />
<br />
Response is an array of booleans. Array length is the number of days. Each entry in the array corresponds with one day in the range that was queried, explaining whether there is an appointment on this day or not.<br />
<br />
=== Get a list of appointments ===<br />
<br />
PUT <code>/ajax/calendar?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]].<br />
* <code>recurrence_master</code> – Extract the recurrence to several appointments. The default value is false so every appointment of the recurrence will be calculated.<br />
<br />
Request body: An array with full object IDs (folder, id and optionally either recurrence_position or recurrence_date_position) of requested appointments.<br />
<br />
Response with timestamp: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="FullIdentifierForAnAppointment" cellspacing="0" border="1"<br />
|+ align="bottom" | Full identifier for an appointment<br />
! Name !! Type !! Value<br />
|-<br />
| id || String || Object ID<br />
|-<br />
| pos || Number || Value of the field recurrence_position, if present in the appointment.<br />
|}<br />
<br />
=== Get updated appointments ===<br />
<br />
GET <code>/ajax/calendar?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]].<br />
* <code>timestamp</code> – Timestamp of the last update of the requested appointments.<br />
* <code>start</code> (optional) – Lower inclusive limit of the queried range as a Date. Only appointments which end on or after this date are returned.<br />
* <code>end</code> (optional) – Upper exclusive limit of the queried range as a Date. Only appointments which start before this date are returned.<br />
* <code>ignore</code> (mandatory - should be set to "deleted") (deprecated) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
* <code>recurrence_master</code> – Extract the recurrence to several appointments. The default value is false so every appointment of the recurrence will be calculated.<br />
* <code>showPrivate</code> (optional) – only works in shared folders: When enabled, shows private appointments of the folder owner. Such appointments are anonymized by stripping away all information except start date, end date and recurrence information (since 6.18)<br />
<br />
Response with timestamp: An array with new, modified and deleted appointments. New and modified appointments are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted appointments (should the <code>ignore</code> parameter be ever implemented) would be identified by objects described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]] instead of arrays. Appointment sequencies are broken up into individual appointments and each modified occurrence of a sequence in the requested range is returned separately. The appointments are sorted in ascending order by the field start_date.<br />
<br />
=== Get an appointment ===<br />
<br />
GET <code>/ajax/calendar?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested appointment.<br />
* <code>folder</code> – Folder ID of the requested appointment.<br />
* <code>recurrence_position</code> (optional) – Recurrence Position requested appointment.<br />
<br />
Response with timestamp: An object containing all data of the requested appointment. The fields of the object are listed in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]]. The field id is not included.<br />
<br />
=== Update an appointment ===<br />
<br />
PUT <code>/ajax/calendar?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated appointment.<br />
* <code>folder</code> - Object ID of the appointment's folder.<br />
* <code>timestamp</code> – Timestamp of the updated appointment. If the appointment was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: Appointment object as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]]. The field recurrence_id is always present if it is present in the original appointment. The field recurrence_position is present if it is present in the original appointment and only this single appointment should be modified. The field id is not present because it is already included as a parameter. Other fields are present only if modified.<br />
<br />
=== Create an appointment ===<br />
PUT <code>/ajax/calendar?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Appointment object as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]]. The field id is not present.<br />
<br />
Response: If the appointment was created successfully, an object with the attribute <code>id</code> of the newly created appointment. If the appointment could not be created due to conflicts, the response body is an object with the field <code>conflicts</code>, which is an array of appointment objects which caused the conflict. Each appointment object which represents a resource conflict contains an additional field <code>hard_conflict</code> with the Boolean value true. If the user does not have read access to a conflicting appointment, only the fields <code>id</code>, <code>start_date</code>, <code>end_date</code>, <code>shown_as</code> and <code>participants</code> are present and the field <code>participants</code> contains only the participants which caused the conflict.<br />
<br />
=== Delete an appointment ===<br />
<br />
PUT <code>/ajax/calendar?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted appointments.<br />
<br />
Request body: The appointment object to delete. The fields for the object are described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]]. <br />
<br />
Response: An array of objects identifying the appointments which were modified after the specified timestamp and were therefore not deleted. The fields of each object are described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]].<br />
<br />
=== Delete appointments (since v6.22) ===<br />
<br />
PUT <code>/ajax/calendar?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted appointments.<br />
<br />
Request body: An array of appointment objects to delete. The fields for the object are described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]]. <br />
<br />
Response: An array of objects identifying the appointments which were modified after the specified timestamp and were therefore not deleted. The fields of each object are described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]].<br />
<br />
=== Confirm appointment ===<br />
<br />
PUT <code>/ajax/calendar?action=confirm</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the appointment to confirm.<br />
* <code>occurrence</code> – The numeric identifier of the occurrence to which the confirmation applies (in case "id" denotes a series appointment). Available with v7.6.0<br />
* <code>folder</code> – ID of the folder through which the appointment is accessed.<br />
* <code>timestamp</code> – Timestamp of the last update of the to confirmed appointment.<br />
<br />
Request body: An object with the fields "confirmation", "confirmmessage" and "id" (optional) as described in [[#UserParticipantObject | User participant object]].<br />
<br />
Response: Nothing, except the standard response object with empty data, the timestamp of the confirmed and thereby updated task, and maybe errors.<br />
<br />
=== Free & Busy ===<br />
<br />
GET <code>/ajax/calendar?action=freebusy</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> - Internal user id. Must be obtained from the contact module.<br />
* <code>type</code> - Constant for user or resource (1 for users, 3 for resources)<br />
* <code>start</code> – Lower inclusive limit of the queried range as a Date. Only appointments which end on or after this date are returned.<br />
* <code>end</code> – Upper exclusive limit of the queried range as a Date. Only appointments which start before this date are returned.<br />
<br />
Response: An array of objects identifying the appointments which lie between start and end as described.<br><br />
This objects consist of:<br />
{| id="FreeAndBusyAppointment" cellspacing="0" border="1"<br />
! Name !! Type !! Value<br />
|-<br />
| shown_as || Number || Describes, how this appointment appears in availability queries:<br />
{| cellspacing="0" border="1"<br />
| 1 || reserved<br />
|-<br />
| 2 || temporary<br />
|-<br />
| 3 || absent<br />
|-<br />
| 4 || free<br />
|}<br />
|-<br />
| start_date || Date or Time || see [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]]<br />
|- <br />
| end_date || Date or Time || see [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]]<br />
|-<br />
| id || String || Object ID<br />
|-<br />
| folder_id || String || Folder ID. Only set, if the user has the right to see the object. (added 2009-08-18/6.12) <br />
|-<br />
| full_time || Boolean || True if the appointment is a whole day appointment, not present otherwise.<br />
|}<br />
<br />
=== Search appointments ===<br />
<br />
PUT <code>/ajax/calendar?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
<br />
Request body: An Object as described in [[#SearchAppointments | Search appointments]].<br />
<br />
{| id="SearchAppointments" cellspacing="0" border="1"<br />
|+ align="bottom" | Search appointments<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find appointments. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|-<br />
| startletter || String || Search appointments with the given starting letter.<br />
|}<br />
<br />
Request body: An Object as described in [[#SearchAppointments | Search appointments]].<br />
<br />
Response: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get new appointments ===<br />
<br />
GET <code>/ajax/calendar?action=newappointments</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
* <code>start</code> – Lower inclusive limit of the queried range as a Date. Only appointments which end on or after this date are returned.<br />
* <code>end</code> – Upper exclusive limit of the queried range as a Date. Only appointments which start before this date are returned.<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified and holds a column number, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>limit</code> – limits the number of returned object to the given value.<br />
<br />
Response: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Resolve UID ===<br />
<br />
GET <code>/ajax/calendar?action=resolveuid</code><br />
<br />
Parameters<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>uid</code> – The UID to be resolved.<br />
<br />
Response: An object object with the field "id" containing the ox-object id, if existing, an error message otherwise.<br />
<br />
=== Get all Change Exceptions (Since v7.2.0) ===<br />
<br />
GET <code>/ajax/calendar?action=getChangeExceptions</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object id of the appointment series.<br />
* <code>folder</code> – Folder ID of the requested appointments. <br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier.<br />
<br />
Response with timestamp: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
== Module "mail" ==<br />
<br />
The mail module is used to access mail data.<br />
<br />
When mails are stored on an IMAP server, some functionality is not available due to restrictions of the IMAP protocol. Such functionality is marked with "not IMAP".<br />
<br />
=== Get mail count ===<br />
<br />
GET <code>/ajax/mail?action=count</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder whose mail count is queried<br />
<br />
Response (not IMAP: with timestamp): An integer value representing folder's mail count<br />
<br />
=== Get all mails ===<br />
<br />
GET <code>/ajax/mail?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#DetailedMailData | Detailed mail data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response or the string “thread” to return thread-sorted messages. If this parameter is specified and holds a column number, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>left_hand_limit</code> - A positive integer number to specify the "right-hand" limit of the range to return<br />
* <code>right_hand_limit</code> - A positive integer number to specify the "left-hand" limit of the range to return<br />
* <code>limit</code> - A positive integer number to specify how many items shall be returned according to given sorting; overrides <code>left_hand_limit</code>/<code>right_hand_limit</code> parameters and is equal to <code>left_hand_limit=0</code> and <code>right_hand_limit=&lt;limit&gt;</code><br />
<br />
Response (not IMAP: with timestamp): An array with mail data. Each array element describes one mail and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedMailData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed mail data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 102 || color_label || Number || Color number used by Outlook to label the object. The assignment of colors to numbers is arbitrary and specified by the client. The numbers are integer numbers between 0 and 10 (inclusive).<br />
|-<br />
| 600 || id || String || Object ID<br />
|-<br />
| 601 || folder_id || String || Object ID of the parent folder<br />
|-<br />
| 602 || attachment || Boolean || Specifies whether this mail has attachments.<br />
|-<br />
| 603 || from || Array || Each element is a two-element array specifying one sender. The first element of each address is the personal name, the second element is the email address. Missing address parts are represented by <code>null</code> values.<br />
|-<br />
| 604 || to || Array || Each element is a two-element array (see the from field) specifying one receiver.<br />
|-<br />
| 605 || cc || Array || Each element is a two-element array (see the from field) specifying one carbon-copy receiver.<br />
|-<br />
| 606 || bcc || Array || Each element is a two-element array (see the from field) specifying one blind carbon-copy receiver.<br />
|-<br />
| 607 || subject || String || Subject line.<br />
|-<br />
| 608 || size || Number || Size of the mail in bytes.<br />
|-<br />
| 609 || sent_date || Time || Date and time as specified in the mail by the sending client.<br />
|-<br />
| 610 || received_date || Time || Date and time as measured by the receiving server.<br />
|-<br />
| 611 || flags || Number || Various system flags. A sum of zero or more of following values:<br />
{| cellspacing="0" border="1"<br />
| 1 || answered<br />
|-<br />
| 2 || deleted<br />
|-<br />
| 4 || draft<br />
|-<br />
| 8 || flagged<br />
|-<br />
| 16 || recent<br />
|-<br />
| 32 || seen<br />
|-<br />
| 64 || user<br />
|-<br />
| 256 || forwarded<br />
|}<br />
See javax.mail.Flags.Flag for details.<br />
|-<br />
| 612 || level || Number || Zero-based nesting level in a thread.<br />
|-<br />
| 613 || disp_notification_to || String || Content of message's header “Disposition-Notification-To”<br />
|-<br />
| 614 || priority || Number || Value of message's “X-Priority” header:<br />
{| cellspacing="0" border="1"<br />
| 0 || No priority<br />
|-<br />
| 5 || Very Low<br />
|-<br />
| 4 || Low<br />
|-<br />
| 3 || Normal<br />
|-<br />
| 2 || High<br />
|-<br />
| 1 || Very High<br />
|}<br />
|-<br />
| 615 || msg_ref || String || Message reference on reply/forward.<br />
|-<br />
| 651 || flag_seen || String || Special field to sort mails by seen status<br />
|-<br />
| 652 || account_name || String || Message's account name.<br />
|-<br />
| 653 || account_id || int || Message's account identifier. Since v6.20.2<br />
|-<br />
| || user || Array || An array with user-defined flags as strings.<br />
|-<br />
| || headers || Object || An object with a field for every non-standard header. The header name is the field name. The header value is the value of the field as string.<br />
|-<br />
| || attachments || Array || Each element is an attachment as described in [[#Attachment | Attachment]]. The first element is the mail text. If the mail has multiple representations (multipart-alternative), then the alternatives are placed after the mail text and have the field disp set to alternative.<br />
|-<br />
| || nested_msgs || Array || Each element is a mail object as described in this table, except for fields id, folder_id and attachment.<br />
|-<br />
| || truncated || boolean || true/false if the mail content was trimmed. Since v7.6.1<br />
|-<br />
| || source || String || RFC822 source of the mail. Only present for <tt>action=get&attach_src=true</tt><br />
|}<br />
<br />
{| id="Attachment" cellspacing="0" border="1"<br />
|+ align="bottom" | Attachment<br />
! Name !! Type !! Value<br />
|-<br />
| id || String || Object ID (unique only inside the same message)<br />
|-<br />
| content_type || String || MIME type<br />
|-<br />
| content || String || Content as text. Present only if easily convertible to text.<br />
|-<br />
| filename || String || Displayed filename (mutually exclusive with content).<br />
|-<br />
| size || Number || Size of the attachment in bytes.<br />
|-<br />
| disp || String || Attachment's disposition: null, inline, attachment or alternative.<br />
|}<br />
<br />
=== Get all mail conversations (since v7.x) ===<br />
<br />
GET <code>/ajax/mail?action=threadedAll</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#DetailedMailData | Detailed mail data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response or the string “thread” to return thread-sorted messages. If this parameter is specified and holds a column number, then the parameter order must be also specified. <b>Note</b>: Applies only to root-level messages.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified. <b>Note</b>: Applies only to root-level messages.<br />
* <code>includeSent</code> - A boolean value to signal that conversations also include messages taken from special "sent" aka "sent items" folder<br />
* <code>left_hand_limit</code> - A positive integer number to specify the "right-hand" limit of the range to return. <b>Note</b>: Applies only to root-level messages.<br />
* <code>right_hand_limit</code> - A positive integer number to specify the "left-hand" limit of the range to return. <b>Note</b>: Applies only to root-level messages.<br />
* <code>limit</code> - A positive integer number to specify how many items shall be returned according to given sorting; overrides <code>left_hand_limit</code>/<code>right_hand_limit</code> parameters and is equal to <code>left_hand_limit=0</code> and <code>right_hand_limit=&lt;limit&gt;</code>. <b>Note</b>: Applies only to root-level messages.<br />
<br />
Response (not IMAP: with timestamp): An JSON array consisting of JSON objects, each representing a conversation's root message along with its message thread. The root message's JSON object is filled according to specified columns and is enhanced by special <code>"thread"</code> JSON field representing the full message thread (including the root message itself). The <code>"thread"</code> JSON field is a JSON array of JSON objects; each representing a message in the conversation sorted by time-line, also filled with specified columns. E.g.<br />
<br />
<pre><br />
{<br />
"flags":32,<br />
"color_label":0,<br />
"unreadCount":0,<br />
"id":"263852",<br />
"folder_id":"default0/INBOX",<br />
"thread":[<br />
{<br />
"id":"263852",<br />
"folder_id":"default0/INBOX",<br />
"flags":32,<br />
"color_label":0<br />
},<br />
{<br />
"id":"263853",<br />
"folder_id":"default0/INBOX",<br />
"flags":32,<br />
"color_label":0<br />
},<br />
{<br />
"id":"26323",<br />
"folder_id":"default0/Sent",<br />
"flags":32,<br />
"color_label":0<br />
},<br />
{<br />
"id":"263854",<br />
"folder_id":"default0/INBOX",<br />
"flags":32,<br />
"color_label":0<br />
}<br />
]<br />
}<br />
</pre><br />
<br />
=== Search mails ===<br />
<br />
PUT <code>/ajax/mail?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#DetailedMailData | Detailed mail data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response or the string “thread” to return thread-sorted messages. If this parameter is specified and holds a column number, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Request Body: A JSON array of JSON objects each containing the search field and its search pattern: e.g.:<br />
<code>[{"col": 612, "pattern": "Joe"}, {"col": 614, "pattern": "Tuesday"}]</code> Supported values for <code>col</code> are 603 to 607 (from, to, cc, bcc and subject) and -1 for full text search.<br />
<br />
Response (not IMAP: with timestamp): An array with mail data. Each array element describes one mail and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a list of mails ===<br />
<br />
PUT <code>/ajax/mail?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for mails are defined in [[#DetailedMailData | Detailed mail data]].<br />
* <code>headers</code> - (preliminary) A comma-separated list of header names. Each name requests denoted header from each mail<br />
<br />
Request body: An array with one object for each requested mail. Each object contains the fields <code>folder</code> and <code>id</code>.<br />
<br />
Response (not IMAP: with timestamp): An array with mail data. Each array element describes one mail and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter followed by requested headers.<br />
<br />
=== Copy mails ===<br />
<br />
PUT <code>/ajax/mail?action=copy</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested mail.<br />
* <code>folder</code> – Object ID of the source folder.<br />
<br />
Request Body: A JSON object containing the id of the destination folder inside the "folder_id" field: e.g.:<br />
<code>{"folder_id": 1376}</code><br />
<br />
Response: A JSON array containing the ID of the copied mail<br />
<br />
=== Move mails ===<br />
<br />
PUT <code>/ajax/mail?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested mail.<br />
* <code>folder</code> – Object ID of the source folder.<br />
<br />
Request Body: A JSON object containing the id of the destination folder inside the "folder_id" field: e.g.:<br />
<code>{"folder_id": 1376}</code><br />
<br />
<br />
Response: A JSON array containing the ID of the moved mail<br />
<br />
=== Update mails ===<br />
<br />
PUT <code>/ajax/mail?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested mail.<br />
* <code>message_id</code> – (Preliminary) The value of "Message-Id" header of the requested mail. This parameter is a substitute for "id" parameter.<br />
* <code>folder</code> – Object ID of the folder.<br />
<br />
'''Note''': If neither parameter "<code>id</code>" nor parameter "<code>message_id</code>" is specified, all folder's messages are updated accordingly. Available with v6.20.<br />
<br />
Request Body: A JSON object which carries the new values that ought to be applied to mail as described in [[#UpdateMail | Update mail]] or [[#UpdateMailExtended | Update mail extended]] (available with SP6 v6.10).<br />
<br />
Response: A JSON object containing the Object ID of the updated mail and its folder.<br />
<br />
{| id="UpdateMail" cellspacing="0" border="1"<br />
|+ align="bottom" | Update mail<br />
! Name !! Type !! Value<br />
|-<br />
| color_label || Number || The color number between 0 and 10.<br />
|-<br />
| flags || Number || A set of flags to add or remove. Note: Flags for "recent" (8) and "user" (64) are ignored.<br />
|-<br />
| value || Boolean || <code>true</code> to add the flags specified by <code>flags</code> (logical OR), <code>false</code> to remove them (logical AND with the inverted value).<br />
|}<br />
<br />
<br />
<br />
{| id="UpdateMailExtended" cellspacing="0" border="1"<br />
|+ align="bottom" | Update mail extended (available with SP6 v6.10)<br />
! Name !! Type !! Value<br />
|-<br />
| set_flags || Number || A set of flags to add. Note: Flags for "recent" (8) and "user" (64) are ignored.<br />
|-<br />
| clear_flags || Number || A set of flags to remove. Note: Flags for "recent" (8) and "user" (64) are ignored.<br />
|}<br />
<br />
<br />
=== Mark all mails as seen (available with v7.6.0) ===<br />
<br />
PUT <code>/ajax/mail?action=all_seen</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder.<br />
<br />
Request Body: n.a.<br />
<br />
Response: <code>true</code><br />
<br />
=== Not IMAP: Get updated mails ===<br />
<br />
GET <code>/ajax/mail?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: Just an empty JSON array is going to be returned since this action cannot be applied to IMAP.<br />
<br />
=== Get a mail ===<br />
<br />
GET <code>/ajax/mail?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested mail.<br />
* <code>message_id</code> – (Preliminary) The value of "Message-Id" header of the requested mail. This parameter is a substitute for "id" parameter.<br />
* <code>folder</code> – Object ID of the mail's folder.<br />
* <code>edit</code> (optional) – 1 indicates that this request should fill the message compose dialog to edit a message and thus display-specific date is going to be withheld.<br />
* <code>hdr</code> (optional) – 1 to let the response contain only the (formatted) message headers as plain text<br />
* <code>src</code> (optional) – 1 to let the response contain the complete message source as plain text<br />
* <code>save</code> (optional) – 1 to write the complete message source to output stream. '''NOTE:''' This parameter will only be used if parameter <code>src</code> is set to 1.<br />
* <code>view</code> (optional - available with SP4)<br />
** "raw" returns the content as it is, meaning no preparation are performed and thus no guarantee for safe contents is given (available with SP6 v6.10).<br />
** "text" forces the server to deliver a text-only version of the requested mail's body, even if content is HTML.<br />
** "textNoHtmlAttach" is the same as "text", but does not deliver the HTML part as attachment in case of multipart/alternative content.<br />
** "html" to allow a possible HTML mail body being transferred as it is (but white-list filter applied).<br />
** "noimg" to allow a possible HTML content being transferred but without original image src attributes which references external images: Can be used to prevent loading external linked images (spam privacy protection).<br />
** '''NOTE:''' if set, the corresponding gui config setting will be ignored.<br />
* <code>unseen</code> (optional) – "1" or "true" to leave an unseen mail as unseen although its content is requested<br />
* <code>max_size</code> (optional - available since v7.6.1) A positive integer number (greater than 10000) to specify how many characters of the message content will be returned. If the number is smaller than 10000 the value will be ignored and 10000 used.<br />
* <code>attach_src</code> (optional - available since v7.6.1) 1 to let the JSON mail representation being extended by <code>"source"</code> field containing the mail raw RFC822 source data<br />
<br />
Response (not IMAP: with timestamp): An JSON object containing all data of the requested mail. The fields of the object are listed in [[#DetailedMailData | Detailed mail data]]. The fields id and attachment are not included. '''NOTE:''' Of course response is not a JSON object if either parameter <code>hdr</code> or parameter <code>src</code> are set to "1". Then the response contains plain text. Moreover if optional parameter <code>save</code> is set to "1" the complete message source is going to be directly written to output stream to open browser's save dialog.<br />
<br />
=== Get multiple mails as a ZIP file ===<br />
<br />
GET <code>/ajax/mail?action=zip_messages</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – The folder identifier.<br />
* <code>id</code> – A comma-separated list of Object IDs of the requested mails<br />
<br />
Response body: The raw byte data of the ZIP file.<br />
<br />
=== Get a mail attachment ===<br />
<br />
GET <code>/ajax/mail?action=attachment</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – The folder identifier.<br />
* <code>id</code> – Object ID of the mail which contains the attachment.<br />
* <code>attachment</code> – ID of the requested attachment '''OR'''<br />
* <code>cid</code> – Value of header 'Content-ID' of the requested attachment<br />
* <code>save</code> – 1 overwrites the defined mimetype for this attachment to force the download dialog, otherwise 0.<br />
* <code>filter</code> (optional) – 1 to apply HTML white-list filter rules if and only if requested attachment is of MIME type <code>text/htm*</code> '''AND''' parameter <code>save</code> is set to 0.<br />
<br />
Response body: The raw byte data of the document. The response type for the HTTP Request is set accordingly to the defined mimetype for this attachment, except the parameter save is set to 1.<br />
<br />
=== Get multiple mail attachments as a ZIP file ===<br />
<br />
GET <code>/ajax/mail?action=zip_attachments</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – The folder identifier.<br />
* <code>id</code> – Object ID of the mail which contains the attachments.<br />
* <code>attachment</code> – A comma-separated list of IDs of the requested attachments<br />
<br />
Response body: The raw byte data of the ZIP file.<br />
<br />
=== Send a mail ===<br />
<br />
POST <code>/ajax/mail?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request Body: This method uses the encoding multipart/form-data or multipart/mixed.<br />
* The form filed <code>json_0</code> contains the rudimentary mail as JSON object as described in [[#DetailedMailData | Detailed mail data]] with just its message body (as html content) defined in nested JSON array "attachments" and its header data (from, to, subject, etc.). The field "content_type" defines whether the mail ought to be sent as plain text ("text/plain"), as html ("text/html") or as multipart/alternative ("ALTERNATIVE"). Sending a mail requires some special fields inside JSON mail object. The field "infostore_ids" defines a JSON array of infostore document ID(s) that ought to be appended to this mail as attachments. The field "msgref" indicates the ID of the referenced original mail. Moreover the field "sendtype" indicates the type of the message:<br />
** 0 - A normal new mail (optional)<br />
** 1 - A reply mail. The field "msgref" must be present<br />
** 2 - A forward mail. The field "msgref" must be present<br />
** 3 - A draft edit operation. The field "msgref" must be present in order to delete previous draft message since e.g. IMAP does not support changing/replacing a message but requires a delete-and-insert sequence<br />
** 4 - Transport of a draft mail. The field "msgref" must be present<br />
** 6 - This type signals that user intends to send out a saved draft message and expects the draft message (referenced by "msgref" field) being deleted after successful transport<br />
Example of a normal new mail which appends user's VCard and requests a read receipt from receiver:<br />
<br />
<code>Content-Disposition: form-data; name="json_0"....{"from":"\u0022Muster, Karl\u0022 <karl.muster@somewhere.com>","to":"someone@somewhere.com","cc":"","bcc":"",<br />
"subject":"Mail Subject","priority":"3","disp_notification_to":true,"vcard":1,<br />
"attachments":[{"content_type":"ALTERNATIVE","content":"Simple Mail Text!&lt;br&gt;&lt;br&gt;\u000a\u000a"}]}</code><br />
* The request accepts file fields in upload form that denote referenced files that are going to be appended as attachments<br />
* For "text/plain" mail bodies, the JSON boolean field "raw" may be specified inside the body's JSON representation to signal that the text content shall be kept as-is; meaning to keep all formatting intact<br />
<br />
==== Attach data sources ====<br />
Moreover the JSON representation may contain data sources which should be appended as file attachments to the mail. Then the mail contains the <code>"datasources"</code> key which is expected to be a JSON array of data source descriptions.<br />
<br />
A data source description follows the [[#Module_.22conversion.22_.28preliminary.29 | conversion specification]].<br />
<br />
For example to attach a file through an URL the field looks like this (available with v6.18.2):<br />
<br />
<pre><br />
{<br />
"from": "someone@somewhere.com,<br />
...<br />
"datasources"<br />
[<br />
{<br />
"identifier": "com.openexchange.url.mail.attachment",<br />
"args":<br />
{<br />
"url": <url-string>,<br />
"timeout": <optional-timeout-millis-int, default is 2500msec>,<br />
"contentType": <optional-content-type-string>,<br />
"charset": <optional-charset-string>,<br />
"size": <optional-size-int>,<br />
"disposition": <optional-disposition-string>,<br />
"fileName": <optional-file-name-string>,<br />
}<br />
}<br />
]<br />
}<br />
</pre><br />
<br />
Response: Object ID of the newly created mail.<br />
<br />
=== Send/Save mail as MIME data block (RFC822) (added in SP5) ===<br />
<br />
PUT <code>/ajax/mail?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> - A session ID previously obtained from the login module.<br />
* <code>folder</code> (optional) - In case the mail should not be sent out, but saved in a specific folder, the "folder" parameter can be used. If the mail should be sent out to the recipient, the "folder" parameter must not be included and the mail is stored in the folder "Sent Items". Example "folder=default.INBOX/Testfolder"<br />
* <code>flags</code> (optional) - In case the mail should be stored with status "read" (e.g. mail has been read already in the client inbox), the parameter "flags" has to be included. If no "folder" parameter is specified, this parameter must not be included. For infos about mail flags see [[#DetailedMailData | Detailed mail data]] spec.<br />
<br />
Request Body: The MIME Data Block<br />
<br />
Response: Object ID of the newly created/moved mail.<br />
<br />
=== Import of mails as MIME data block (RFC822) (added with 6.18) ===<br />
<br />
This request can be used to store a single or a lot of mails in the OX mail storage backend. This action should be used instead of <code>action=new</code> because it is faster and tolerant to 8bit encoded emails.<br />
<br />
<code>POST /ajax/mail?action=import</code><br />
<br />
Parameters:<br />
* <code>session</code> - A session ID previously obtained from the login module.<br />
* <code>folder</code> - For the import this parameter is required to specify the folder into that the emails should be imported. Example "folder=default.INBOX/Testfolder"<br />
* <code>flags</code> (optional) - In case the mail should be stored with status "read" (e.g. mail has been read already in the client inbox), the parameter "flags" has to be included. For infos about mail flags see [[#DetailedMailData | Detailed mail data]] spec.<br />
*<code>force</code> (optional) - If this parameter is set to true, the server skips checking the valid From-address<br />
<br />
Request Body: A multipart/form-data with a single or multiple file parts each having a different name and containing the RFC822 encoded email as binary data like in a file upload.<br />
<br />
Response: A JSON object containing the folder identifier and the object identifier of the imported mail or a JSON array of those JSON objects if multiple mails are imported.<br />
<br />
=== Reply/Forward a mail ===<br />
<br />
GET <code>/ajax/mail?action=reply</code><br><br />
GET <code>/ajax/mail?action=replyall</code><br><br />
GET <code>/ajax/mail?action=forward</code><br><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested Message.<br />
* <code>folder</code> - Object ID of the folder, whose contents are queried.<br />
* <code>view</code> (optional - available with SP6) - "text" forces the server to deliver a text-only version of the requested mail's body, even if content is HTML. "html" to allow a possible HTML mail body being transferred as it is (but white-list filter applied).'''NOTE:''' if set, the corresponding gui config setting will be ignored.<br />
* <code>setFrom</code> (optional - available since v7.6.0) A flag ("true"/"false") that signals if "From" header shall be pre-selected according to a suitable recipient address that matches one of user's E-Mail address aliases; only supported for <code>/ajax/mail?action=replyall</code> and <code>/ajax/mail?action=reply</code><br />
* <code>max_size</code> (optional - available since v7.6.1) A positive integer number (greater than 10000) to specify how many characters of the message content will be returned. If the number is smaller than 10000 the value will be ignored and 10000 used.<br />
<br />
Response (not IMAP: with timestamp): An object containing all data of the requested mail. The fields of the object are listed in [[#DetailedMailData | Detailed mail data]]. The fields id and attachment are not included.<br />
<br />
=== Delete mails ===<br />
<br />
PUT <code>/ajax/mail?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* Not IMAP: <code>timestamp</code> – Timestamp of the last update of the deleted mails.<br />
<br />
Request body: An array of objects providing folder IDs and object IDs of the deleted mails.<br />
<code><br><br />
[<br><br />
&nbsp;{&nbsp;&quot;folder&quot;:&quot;default0/INBOX&quot;,&nbsp;&quot;id&quot;:&quot;123&quot;&nbsp;}<br><br />
&nbsp;...<br><br />
&nbsp;{&nbsp;&quot;folder&quot;:&quot;default0/MyFolder&quot;,&nbsp;&quot;id&quot;:&quot;134&quot;&nbsp;}<br><br />
]<br><br />
</code><br />
<br />
Not IMAP: Response: An array with object IDs of mails which were modified after the specified timestamp and were therefore not deleted.<br />
<br />
=== Clear mail folder(s) ===<br />
<br />
PUT <code>/ajax/mail?action=clear</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* Not IMAP: <code>timestamp</code> – Timestamp of the last update of the deleted mails.<br />
<br />
Request body: An array with IDs of the mail folders to clear<br />
<br />
Response: An array with IDs of mail folder that could not be cleared; meaning the response body is an empty JSON array if everything went well.<br />
<br />
== Module "groups" ==<br />
<br />
The group module allows to query available groups. It is mainly used by the dialog for the selection of participants.<br />
<br />
=== Get a group ===<br />
<br />
GET <code>/ajax/group?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The group id.<br />
<br />
Response: A group object as described in [[#GroupData | Group data]].<br />
<br />
=== List groups ===<br />
<br />
PUT <code>/ajax/group?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An array with group identifiers.<br />
<br />
Response: An array of group objects as described in [[#GroupData | Group data]].<br />
<br />
=== Search for groups ===<br />
<br />
PUT <code>/ajax/group?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An object with search parameters as described in [[#GroupSearch | Group search]].<br />
<br />
{| id="GroupSearch" cellspacing="0" border="1"<br />
|+ align="bottom" | Group search<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find groups. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|}<br />
<br />
Response with timestamp: An array of group objects as described in [[#GroupData | Group data]].<br />
<br />
{| id="GroupData" cellspacing="0" border="1"<br />
|+ align="bottom" | Group data<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || ID<br />
|-<br />
| display_name || String || Display name<br />
|-<br />
| name || String || Name with character restrictions<br />
|-<br />
| members || Array || The array contains identifier of users that are member of the group.<br />
|}<br />
<br />
=== Create a group ===<br />
<br />
introduced 2008-06-12<br />
<br />
PUT <code>/ajax/group?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Group object as described in [[#GroupData | Group data]]. The field id is not present.<br />
<br />
Response: A json objekt with attribute <code>id</code> of the newly created group.<br />
<br />
=== Delete a group ===<br />
<br />
introduced 2008-06-12<br />
<br />
PUT <code>/ajax/group?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the group to delete.<br />
<br />
Request body: An object with the field “id” containing the unique identifier of the group.<br />
<br />
Response: An empty json array if the group was deleted successfully.<br />
<br />
=== Change a group ===<br />
<br />
introduced 2008-06-12<br />
<br />
PUT <code>/ajax/group?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the group to update.<br />
* <code>timestamp</code> – Time stamp of the group to update. If the group was modified after the specified time stamp, then the update must fail. <br />
<br />
Request body: Group object as described in [[#GroupData | Group data]]. Only modified fields are present and the field id is omitted.<br />
<br />
=== Get updates (since v6.18.1) ===<br />
<br />
introduced 2010-09-13<br />
<br />
GET <code>/ajax/group?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested groups.<br />
<br />
Response with timestamp: An array with new, modified and deleted groups. New, modified and deleted groups are represented by JSON objects as described in [[#GroupData | Group data]].<br />
<br />
== Module "resource" ==<br />
<br />
The resource module allows to query available resources. It is mainly used by the dialog for the selection of participants.<br />
<br />
=== Get all resources ===<br />
<br />
GET <code>/ajax/resource?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: An array of resource identifier.<br />
<br />
=== List resources ===<br />
<br />
PUT <code>/ajax/resource?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
<br />
Request body: An array with resources ids.<br />
<br />
Response: An array of resource objects as described in [[#ResourceResponse | Resource response]].<br />
<br />
=== Get a resource ===<br />
<br />
GET <code>/ajax/resource?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The resource id.<br />
<br />
Response: An array of resource objects as described in [[#ResourceResponse | Resource response]].<br />
<br />
=== Search for resources ===<br />
<br />
PUT <code>/ajax/resource?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An object with search parameters as described in [[#ParticipantSearch | Participant search]].<br />
<br />
{| id="ParticipantSearch" cellspacing="0" border="1"<br />
|+ align="bottom" | Participant search<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find resources. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|}<br />
<br />
Response: An array of resource objects as described in [[#ResourceResponse | Resource response]].<br />
<br />
{| id="ResourceResponse" cellspacing="0" border="1"<br />
|+ align="bottom" | Resource Response<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || ID<br />
|-<br />
| display_name || String || Display name<br />
|-<br />
| name || String || internal name<br />
|-<br />
| mailaddress || String || email address<br />
|-<br />
| availability || Boolean || can be false to mark the resource currently unavailable<br />
|-<br />
| description || String || description of the resource<br />
|-<br />
| last_modified || Time || Date and time of the last modification.<br />
|-<br />
| last_modified_utc || Timestamp || Date and time of the last modification.<br />
|}<br />
<br />
=== Create a resource ===<br />
<br />
PUT <code>/ajax/resource?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Resource object as described in [[#ResourceResponse | Resource response]]. The field id is not present.<br />
<br />
Response: An object with attribute <code>id</code> of the newly created resource.<br />
<br />
=== Delete a resource ===<br />
<br />
PUT <code>/ajax/resource?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the resource to delete.<br />
<br />
Request body: An object with the field “id” containing the unique identifier of the resource.<br />
<br />
Response: An empty json array if the resource was deleted successfully.<br />
<br />
=== Delete resources (since v6.22) ===<br />
<br />
PUT <code>/ajax/resource?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the resource to delete.<br />
<br />
Request body: An array of objects with the field “id” containing the unique identifier of the resource.<br />
<br />
Response: An empty json array if the resources were deleted successfully.<br />
<br />
=== Change a resource ===<br />
<br />
PUT <code>/ajax/resource?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the resource to update.<br />
* <code>timestamp</code> – Time stamp of the resource to update. If the resource was modified after the specified time stamp, then the update must fail. <br />
<br />
Request body: Resource object as described in [[#ResourceResponse | Resource response]]. Only modified fields are present and the field id is omitted.<br />
<br />
=== Get updates (since v6.18.1) ===<br />
<br />
introduced 2010-09-13<br />
<br />
GET <code>/ajax/resource?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested resources.<br />
<br />
Response with timestamp: An array with new, modified and deleted resources. New, modified and deleted resources are represented by JSON objects as described in [[#ResourceResponse | Resource response]].<br />
<br />
== Module "infostore" or "Filestore" or "Files" or "Drive" ==<br />
This module has been renamed quite often. Whatever its name, it combines the knowledge database, bookmarks and document storage.<br />
<br />
=== Get all infoitems ===<br />
<br />
GET <code>/ajax/infostore?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for infoitems are defined in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response with timestamp: An array with infoitem data. Each array element describes one infoitem and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedInfoitemData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed infoitem data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 108 || object_permissions || Array || Each element is an object described in [[#ObjectPermissionObject | Object Permission object]] (preliminary, available with 7.8.0).<br />
|-<br />
| 700 || title || String || Title<br />
|-<br />
| 701 || url || String || Link/URL<br />
|-<br />
| 702 || filename || String || Displayed filename of the document.<br />
|-<br />
| 703 || file_mimetype || String || MIME type of the document. The client converts known types to more readable names before displaying them.<br />
|-<br />
| 704 || file_size || Number || Size of the document in bytes.<br />
|-<br />
| 705 || version || Number || Version number of the document. New documents start at 1. Every update increments the version by 1.<br />
|-<br />
| 706 || description || String || Description<br />
|-<br />
| 707 || locked_until || Time || The time until which this item will presumably be locked. Only set if the docment is currently locked, 0 otherwise.<br />
|-<br />
| 708 || file_md5sum || String || MD5Sum of the document. Not yet implemented, so this is currently always empty.<br />
|-<br />
| 709 || version_comment || String || A version comment is used to file a changelog for the file.<br />
|-<br />
| 710 || current_version || Boolean || “true” if this version is the current version “false” otherwise. . Note: This is not writeable<br />
|-<br />
| 711 || number_of_versions || Number || The number of all versions of the infoitem. Note: This is not writeable.<br />
|}<br />
<br />
{| id="ObjectPermissionObject" cellspacing="0" border="1"<br />
|+ align="bottom" | Object Permission object<br />
! Name !! Type !! Value<br />
|-<br />
| bits || Number || A number as described in [[#ObjectPermissionFlags | Object Permission flags]].<br />
|-<br />
| entity || Number || User ID of the user or group to which this permission applies.<br />
|-<br />
| group || Boolean || true if entity refers to a group, false if it refers to a user.<br />
|-<br />
| type || String || The recipient type, i.e. one of "guest", "anonymous" (required if no internal "entity" defined).<br />
|-<br />
| password || String || An additional secret / pin number an anonymous user needs to enter when accessing the share (for type "anonymous", optional) .<br />
|-<br />
| email_address || String || The e-mail address of the recipient (for type "guest").<br />
|-<br />
| display_name || String || The display name of the recipient (for type "guest", optional).<br />
|-<br />
| contact_id || String || The object identifier of the corresponding contact entry if the recipient was chosen from the address book (for type "guest", optional).<br />
|-<br />
| contact_folder || String || The folder identifier of the corresponding contact entry if the recipient was chosen from the address book (for type "guest", required if "contact_id" is set).<br />
|-<br />
| expiry_date || Time || The end date / expiration time after which the share link is no longer accessible (for type "guest" or "anonymous", optional).<br />
|}<br />
<br />
{| id="ObjectPermissionFlags" cellspacing="0" border="1"<br />
|+ align="bottom" | Object Permission flags<br />
! Bits !! Value<br />
|-<br />
| 0 || The numerical value indicating no object permissions.<br />
|-<br />
| 1 || The numerical value indicating read object permissions.<br />
|-<br />
| 2 || The numerical value indicating write object permissions. This implicitly includes the “read” permission (this is no bitmask).<br />
|-<br />
| 4 || The numerical value indicating delete object permissions. This implicitly includes the “read” and “write” permission (this is no bitmask).<br />
|}<br />
<br />
=== Get a list of infoitems ===<br />
<br />
PUT <code>/ajax/infostore?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for infoitems are defined in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
<br />
Request body: An array with object IDs of requested infoitems.<br />
<br />
Response with timestamp: An array with infoitem data. Each array element describes one infoitem and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get updated infoitems ===<br />
<br />
GET <code>/ajax/infostore?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for infoitems are defined in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested infoitems.<br />
* <code>ignore</code> (optional) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
<br />
Response with timestamp: An array with new, modified and deleted infoitems. New and modified infoitems are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted infoitems (should the <code>ignore</code> parameter be ever implemented) would be identified by their object IDs as plain strings, without being part of a nested array.<br />
<br />
=== Get an infoitem ===<br />
<br />
GET <code>/ajax/infostore?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested infoitem.<br />
* <code>version</code> (optional) – If present the infoitem data describes the given version. Otherwise the current version is returned <br />
<br />
Response with timestamp: An object containing all data of the requested infoitem. The fields of the object are listed in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. The field id is not included.<br />
<br />
=== Search infoitems ===<br />
<br />
PUT <code>/ajax/infostore?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields as per tables [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>start</code> (optional) – The start index (inclusive) in the ordered search, that is requested.<br />
* <code>end</code> (optional) – The last index (inclusive) from the ordered search, that is requested.<br />
<br />
Request body: An Object as described in [[#SearchContacts | Search contacts]].<br />
<br />
=== Get an infoitem document ===<br />
<br />
GET <code>/ajax/infostore/[filename]?action=document</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested infoitem.<br />
* <code>folder</code> – Object ID of the infoitem's folder.<br />
* <code>version</code> (optional) – If present the infoitem data describes the given version. Otherwise the current version is returned <br />
* <code>content_type</code>(optional) – If present the response declares the given content_type in the Content-Type header.<br />
<br />
Response body: The raw byte data of the document. The response type for the HTTP Request is set accordingly to the defined mimetype for this infoitem or the content_type given.<br />
<br />
Note: The Filename may be added to the customary infostore path to suggest a filename to a Save-As dialog.<br />
<br />
=== Get a ZIP archive containing the infoitems of a denoted folder (available with v7.6.1) ===<br />
<br />
GET <code>/ajax/infostore/[filename]?action=document</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the infoitem's folder.<br />
* <code>recursive</code> – <code>true</code> to also include subfolders and their infoitems respectively; otherwise <code>false</code> to only consider the infoitems of specified folder<br />
<br />
Response body: The raw byte data of the ZIP archive. The response type for the HTTP Request is set to <code>application/zip</code>.<br />
<br />
=== Get all versions ===<br />
<br />
GET <code>/ajax/infostore?action=versions</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the infoitem whose versions are requested.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for infoitems are defined in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response with timestamp: An array with infoitem data. Each array element describes one infoitem and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. The timestamp is the timestamp relating to the requested infostore item.<br />
<br />
=== Get multiple documents as a ZIP archive (available with v7.4.0) ===<br />
<br />
GET <code>/ajax/infostore?action=zipdocuments</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>body</code> – A URL-encoded JSON array; see below for details<br />
<br />
Parameter <code>body</code>: A JSON array of JSON object tuples specifying the documents' versions to include in the requested ZIP archive; e.g<br><br />
<pre><br />
[{"id":"61820","folder":"70303"},{"id":"61821","folder":"70303", "version": "1"}]<br />
</pre><br />
The field <code>"version"</code> is optional; if missing it refers to latest/current version.<br><br />
So, a valid parameter would look like:<br />
<pre><br />
...&body=%5B%7B%22id%22%3A%2261820%22%2C%22folder%22%3A%2270303%22%7D%2C%7B%22id%22%3A%2261821%22%2C%22folder%22%3A%2270303%22%2C%22version%22%3A%221%22%7D%5D<br />
</pre><br />
<br />
Response: The download offer for the requested ZIP archive containing specified document versions<br />
<br />
=== Update an infoitem via PUT ===<br />
<br />
PUT <code>/ajax/infostore?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated infoitem.<br />
* <code>timestamp</code> – Timestamp of the updated infoitem. If the infoitem was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. Only modified fields are present.<br />
<br />
=== Update an infoitem via POST ===<br />
<br />
POST <code>/ajax/infostore?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated infoitem.<br />
* <code>timestamp</code> – Timestamp of the updated infoitem. If the infoitem was modified after the specified timestamp, then the update must fail.<br />
* <code>json</code> - Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. Only modified fields are present.<br />
* <code>file</code> – File Metadata as per <input type=”file” /><br />
<br />
Request Body: Body of content-type “multipart/form-data” or “multipart/mixed” containing the above mentioned fields and file-data.<br />
<br />
Response: The response is sent as a HTML document (see introduction).<br />
<br />
=== Create an infoitem via PUT ===<br />
<br />
PUT <code>/ajax/infostore?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. The field id is not included.<br />
<br />
Response: Object ID of the newly created infoitem.<br />
<br />
=== Create an infoitem via POST ===<br />
<br />
POST <code>/ajax/infostore?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>json</code> - Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. The field id is not included.<br />
* <code>file</code> – File metadata as per <input type=”file” /><br />
<br />
Request Body: Body of content-type “multipart/form-data” or “multipart/mixed” containing the above mentioned fields and file-data.<br />
<br />
Response: Object ID of the newly created infoitem. The response is sent as a HTML document (see introduction).<br />
<br />
=== Save an attachment in the infostore ===<br />
<br />
PUT <code>/ajax/infostore?action=saveAs</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>attached</code> – The Object ID of the Object with the attachment<br />
* <code>folder</code> – The Folder ID of the Object with the attachment<br />
* <code>module</code> – The Module type of the Object with the attachment.<br />
* <code>Attachment</code> – The id of the attachement to save.<br />
<br />
Request body: Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. The field id is not included. The fields in this infoitem object override values from the attachment. The folder_id must be given.<br />
<br />
Response: Object ID of the newly created infoitem.<br />
<br />
=== Delete infoitems ===<br />
<br />
PUT <code>/ajax/infostore?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted infoitems.<br />
* <code>hardDelete</code> - Optional, defaults to \"false\". If set to \"true\", the file is deleted permanently. Otherwise, and if the underlying storage supports a trash folder and the file is not yet located below the trash folder, it is moved to the trash folder.<br />
<br />
Request body: An array with objects to delete. The fields for the object are described in [[#FullIdentifierForAnInfostoreDocument|Full identifier for an infostore document]].<br />
<br />
Response: An array with [[]]. <br />
<br />
{| id="FullIdentifierForAnInfostoreDocument" cellspacing="0" border="1"<br />
|+ align="bottom" | Full identifier for an infostore document<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || Object ID<br />
|-<br />
| folder || Number || Folder ID<br />
|}<br />
<br />
=== Delete versions of infostore documents ===<br />
<br />
PUT <code>/ajax/infostore?action=detach</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the base Object<br />
* <code>folder</code> – The Folder of the Object<br />
* <code>timestamp</code> - Timestamp of the infostore object<br />
<br />
Request body: A List of arrays with the version numbers of the infoitems to detach.<br />
<br />
Response: An array with version numbers that were not deleted.<br />
<br />
Note: When the current version of a document is deleted the new current version will be the newest version.<br />
<br />
=== Delete all versions of infostore documents ===<br />
<br />
PUT <code>/ajax/infostore?action=revert</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the base Object<br />
* <code>folder</code> – The Folder of the Object<br />
* <code>timestamp</code> - Timestamp of the infostore object<br />
<br />
Removes all versions of the infostore document leaving only the base object.<br />
<br />
=== Copy an infostore document via PUT ===<br />
<br />
PUT <code>/ajax/infostore?action=copy</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the base Object<br />
* <code>folder</code> – The Folder of the Object<br />
* <code>timestamp</code> - Timestamp of the infostore object<br />
<br />
Request body: Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. Only modified fields are present.<br />
<br />
Response: The id of the newly created object<br />
<br />
Note: Only the fields (and the file) of the current document will be copied. Those fields present in the request are modified accordingly.<br />
<br />
=== Copy an infostore document via POST ===<br />
<br />
POST <code>/ajax/infostore?action=copy</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated infoitem.<br />
* <code>timestamp</code> – Timestamp of the updated infoitem. If the infoitem was modified after the specified timestamp, then the update must fail.<br />
* <code>json</code> - Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. Only modified fields are present.<br />
* <code>file</code> – File Metadata as per <input type=”file” /><br />
<br />
Request Body: Body of content-type “multipart/form-data” or “multipart/mixed” containing the above mentioned fields and file-data.<br />
<br />
Response: The response is sent as a HTML document (see introduction).<br />
<br />
Note: Only the fields (and the file) of the current document will be copied. Those fields present in the request are modified accordingly.<br />
<br />
=== Lock an infoitem ===<br />
<br />
GET <code>/ajax/infostore?action=lock</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the infoitem that should be locked.<br />
* <code>diff</code> (optional) – If present the value is added to the current time on the server (both in ms). The document will be locked until that time. If this parameter is not present, the document will be locked for a duration as configured on the server.<br />
<br />
Response with timestamp: Can only include errors.<br />
<br />
=== Unlock an infoitem ===<br />
<br />
GET <code>/ajax/infostore?action=unlock</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the infoitem that should be unlocked.<br />
<br />
Response with timestamp: Can only contain errors.<br />
<br />
<br />
== Module "Attachments" ==<br />
<br />
The Attachment Module allows file attachments to arbitrary objects. An Attachment always belongs to an object (called 'attached') in a certain folder of a certain module. <br />
<br />
=== Get All Attachments for an Object ===<br />
<br />
GET <code>/ajax/attachment?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>attached</code> – The Object ID of the Object<br />
* <code>folder</code> – The Folder ID of the Object<br />
* <code>module</code> – The Module type of the Object<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for attachment's are defined in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response: An array with attachment data. Each array element describes one attachment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a list of attachments ===<br />
<br />
PUT <code>/ajax/attachment?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for attachments are defined in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]].<br />
* <code>attached</code> – The Object ID of the Object<br />
* <code>folder</code> – The Folder ID of the Object<br />
* <code>module</code> – The Module type of the Object<br />
<br />
Request body: An array of with object IDs of requested tasks.<br />
<br />
Response with timestamp: An array with attachment data. Each array element describes one attachment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Create an Attachment ===<br />
<br />
POST <code>/ajax/attachment?action=attach</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>json_[index]</code> – The JSON representation of an attachment object as described in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]].<br />
* <code>file_[index]</code> – The file metadata as per <input type=file /> upload.<br />
<br />
Note: The JSON Object and file fields describe the corresponding attachment. For ex.: json_0 contains metadata for file_0, json_1 for file_1 and so on. Indexes start with 0.<br />
<br />
Request body: multipart/form-data or multipart/mixed containing the file data of the attached file and the above fields.<br />
<br />
Response: HTML page with javascript callback as per introduction. Contains a JSON-Array of ids of the newly created attachments. The order of the ids corresponds to the indexes in the request.<br />
<br />
{| id="AttachmentObject" cellspacing="0" border="1"<br />
|+ align="bottom" | Attachment Object<br />
! ID !! Name !! Type !! Description<br />
|-<br />
| 800 || folder || Number || The ID of the first Folder in which the attached object resides.<br />
|-<br />
| 801 || attached || Number || The object id of the object this attachement is attached to.<br />
|-<br />
| 802 || module || Number || The Module of this Object Possible Values:<br />
{| cellspacing="0" border="1"<br />
| 1 || Appointment<br />
|-<br />
| 4 || Task<br />
|-<br />
| 7 || Contact<br />
|-<br />
| 137 || Infostore<br />
|}<br />
|-<br />
| 803 || filename || String || The filename of the attached file.<br />
|-<br />
| 804 || file_size || Number || The file size (in bytes) of the attached file.<br />
|-<br />
| 805 || file_mimetype || String || The MIME-Type of the attached file<br />
|-<br />
| 806 || rft_flag || Boolean || If the attachment is a RTF Attachment of Outlook. (Outlook descriptions can be stored as RTF Documents).<br />
|}<br />
<br />
=== Delete Attachment ===<br />
<br />
PUT <code>/ajax/attachment?action=detach</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>attached</code> – The ID of the base Object<br />
* <code>module</code> – The type of the Object<br />
* <code>folder</code> – The Folder of the Object<br />
<br />
Request body: An array with the ids of the attachments to delete.<br />
<br />
=== Get updated attachments ===<br />
<br />
GET <code>/ajax/attachment?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>attached</code> – Object ID of the object to which the attachments are attached.<br />
* <code>module</code> – Module ID (as per [[#AttachmentObject | Attachment object]]) of the attached object.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for attachments are defined in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested infoitems.<br />
ignore (optional) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
<br />
Response with timestamp: An array with new and deleted attachments for the specified object. New attachments are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted attachments (should the <code>ignore</code> parameter be ever implemented) would be identified by their object IDs as plain numbers, without being part of a nested array.<br />
<br />
=== Get an attachment ===<br />
<br />
GET <code>/ajax/attahment?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>attached</code> – Object ID of the object to which the attachments are attached.<br />
* <code>module</code> – Module ID (as per [[#AttachmentObject | Attachment object]]) of the attached object.<br />
* <code>id</code> – Object ID of the requested attachment.<br />
<br />
Response with timestamp: An object containing all data of the requested attachment. The fields of the object are listed in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]]. <br />
<br />
=== Get an attachments filedata ===<br />
<br />
GET <code>/ajax/attachment/[filename]?action=document</code><br />
<br />
Parameters:<br />
<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>attached</code> – Object ID of the object to which the attachments are attached.<br />
* <code>module</code> – Module ID (as per [[#AttachmentObject | Attachment object]]) of the attached object.<br />
* <code>id</code> – Object ID of the requested attachment.<br />
* <code>content_type</code> (optional) – If set the responses Content-Type header is set to this value, not the attachements file mime type.<br />
<br />
Response body: The raw byte data of the document. The response type for the HTTP Request is set accordingly to the defined mimetype for this infoitem.<br />
Note: The Filename may be added to the customary infostore path to suggest a filename to a Save-As dialog.<br />
<br />
== Module "reminder" ==<br />
<br />
The reminder module provides the ability to fetch all active reminders for a user between two dates.<br />
<br />
=== Get reminder range ===<br />
<br />
GET <code>/ajax/reminder?action=range</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>end</code> – The End date of the reminder range<br />
<br />
Response: An Array with all reminders which are scheduled until the specified time. Each reminder is described in [[#ReminderResponse | Reminder response]].<br />
<br />
{| id="ReminderResponse" cellspacing="0" border="1"<br />
|+ align="bottom" | Reminder response<br />
! Field !! Type !! Description<br />
|-<br />
| id || Number || The ID of the reminder.<br />
|-<br />
| target_id || Number || The target_id where this reminder is attached to<br />
|-<br />
| alarm || Time || The time of the alarm<br />
|-<br />
| module || Number || The module of the reminder<br />
|-<br />
| servertime || Time || The time on the server<br />
|-<br />
| user_id || Number || The ID of the user.<br />
|-<br />
| last_modified || Time || The last modification timestamp of the reminder<br />
|-<br />
| recurrence_position || Number || The recurrence position for series appointments or 0 if no series<br />
|-<br />
| folder || Number || The ID of the folder through that the object can be read<br />
|-<br />
|}<br />
<br />
=== Delete a Reminder===<br />
<br />
PUT <code>/ajax/reminder?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An object with the field “id”.<br />
<br />
Response body: An JSON array with the id that was not deleted.<br />
<br />
=== Delete Reminders (since v6.22)===<br />
<br />
PUT <code>/ajax/reminder?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An array of objects with the field “id”.<br />
<br />
Response body: An JSON array with the ids that were not deleted.<br />
<br />
=== Remind again (since v6.18.1) ===<br />
<br />
PUT <code>/ajax/reminder?action=remindAgain</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the reminder whose date shall be changed.<br />
<br />
Request body: The JSON representation of the reminder; mainly containing the field “alarm” which provides the new reminder date.<br><br />
E.g. <code>{ "alarm": 1283418027381 }</code><br />
<br />
Response body: The JSON representation of the updated reminder.<br />
<br />
== Module "multiple" ==<br />
<br />
The multiple module allows to bundle multiple requests to most other modules in a single request. Not supported are:<br />
* modules login and multiple,<br />
* POST requests with a multipart encoding (uploads),<br />
* GET requests which do not use an object as described in [[#ResponseBody | Response body]] as response body (downloads).<br />
<br />
=== Multiple requests ===<br />
<br />
PUT <code>/ajax/multiple</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>continue</code> – Specifies whether processing of requests should stop when an error occurs, or whether all request should be processed regardless of errors.<br />
<br />
Request body: An array with request objects. Each request object contains all URI parameters of the "normal" request as fields. The module name of the "normal" request is included in the field module. The parameter session is not included. If the "normal" request has a request body, the object which is represented by that request body is includes as the value of the field data.<br />
<br />
Response: An array with reply objects as described in [[#ResponseBody | Response body]]. The order of reply objects corresponds to the order of requests in the request body. Unlike with all other modules, this response is itself not part of a response object as described in [[#ResponseBody | Response body]].<br />
<br />
== Module "quota" ==<br />
<br />
The filestore module allows accesssing information about the use and quota of the filestore.<br />
<br />
=== Get quota information (Since 7.6.1, Preliminary) ===<br />
<br />
GET <code>/ajax/quota?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>module</code> (optional) – The module identifier to get quota information for, required if <code>account</code> is set.<br />
* <code>account</code> (optional) – The account identifier within the module to get quota information for.<br />
<br />
Response: A JSON object containing the requested quota information. If no <code>module</code> was specified, all defined [[#ModuleQuota | module quotas]] are set in the JSON object, each one mapped to it's module identifier. If the quota from a <code>module</code> was requested, a JSON array containing all [[#AccountQuota | account quotas]] of this module are returned. If both a <code>module</code> and <code>account</code> were requested, a JSON object representing this specific [[#AccountQuota | account auota]] is returned. <br />
<br />
Note: In case there is no quota limitation defined for a module or account, no corresponding JSON object is included in the response. <br />
<br />
<br />
{| id="ModuleQuota" cellspacing="0" border="1"<br />
|+ align="bottom" | Module Quota<br />
! Field !! Type !! Description<br />
|-<br />
| display_name || String || The display name of the module<br />
|-<br />
| accounts|| Array || Each element identifies an account quota within the module, as described in [[#AccountQuota | Account Quota]]<br />
|-<br />
|}<br />
<br />
<br />
{| id="AccountQuota" cellspacing="0" border="1"<br />
|+ align="bottom" | Account Quota<br />
! Field !! Type !! Description<br />
|-<br />
| account_id || String || Identifier of the account<br />
|-<br />
| account_name || String || Name of the account<br />
|-<br />
| countquota || Number || The account's quota limit for the number of items, or not set if not defined<br />
|-<br />
| countuse || Number || The account's actual usage for the number of items, or not set if no count quota defined<br />
|-<br />
| quota || Number || The account's quota limit for the storage in bytes, or not set if not defined<br />
|-<br />
| use || Number || The account's actual usage for the storage in bytes, or not set if no storage quota defined<br />
|-<br />
|}<br />
<br />
<br />
=== Get the filestore usage data ===<br />
<br />
GET <code>/ajax/quota?action=filestore</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: A JSON Object containing the fields “use” and “quota”. “use” represents the uploaded files sizes sum and the field “quota” represents the maximum.<br />
<br />
=== Get the mail usage data ===<br />
<br />
GET <code>/ajax/quota?action=mail</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: A JSON Object containing the fields “use” and “quota”. “use” represents the use mail quota and the field “quota” represents the maximum. -1 represents an unlimited quota.<br />
<br />
== Module "import"==<br />
The module import allows to import specific module data (like Contacts, Tasks or Appointments) in several formats (iCal, vCard, CSV) into a folder. Please note: The callback for all actions of this bundle is callback_import, not callback_$actionname for legacy purposes.<br />
<br />
=== Import CSV ===<br />
POST <code>/ajax/import?action=CSV</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder into which data should be imported. This must be a Contact folder.<br />
* <code>charset</code> (preliminary, since 7.6.2) – Optional. A fixed character encoding to use when parsing the uploaded file, overriding the built-in defaults, following the conventions documented in RFC 2278.<br />
<br />
Request body: A "multipart/form-data" encoded .CSV file. The field name for the file is "file". The column titles of the table are those used within the OX, see column ''Displayed Name'' in [[#DetailedContactData]].<br />
<br />
Response: An array of JSON-Objects, one for each entry in the list, containing: The Object ID of the entry, the Object ID of the folder the data was written into, a timestamp of the modification (in case of error, of modification attempt) and an error in case the data could not be entered.<br />
<br />
=== Import Outlook CSV ===<br />
POST <code>/ajax/import?action=OUTLOOK_CSV</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder into which data should be imported. This must be a Contact folder.<br />
* <code>charset</code> (preliminary, since 7.6.2) – Optional. A fixed character encoding to use when parsing the uploaded file, overriding the built-in defaults, following the conventions documented in RFC 2278.<br />
<br />
Request body: An .CSV file with Windows' default encoding Windows-1252. The column titles of the table may be those used by the English, French or German version of Outlook.<br />
<br />
Response: An array of JSON-Objects, one for each entry in the list, containing: The Object ID of the entry, the Object ID of the folder the data was written into, a timestamp of the modification (in case of error, of modification attempt) and an error in case the data could not be entered.<br />
<br />
=== Import iCAL ===<br />
POST <code>/ajax/import?action=ICAL</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder into which data should be imported. This may be an Appointment or a Task folder. May even be a list containing both.<br />
* <code>suppressNotification</code> – This optional parameter can be used to disable the notifications for new appointments that are imported through the given iCal file. This help keeping the Inbox clean if a lot of appointments need to be imported. The value of this parameter does not matter because only for the existence of the parameter is checked.<br />
* <code>ignoreUIDs</code> – Optional. When set to "true", UIDs are partially ignored during import of tasks and appointments from iCal. Internally, each UID is replaced statically by a random one to preserve possibly existing relations between recurring appointments in the same iCal file, but at the same time to avoid collisions with already existing tasks and appointments.<br />
<br />
Request body: An iCalendar file.<br />
<br />
Response: An array of JSON-Objects, one for each entry in the list, containing: The Object ID of the entry, the Object ID of the folder the data was written into, a timestamp of the modification (in case of error, of modification attempt) and an error in case the data could not be entered, and warnings (under the key "warnings") containing an Array of objects with the warning data, containing all customary error fields.<br />
<br />
=== Import vCard ===<br />
POST <code>/ajax/import?action=VCARD</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder into which data should be imported. This must be a Contact folder.<br />
<br />
Request body: An vCard file, maybe of the formats: vCard 2.1, vCard 3.0 or vCalendar 1.0<br />
<br />
Response: An array of JSON-Objects, one for each entry in the list, containing: The Object ID of the entry, the Object ID of the folder the data was written into, a timestamp of the modification (in case of error, of modification attempt) and an error in case the data could not be entered.<br />
<br />
== Module "export" ==<br />
The module export allows to export specific module data (like Contacts, Tasks or Appointments) from a folder in several formats (iCal, vCard, CSV).<br />
<br />
=== Exporting CSV ===<br />
GET <code>/ajax/export?action=CSV</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder whose contents are to be exported. This must be a Contact folder.<br />
* <code>columns</code> – (optional) Columns to be imported from the given file, given as an array of column numbers. See [[#DetailedContactData | Detailed contact data]] for numbers.<br />
* <code>export_dlists</code> – (optional) toggles whether distribution lists are exported, too. Default is false. Option exists since 7.4.1.<br />
Response: An InputStream containing the file of the MIME type <code>text/csv</code>.<br />
<br />
=== Exporting iCAL ===<br />
GET <code>/ajax/export?action=ICAL</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder whose contents are to be exported. This must be a Calendar folder.<br />
<br />
Response: An InputStream containing the file, of the MIME type <code>text/calendar</code>.<br />
<br />
=== Exporting vCard ===<br />
GET <code>/ajax/export?action=VCARD</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder whose contents are to be exported. This must be a Contact folder.<br />
<br />
Response: An InputStream containing the file, of the MIME type <code>text/x-vcard</code>.<br />
<br />
== Module "sync" ==<br />
The module sync delivers several core API extensions to support common operations used in a mobile synchronization environment.<br />
<br />
=== Clearing a folder's content ===<br />
PUT <code>/ajax/sync?action=refresh_server</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON array containing the folder ID(s) whose content should be cleared. '''NOTE:''' Although the requests offers to clear multiple folders at once it is recommended to clear only one folder per request since if any exception occurs<br />
(e.g. missing permissions) the complete request is going to be aborted.<br />
<br />
Response: A JSON array containing the IDs of folders that could not be cleared due to a concurrent modification. Meaning you receive an empty JSON array if everything worked well.<br />
<br />
== Module "token" (since 7.4.0) ==<br />
The module token delivers several core API extensions to support token based logins.<br />
<br />
=== Get a login token ===<br />
GET <code>/ajax/token?action=acquireToken</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response:<br />
A JSON object with the timestamp of the creation date and a token which can be used to create a new session.<br />
<br />
== Module "mailfilter" ==<br />
The module mailfilter describes how to add, update or delete mail filter rules or to check which actions are supported by the underlying system.<br />
<br />
A detailed description can be found here [[ HTTP_API_MailFilter | Mail Filter HTTP API]]<br />
<br />
== Module "ajax file upload" ==<br />
This module offers to store files in server's dedicated download directory for a configureable amount of time. The files are then accessible for further operations like inline images in (html) mails<br />
<br />
=== Uploading a file ===<br />
POST <code>/ajax/file?action=new</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>module</code> – The module for which the file is uploaded to determine proper upload quota constraints (e.g. "mail", "infostore", etc.).<br />
* <code>type</code> – The file type filter to define which file types are allowed during upload. Currently supported filters are: <code>file=all, text=text/*, media=image OR audio OR video, image=image/*, audio=audio/*, video=video/*, application=application/*</code><br />
<br />
Request body: A common POST request body of MIME type "multipart/*" which holds the file(s) to upload<br />
<br />
Response: A JSON array containing the IDs of the uploaded files. The files are accessible through the returned IDs for future use.<br />
<br />
=== Updating a file's last access timestamp (keep alive) ===<br />
By updating the last access timestamp it's prevented from being deleted from both session and disk storage.<br />
<br />
GET <code>/ajax/file?action=keepalive</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the uploaded file whose timestamp should be updated<br />
<br />
Response: The string "null" in response's data element<br />
<br />
=== Requesting a formerly uploaded file ===<br />
GET <code>/ajax/file?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the uploaded file<br />
<br />
Response: The content of the requested file is directly written into output stream<br />
<br />
== Module "image" ==<br />
This module allows to download images from Open-Xchange server without providing a session ID in request's URL parameters.<br />
<br />
=== Requesting an image ===<br />
Open-Xchange Server supports multiple image sources that are identified through request's path identifier<br />
<br />
* Inline images from mails<br />
** Request path needs to be <code>"/mail/picture"</code><br><br><br />
* Contact profile image<br />
** Request path needs to be <code>"/contact/picture"</code><br><br><br />
* User profile image<br />
** Request path needs to be <code>"/user/picture"</code><br><br><br />
* MP3 cover image<br />
** Request path needs to be <code>"/file/mp3cover"</code><br><br><br />
* Fetch a previously uploaded image using <code>"/ajax/file"</code> interface<br />
** Request path needs to be <code>"/mfile/picture"</code><br><br><br />
<br />
Each image source requires an individual set of required parameters<br />
<br />
==== Inline images from mails ====<br />
GET <code>/mail/picture</code> <br />
<br />
Parameters:<br />
* <code>accountId</code> – The mail account identifier<br />
* <code>folder</code> – The identifier of the folder in which the mail resides<br />
* <code>id</code> – The mail identifier<br />
* <code>uid</code> – The identifier of the image inside the referenced mail<br />
<br />
Response: The content of the requested image is directly written into output stream<br />
<br />
<br />
==== Contact profile images ====<br />
GET <code>/contact/picture</code> <br />
<br />
Parameters:<br />
* <code>folder</code> – The identifier of the folder in which the contact resides<br />
* <code>id</code> – The contact identifier<br />
<br />
Response: The content of the requested image is directly written into output stream<br />
<br />
<br />
==== User profile images ====<br />
GET <code>/user/picture</code> <br />
<br />
Parameters:<br />
* <code>id</code> – The user identifier<br />
<br />
Response: The content of the requested image is directly written into output stream<br />
<br />
<br />
==== MP3 cover image ====<br />
GET <code>/file/mp3cover</code> <br />
<br />
Parameters:<br />
* <code>id</code> – The identifier of the uploaded image<br />
<br />
Response: The content of the requested image is directly written into output stream<br />
<br />
<br />
==== Managed Image File ====<br />
GET <code>/image/mfile/picture</code> <br />
<br />
Parameters:<br />
* <code>uid</code> – The identifier of the uploaded image<br />
<br />
Response: The content of the requested image is directly written into output stream<br />
<br />
== Module "conversion" (preliminary) ==<br />
<br />
A generic module to request data from a data source and to process obtained/submitted data with a data handler. Thus data is converted from a data source by a data handler.<br />
<br />
=== Converting data ===<br />
PUT <code>/ajax/conversion?action=convert</code><br><br />
or<br><br />
POST <code>/ajax/conversion?action=convert</code> <br />
<br />
Parameters: &lt;no parameters required&gt;<br />
<br />
Request body: A [[#ConversionRequest | conversion request]] JSON object containing nested JSON objects for [[#DataSource | data source]] and [[#DataHandler | data handler]]<br />
<br />
<br />
{| id="ConversionRequest" cellspacing="0" border="1"<br />
|+ align="bottom" | Conversion request object<br />
! Field !! Type !! Description<br />
|-<br />
| datasource || JSON object || The data source object.<br />
|-<br />
| datahandler || JSON object || The data handler object.<br />
|-<br />
|}<br />
<br />
<br />
{| id="DataSource" cellspacing="0" border="1"<br />
|+ align="bottom" | Data source object<br />
! Field !! Type !! Description<br />
|-<br />
| identifier || String || The identifier of the data source.<br />
|-<br />
| args || JSON array or JSON object || The '''optional''' name-value-pairs as a single JSON object or a JSON object for each kept inside a JSON array for data source<br />
|-<br />
|}<br />
<br />
<br />
{| id="DataHandler" cellspacing="0" border="1"<br />
|+ align="bottom" | Data handler object<br />
! Field !! Type !! Description<br />
|-<br />
| identifier || String || The identifier of the data handler.<br />
|-<br />
| args || JSON array or JSON object || The '''optional''' name-value-pairs as a single JSON object or a JSON object for each kept inside a JSON array for data handler<br />
|-<br />
|}<br />
<br />
Response: The result of converted data ready as an appropriate JSON response<br />
<br />
==== Saving an ICal email attachment ====<br />
<br />
If an ICal file is attached to an email, its content can be saved as appointments and tasks into given calendar and task folder.<br />
If the fields "com.openexchange.groupware.calendar.confirmstatus" and "com.openexchange.groupware.calendar.confirmmessage" are set, the data handler inserts the appointment with the given status for the user, if the appointment does not exist. If it is already existing, the handler just updates the participant status.<br />
<br />
Data source's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.mail.ical&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.fullname&quot;:&quot;&lt;folder-fullname&gt;&quot;},<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.mailid&quot;:&quot;&lt;mail-id&gt;&quot;},<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.sequenceid&quot;:&quot;&lt;attachment-sequence-id&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Data handler's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.ical&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.groupware.calendar.folder&quot;:&quot;&lt;calendar-folder-id&gt;&quot;},<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.task.folder&quot;:&quot;&lt;task-folder-id&gt;&quot;},<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.calendar.confirmstatus&quot;:&quot;&lt;status&gt;&quot;},<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.calendar.confirmmessage&quot;:&quot;&lt;message&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Response: A JSON array of JSON objects each providing folder and object ID of added appointment/task; e.g. <code>[{&quot;folder_id&quot;:2567, &quot;id&quot;:7689}, ...]</code><br />
<br />
==== Converting an ICal email attachment into JSON objects ====<br />
<br />
If an ICal file is attached to an email, its content can converted to JSON appointments and tasks.<br />
<br />
Data source's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.mail.ical&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.fullname&quot;:&quot;&lt;folder-fullname&gt;&quot;}<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.mailid&quot;:&quot;&lt;mail-id&gt;&quot;}<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.sequenceid&quot;:&quot;&lt;attachment-sequence-id&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Data handler's JSON object.<br><br />
'''Note''' that all arguments are optional: Default is user time zone and zero recurrence position<br><br />
"com.openexchange.groupware.calendar.searchobject" triggers a search for the uid, and replaces the object_id and folder_id with the data of the corresponding ox-object id, if existing. The returned objects are still the ical objects and NOT the ox-objects.<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.ical.json&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.groupware.calendar.timezone&quot;:&quot;&lt;timezone-id&gt;&quot;}<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.calendar.recurrencePosition&quot;:&quot;&lt;recurrence-position&gt;&quot;}<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.calendar.searchobject&quot;:&quot;&lt;true|false&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Response: A JSON array of JSON objects for each appointment/task as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]]/[[##DetailedAppointmentData | Detailed appointment data]]<br />
<br />
==== Saving a VCard email attachment ====<br />
<br />
If a VCard file is attached to an email, its content can be saved as contacts into given contact folder.<br />
<br />
Data source's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.mail.vcard&quot;,<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.fullname&quot;:&quot;&lt;folder-fullname&gt;&quot;},<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.mailid&quot;:&quot;&lt;mail-id&gt;&quot;},<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.sequenceid&quot;:&quot;&lt;attachment-sequence-id&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Data handler's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.contact&quot;,<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.groupware.contact.folder&quot;:&quot;&lt;contact-folder-id&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Response: A JSON array of JSON objects each providing folder and object ID of added contact; e.g. <code>[{&quot;folder_id&quot;:2567, &quot;id&quot;:7689}, ...]</code><br />
<br />
==== Contact(s) attached to a new email as a VCard file ====<br />
<br />
Obtain VCard data from specified contact object(s).<br />
<br />
Data source's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.contact&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;folder&quot;:&quot;&lt;folder-id1&gt;&quot;,&quot;id&quot;:&quot;&lt;id1&gt;&quot;}<br><br />
&nbsp;&nbsp;&nbsp;...<br><br />
&nbsp;&nbsp;&nbsp;{&quot;folder&quot;:&quot;&lt;folder-idn&gt;&quot;,&quot;id&quot;:&quot;&lt;idn&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Get a new email's JSON object with specified VCard data source attached.<br />
<br />
Data handler's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.mail.vcard&quot;<br><br />
&nbsp;&quot;args&quot;:[]<br><br />
}<br><br />
</code><br />
<br />
Response: A [[#DetailedMailData | mail]] JSON object.<br />
<br />
== Module "search" (preliminary) ==<br />
<br />
The search module is an enhancement to each search request as an optional JSON object via PUT method to filter elements; e.g.<br />
<br />
<code><br />
PUT /ajax/contacts?action=all&...<br />
<br />
{"filter":{search-term-object}}<br />
</code><br />
<br />
This section describes the syntax of the optional JSON object representing the search term.<br><br />
In general the structure of a search term is in prefix notation; meaning the operator is written before its operands:<br />
<br />
<code>{"operation":"equals","operands":[...]}</code><br />
<br />
Moreover there are two different types of a search terms:<br />
* A single search term<br />
* A composite search term<br />
<br />
A single search term reflects an operation which cannot hold nested search terms as operands; e.g. "equals". In opposite to this a composite search term holds one or more nested search terms as operands; e.g. "not" or the logical junctors "and"/"or".<br />
<br />
By now the following operations are supported:<br />
* composite operations<br />
** "and" - The AND junctor<br />
** "or" - The OR junctor<br />
** "not" - Negation<br />
* single operations<br />
** "equals" - Equals comparison<br />
** "lt" - Less-than comparison<br />
** "gt" - Greater-than comparison<br />
<br />
Furthermore following operand types are supported for single search terms:<br />
* Column - Providing a name referring to a field/column<br />
* Constant - A constant<br />
<br />
Example of an EQUALS search term:<br><br />
<code><br />
{"operation":"equals","operands":[{"type":"column","value":"first_name"},"Jane"]}<br />
</code><br />
<br />
Example of an OR search term:<br><br />
<code><br />
{"operation":"or","operands":<br><br />
&nbsp;[<br><br />
&nbsp;&nbsp;{"operation":"equals","operands":[{"type":"column","value":"first_name"},"Jane"]},<br><br />
&nbsp;&nbsp;{"operation":"gt","operands":[{"type":"column","value":"birthday"},"1975-05-01"]}<br><br />
&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
<br />
Refer to object data tables introduced by different modules to know which field names are supported; e.g. for tasks it is [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]], and [[#DetailedTaskData | Detailed task data]].<br />
<br />
== Module "search" (alternative suggestion, still preliminary) ==<br />
<br />
The search module is an enhancement to each search request as an optional JSON object via PUT method to filter elements; e.g.<br />
<br />
<code><br />
PUT /ajax/contacts?action=all&...<br />
<br />
{"filter":<i>[search term]</i>}<br />
</code><br />
<br />
This section describes the syntax of the optional JSON object representing the search term.<br />
In general the structure of a search term is in prefix notation; meaning the operator is written before its operands:<br />
<br />
<code>[">", 5, 2]</code><br />
<br />
The available operators are:<br />
* Comparison operators ">", "<", "=", "<=", ">=", "<>"<br />
* logic operators "not", "and", "or"<br />
<br />
Comparison operators have exactly two operands. Each operand can be either a field name or a constant. A field name is an object with the member "field" specifying the field name, e.g. <code>{ field: "first_name" }</code>. The available field names depend on the searched module. Primitive JSON types are interpreted as constants. Arrays are not valid operands for comparison operators.<br />
<br />
The logic operator "not" has exactly one operand, the other logic operators can have any number of operands. Each operand must be an array representing a nested search expression.<br />
<br />
== Module "mail account" (available with v6.12) ==<br />
<br />
The mail account module is used to manage multiple mail accounts held by a user.<br />
<br />
=== Get All mail accounts ===<br />
<br />
GET <code>/ajax/account?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for mail account's are defined in [[#MailAccountData | mail account data]].<br />
<br />
Response: An array with attachment data. Each array element describes one mail account and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a mail account ===<br />
<br />
GET <code>/ajax/account?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the account to return.<br />
<br />
Response: A JSON object representing the desired mail account. See [[#MailAccountData | mail account data]].<br />
<br />
{| id="MailAccountData" cellspacing="0" border="1"<br />
|+ align="bottom" | Mail account data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 1001 || id || Number || Account ID<br />
|-<br />
| 1002 || login || String || The login.<br />
|-<br />
| 1003 || password || String || The (optional) password.<br />
|-<br />
| 1004 || mail_url || String || The mail server URL; e.g. "imap://imap.somewhere.com:143". '''URL is preferred over single fields''' (like mail_server, mail_port, etc.)<br />
|-<br />
| 1005 || transport_url || String || The transport server URL; e.g. "smtp://smtp.somewhere.com:25". '''URL is preferred over single fields''' (like transport_server, transport_port, etc.)<br />
|-<br />
| 1006 || name || String || Account's display name.<br />
|-<br />
| 1007 || primary_address || String || User's primary address in account; e.g. "someone@somewhere.com"<br />
|-<br />
| 1008 || spam_handler || String || The name of the spam handler used by account.<br />
|-<br />
| 1009 || trash || String || The name of the default trash folder.<br />
|-<br />
| 1010 || sent || String || The name of the default sent folder.<br />
|-<br />
| 1011 || drafts || String || The name of the default drafts folder.<br />
|-<br />
| 1012 || spam || String || The name of the default spam folder.<br />
|-<br />
| 1013 || confirmed_spam || String || The name of the default confirmed-spam folder.<br />
|-<br />
| 1014 || confirmed_ham || String || The name of the default confirmed-ham folder.<br />
|-<br />
| 1015 || mail_server || String || The mail server's hostname or IP address.<br />
|-<br />
| 1016 || mail_port || Number || The mail server's port.<br />
|-<br />
| 1017 || mail_protocol || String || The mail server's protocol. '''Always use basic protocol name.''' E.g. use "imap" instead of "imaps"<br />
|-<br />
| 1018 || mail_secure || Boolean || Whether to establish a secure connection to mail server (SSL, TLS).<br />
|-<br />
| 1019 || transport_server || String || The transport server's hostname or IP address.<br />
|-<br />
| 1020 || transport_port || Number || The transport server's port.<br />
|-<br />
| 1021 || transport_protocol || String || The transport server's protocol. '''Always use basic protocol name.''' E.g. use "smtp" instead of "smtps"<br />
|-<br />
| 1022 || transport_secure || Boolean || Whether to establish a secure connection to transport server (SSL, TLS).<br />
|-<br />
| 1023 || transport_login || String || The transport login. '''Please see "transport_auth" for the handling of this field.'''<br />
|-<br />
| 1024 || transport_password || String || The transport password. '''Please see "transport_auth" for the handling of this field.'''<br />
|-<br />
| 1025 || unified_inbox_enabled || Boolean || If enabled for Unified INBOX<br />
|-<br />
| 1026 || trash_fullname || String || Path to default trash folder. Preferred over "trash"<br />
|-<br />
| 1027 || sent_fullname || String || Path to default sent folder. Preferred over "sent"<br />
|-<br />
| 1028 || drafts_fullname || String || Path to default drafts folder. Preferred over "drafts"<br />
|-<br />
| 1029 || spam_fullname || String || Path to default spam folder. Preferred over "spam"<br />
|-<br />
| 1030 || confirmed_spam_fullname || String || Path to default confirmed-spam folder. Preferred over "confirmed_spam"<br />
|-<br />
| 1031 || confirmed_ham_fullname || String || Path to default confirmed-ham folder. Preferred over "confirmed_ham"<br />
|-<br />
| 1032 || pop3_refresh_rate || Number || The interval in minutes the POP3 account is refreshed<br />
|-<br />
| 1033 || pop3_expunge_on_quit || Boolean || Whether POP3 messages shall be deleted on actual POP3 account after retrieval or not<br />
|-<br />
| 1034 || pop3_delete_write_through || Boolean || If option "pop3_expunge_on_quit" is disabled, this property defines whether a delete in local INBOX also deletes affected message in actual POP3 account<br />
|-<br />
| 1035 || pop3_storage || String || The name of POP3 storage provider, default is "mailaccount"<br />
|-<br />
| 1036 || pop3_path || String || Path to POP3's virtual root folder in storage, default is name of the POP3 account beside default folders<br />
|-<br />
| 1037 || personal || String || The customizable personal part of email address<br />
|-<br />
| 1038 || reply_to || String || The customizable reply-to email address<br />
|-<br />
| 1039 || addresses || String || The comma-separated list of available E-Mail addresses including aliases. !! Only available for primary mail account !!<br />
|-<br />
| 1040 || meta || JSON data || Stores arbitrary JSON data as specified by client associated with the mail account<br />
|-<br />
| 1041 || archive || String || The name of the archive folder. Currently not functional!<br />
|-<br />
| 1042 || archive_fullname || String || The full name of the archive folder. Currently not functional!<br />
|-<br />
| 1043 || transport_auth || String || '''Available since v7.6.1''' Specifies the source for mail transport (SMTP) credentials. Possible values: "mail", "custom", and "none".<br>- "mail" signals to use the same credentials as given in associated mail store (IMAP, POP3).<br>- "custom" signals that individual credentials are supposed to be used (fields "transport_login" and "transport_password" are considered).<br>- "none" means the mail transport does not support any authentication mechanism (rare case!)<br />
|}<br />
<br />
=== Create a new mail account ===<br />
<br />
PUT <code>/ajax/account?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request: A JSON object describing the new account to create. See [[#MailAccountData | mail account data]].<br />
<br />
Response: A JSON object representing the inserted mail account. See [[#MailAccountData | mail account data]].<br />
<br />
=== Update a mail account ===<br />
<br />
PUT <code>/ajax/account?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request: A JSON object identifiying (field ID is present) and describing the account to update. See [[#MailAccountData | mail account data]].<br />
<br />
Response: A JSON object representing the updated mail account. See [[#MailAccountData | mail account data]].<br />
<br />
=== Delete a mail account ===<br />
<br />
PUT <code>/ajax/account?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An array with the ID of the mail account to delete.<br />
<br />
=== Validate a mail account (which shall be created) ===<br />
<br />
PUT <code>/ajax/account?action=validate</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>tree</code> - An optional boolean parameter which indicates whether on successful validation the folder tree shall be returned (NULL on failure) or if set to "false" or missing only a boolean is returned which indicates validation result<br />
<br />
Request: A JSON object describing the new account to validate. See [[#MailAccountData | mail account data]].<br />
<br />
Response: Dependent on optional "tree" parameter a JSON folder object or a boolean value indicating the validation result<br />
<br />
The JSON folder object corresponding to [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
Additionally a field "subfolder_array" is added which contains possible subfolders. This field is missing if a folder contains no subfolders.<br />
<br />
[[Category: OX6]]<br />
<br />
== Module Auto Configuration (since 6.22) ==<br />
<br />
=== Get Auto Configuration ===<br />
<br />
GET <code>/ajax/autoconfig?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>email</code> – Email Adress for which a mail configuration will be discovered.<br />
* <code>password</code> – Corresponding password for the mail account (optional)<br />
<br />
Response: A JSON Object containing the best available settings for an appropriate mail Server for the given email address. The fields are described in [[#MailAccountData | mail account data]]. The Data may be incomplete or even empty.<br />
<br />
== Module "user" (available with v6.14) ==<br />
<br />
The user module is used to access user information.<br />
<br />
=== Get all users ===<br />
<br />
GET <code>/ajax/user?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for users are defined in [[#CommonObjectData | Common object data]], [[#DetailedContactData | Detailed contact data]] and [[#DetailedUserData | Detailed user data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response with timestamp: An array with user data. Each array element describes one user and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedUserData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed user data<br />
! ID !! Displayed name !! Name !! Type !! Value<br />
|-<br />
| 610 || Aliases || aliases || Array || The user's aliases<br />
|-<br />
| 611 || Time zone || timezone || String || The time zone ID.<br />
|-<br />
| 612 || Locale || locale || String || The name of user's entire locale, with the language, country and variant separated by underbars. E.g. "en", "de_DE"<br />
|-<br />
| 613 || Groups || groups || Array || The IDs of user's groups<br />
|-<br />
| 614 || Contact ID || contact_id || Number || The contact ID of the user<br />
|-<br />
| 615 || Login info || login_info || String || The user's login information<br />
|-<br />
| 616 || Guest Created By || guest_created_by || Number || The ID of the user who has created this guest in case this user represents a guest user; it is 0 for regular users (preliminary, available with v7.8.0)<br />
|}<br />
<br />
=== Get a list of users ===<br />
<br />
PUT <code>/ajax/user?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for users are defined in [[#CommonObjectData | Common object data]], [[#DetailedContactData | Detailed contact data]] and [[#DetailedUserData | Detailed user data]].<br />
<br />
Request body: An array of numbers. Each number is the ID of requested user. Since v6.18.1, a <code>null</code> value in the array is interpreted as the currently logged in user.<br />
<br />
Response with timestamp: An array with user data. Each array element describes one user and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a user ===<br />
<br />
GET <code>/ajax/user?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested user. Since v6.18.1, this parameter is optional: the default is the currently logged in user.<br />
<br />
Response with timestamp: An object containing all data of the requested user. The fields of the object are listed in [[#CommonObjectData | Common object data]], [[#DetailedContactData | Detailed contact data]] and [[#DetailedUserData | Detailed user data]].<br />
<br />
=== Update a user ===<br />
<br />
PUT <code>/ajax/user?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated user.<br />
* <code>timestamp</code> – Timestamp of the updated user. If the user was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: User object as described in [[#CommonObjectData | Common object data]], [[#DetailedContactData | Detailed contact data]] and [[#DetailedUserData | Detailed user data]]. Only modified fields are present.<br />
<br />
'''Note''': "timezone" and "locale" are the only fields from [[#DetailedUserData | Detailed user data]] which are allowed to be updated.<br />
<br />
Response with timestamp: An empty object.<br />
<br />
=== Search users ===<br />
<br />
PUT <code>/ajax/user?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified. In case of use of column 609 (use count depending order for collected users with global address book) the parameter "order" ist NOT necessary and will be ignored.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Request body: An Object as described in [[#SearchUsers | Search users]].<br />
<br />
{| id="SearchUsers" cellspacing="0" border="1"<br />
|+ align="bottom" | Search users<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find users. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|-<br />
| startletter || String || Search users with the given startletter. If this field is present, the pattern is matched against the user field which is specified by the property contact_first_letter_field on the server (default: last name). Otherwise, the pattern is matched against the display name.<br />
|}<br />
<br />
Alternative request body: An Object as described in [[#SearchUsersAlternative | Search users alternative]].<br />
<br />
{| id="SearchUsersAlternative" cellspacing="0" border="1"<br />
|+ align="bottom" | Search users alternative<br />
! Name !! Type !! Value<br />
|-<br />
| last_name || String || Searches users where the last name match with the given last name.<br />
|-<br />
| first_name || String || Searches users where the first name match with the given first name.<br />
|-<br />
| display_name || String || Searches users where the display name match with the given display name.<br />
|-<br />
| orSearch || Boolean || If set to true, the fields are connected through an OR search habit.<br />
|-<br />
| emailAutoComplete || Boolean || If set to true, results are guaranteed to contain at least one email adress and the search is performed by connecting the relevant fields through an OR search habit.<br />
|}<br />
<br />
Response: An array with user data. Each array element describes one user and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get user attribute (available with v6.20) ===<br />
<br />
GET <code>/ajax/user?action=getAttribute</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – ID of the user. <br />
* <code>name</code> – The attribute name. <br />
<br />
Response without timestamp: A JSON object providing name and value of the requested attribute<br />
<pre><br />
{ "name":"somename", "value":"somevalue"}<br />
</pre><br />
<br />
=== Set user attribute (available with v6.20) ===<br />
<br />
PUT <code>/ajax/user?action=setAttribute</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – ID of the user. <br />
* <code>setIfAbsent</code> - Set to "true" to put the value only if the specified name is not already associated with a value, otherwise "false" to put value in any case<br />
<br />
Request body: A JSON object providing name and value of the attribute. If the <code>"value"</code> field id missing or NULL, the attribute is removed.<br />
<pre><br />
{ "name":"somename", "value":"somevalue"}<br />
</pre><br />
<br />
Response: The boolean value "true" if PUT was successful; otherwise "false"<br />
<br />
== Module "user/me" (available with v7.6.2) ==<br />
<br />
The user/me module is used to access formal information about current user.<br />
<br />
=== Get user information ===<br />
<br />
GET <code>/ajax/user/me</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response with timestamp: A JSON object providing information for current user<br />
<br />
<code><br />
{<br />
"data": {<br />
"context_id": 1234,<br />
"user_id": 5,<br />
"is_context_admin": false,<br />
"login_name": "user5",<br />
"display_name": "User Five"<br />
},<br />
"timestamp": 1400855683800<br />
}<br />
</code><br />
<br />
== Module "OAuth" (available with v6.20) ==<br />
<br />
The OAuth module is used to manage multiple OAuth accounts for certian online services for a user. The OAuth mechanism allows the Open-Xchange application to act as behalf of this user using previously obtained access tokens granted by user.<br />
<br />
The OAuth interface is divided into two parts: Account access and service's meta data access.<br />
<br />
=== OAuth account access ===<br />
<br />
The OAuth service account access description.<br />
<br />
<br />
==== Get all OAuth accounts ====<br />
<br />
GET <code>/ajax/oauth/accounts?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – The <b>optional</b> service meta data identifier. If missing all accounts of all services are returned; otherwise all accounts of specified service are returned<br />
<br />
Response: An array with account data. Each array element is a JSON object describing an OAuth account as specified in [[#OAuthAccountData | OAuth account data]].<br />
<br />
==== Get an OAuth account ====<br />
<br />
GET <code>/ajax/oauth/accounts?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The account identifier.<br />
<br />
Response: A JSON object describing an OAuth account as specified in [[#OAuthAccountData | OAuth account data]].<br />
<br />
{| id="OAuthAccountData" cellspacing="0" border="1"<br />
|+ align="bottom" | OAuth account<br />
! Field !! Type !! Description<br />
|-<br />
| id || Number || The numeric identifier of the OAuth account.<br />
|-<br />
| displayName || String || The account display name<br />
|-<br />
| serviceId || String || The identifier of the associated service meta data; e.g. <code>"com.openexchange.oauth.twitter"</code><br />
|-<br />
| token || String || The token<br />
|-<br />
| secret || String || The token secret<br />
|-<br />
|}<br />
<br />
==== Delete an OAuth account ====<br />
<br />
PUT <code>/ajax/oauth/accounts?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The account identifier.<br />
<br />
Response: The boolean value "true" if successful<br />
<br />
==== Update an OAuth account ====<br />
<br />
PUT <code>/ajax/oauth/accounts?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The account identifier. May also be provided in request body's JSON OAuth account representation by <code>"id"</code> field.<br />
<br />
Request body: A JSON object providing the OAuth account fields to update. See [[#OauthAccountData | OAuth account data]]. Currently the only values which make sende being updated are <code>"displayName"</code> and the <code>"token"</code>-<code>"secret"</code>-pair.<br />
<br />
Response: The boolean value "true" if successful<br />
<br />
==== Initialize creation of an OAuth account ====<br />
<br />
GET <code>/ajax/oauth/accounts?action=init</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – The service meta data identifier; e.g. <code>"com.openexchange.oauth.twitter"</code><br />
<br />
Response: An JSON representation of the resulting interaction providing needed information to complete account creation. See [[#OauthInteractionData | OAuth interaction data]].<br />
<br />
{| id="OauthInteractionData" cellspacing="0" border="1"<br />
|+ align="bottom" | OAuth interaction<br />
! Field !! Type !! Description<br />
|-<br />
| authUrl || String || The numeric identifier of the OAuth account.<br />
|-<br />
| type || String || The interaction type name; <code>"outOfBand"</code> or <code>"callback"</code><br />
|-<br />
| token || String || The token<br />
|-<br />
| uuid || String || The UUID for this OAuth interaction<br />
|-<br />
|}<br />
<br />
==== Create an OAuth account ====<br />
<br />
Note: This action is typically called by provided call-back URL and is ony intended for manual invocation if "outOfBand" interaction is returned by preceeding <code>/ajax/oauth/account?action=init</code> step.<br />
<br />
PUT <code>/ajax/oauth/accounts?action=create</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module<br />
* <code>oauth_token</code> – The request token from preceeding OAuth interaction<br />
* <code>uuid</code> – The UUID of the preceeding OAuth interaction<br />
* <code>oauth_verfifier</code> – The verifier string which confirms that user granted access<br />
* <code>displayName</code> – The display name for the new account<br />
<br />
Response: A JSON object describing the newly created OAuth account as specified in [[#OAuthAccountData | OAuth account data]].<br />
<br />
=== OAuth service meta data access ===<br />
<br />
The OAuth service meta data access description.<br />
<br />
<br />
==== Get all OAuth services' meta data ====<br />
<br />
GET <code>/ajax/oauth/services?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: An array with service data. Each array element is a JSON object describing an OAuth service's meta data as specified in [[#OAuthServiceMetaData | OAuth service meta data]].<br />
<br />
==== Get an OAuth service's meta data ====<br />
<br />
GET <code>/ajax/oauth/services?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The service's identifier.<br />
<br />
Response: A JSON object describing an OAuth service's meta data as specified in [[#OAuthServiceMetaData | OAuth service meta data]].<br />
<br />
{| id="OAuthServiceMetaData" cellspacing="0" border="1"<br />
|+ align="bottom" | OAuth service meta data<br />
! Field !! Type !! Description<br />
|-<br />
| id || Number || The numeric identifier of the OAuth account.<br />
|-<br />
| displayName || String || The account display name<br />
|-<br />
|}<br />
<br />
== Module "JSlob" (available with v6.22) ==<br />
<br />
The JSlob module is used to store&retrieve arbitrary JSON-structured configuration for a single user.<br />
<br />
<br />
=== Get all JSLobs ===<br />
<br />
GET <code>/ajax/jslob?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
<br />
<br />
Response: An array with JSON configurations. Each array element is a JSON object representing a certain configuration consisting if a "id" and "jslob" field. See [[#JSlobData | JSlob data ]]<br />
<br />
{| id="JSlobData" cellspacing="0" border="1"<br />
|+ align="bottom" | JSlob data<br />
! Field !! Type !! Description<br />
|-<br />
| id || String or Number || The identifier of the JSlob.<br />
|-<br />
| jslob || JSON object || The JSON configuration.<br />
|-<br />
|}<br />
<br />
=== List denoted JSLobs ===<br />
<br />
PUT <code>/ajax/jslob?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
<br />
<br />
Request body: A JSON array of JSlob identifiers; e.g. <code>[ "1", "2", … ]</code><br />
<br />
Response: An array with JSON configurations. Each array element is a JSON object representing a certain configuration consisting if a "id" and "jslob" field. See [[#JSlobData | JSlob data ]]<br />
<br />
=== Delete a JSlob ===<br />
<br />
PUT <code>/ajax/jslob?action=set</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
* <code>id</code> – The JSlob identifier.<br />
<br />
<br />
Request body: An empty request body<br />
<br />
Response: Nothing<br />
<br />
=== Store a JSlob ===<br />
<br />
PUT <code>/ajax/jslob?action=set</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
* <code>id</code> – The identifier for the new JSlob to create<br />
<br />
<br />
Request body: A JSON object containing the "path" and "value" of the JSON configuration to store. If "path" is missing the current configuration<br />
is merged with given JSON object.<br />
<br />
Response: Nothing<br />
<br />
=== Update a single value inside a JSlob ===<br />
<br />
PUT <code>/ajax/jslob?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
* <code>id</code> – The identifier for the new JSlob to create<br />
<br />
<br />
Request body: The new value to store inside specified JSlob<br />
<br />
Response: A JSlob representation according to [[#JSlobData | JSlob data ]]<br />
<br />
=== REST-like access to JSlob module ===<br />
<br />
to be done...<br />
<br />
<br />
== Module "freebusy" (available with v6.22.1) ==<br />
<br />
Provides access to free/busy information.<br />
<br />
<br />
=== Get free/busy information ===<br />
<br />
GET <code>/ajax/freebusy?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>participant</code> – The participant to get the free/busy data for. May be either an internal user-, group- or resource-ID, or an e-mail address for external participants.<br />
* <code>from</code> – The lower (inclusive) limit of the requested time-range.<br />
* <code>until</code> – The upper (exclusive) limit of the requested time-range.<br />
* <code>merged</code> (optional) – True or False. Whether to pre-process the free/busy data on the server or not. This includes sorting as well as merging overlapping free/busy intervals.<br />
<br />
Response: An array of free/busy intervals as described in [[#FreeBusyInterval | Free/Busy interval]]<br />
<br />
{| id="FreeBusyInterval" cellspacing="0" border="1"<br />
|+ align="bottom" | Free/Busy interval<br />
! Name !! Type !! Value<br />
|-<br />
| start_date || Time || Start time of the interval.<br />
|-<br />
| end_date || Time || End time of the interval.<br />
|-<br />
| shown_as || Number || The busy status of this interval, one of:<br />
{| cellspacing="0" border="1"<br />
| 1 || unknown<br />
|-<br />
| 1 || reserved<br />
|-<br />
| 2 || temporary<br />
|-<br />
| 3 || absent<br />
|-<br />
| 4 || free<br />
|}<br />
|-<br />
| id || String || Object ID of the corresponding appointment if available.<br />
|-<br />
| folder_id || String || Folder ID of the corresponding appointment if available.<br />
|-<br />
| title || String || Title of the corresponding appointment if available.<br />
|-<br />
| location || String || Location of the corresponding appointment if available.<br />
|-<br />
| full_time || Boolean || True if the corresponding appointment is a whole day appointment, not present otherwise.<br />
|}<br />
<br />
<br />
=== Get a list of free/busy information ===<br />
<br />
PUT <code>/ajax/freebusy?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>from</code> – The lower (inclusive) limit of the requested time-range.<br />
* <code>until</code> – The upper (exclusive) limit of the requested time-range.<br />
* <code>merged</code> (optional) – True or False. Whether to pre-process the free/busy data on the server or not. This includes sorting as well as merging overlapping free/busy intervals.<br />
<br />
Request body: An array of participants to get the free/busy data for. Each participant may be either an internal user-, group- or resource-ID, or an e-mail address for external participants.<br />
<br />
Response: The free/busy data for all requested participants inside a JSON object with the participants as keys. Besides a combined data element for a requested group, all group members are resolved and listed seperately in the result. If the 'merged' view was requested, an additional data element named 'merged' representing a combined view for all requested participants is added to the results implicitly.<br />
<br />
<br />
== Messaging Services ==<br />
<br />
Messaging Services represent a messaging backend. The messaging services add a new folder module "messaging". <br />
<br />
A *Messaging Service* Object has the following structure:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Messaging Service<br />
! Field !! Type !! Description<br />
|-<br />
| id || String || Identifies a messagingService. Usually a String in reverse domain name notation. Example: "com.openexchange.messaging.twitter"<br />
|-<br />
| displayName || String || Human readable display name of the service. Example: "Twitter" <br />
|-<br />
| formDescription || Array || A description for dynamic form fields. Same as in PubSub <br />
|-<br />
| messagingActions || Array || An array of Strings a dynamic set of actions that are possible with messages of this service. Described in detail later on. <br />
|-<br />
|}<br />
<br />
The available JSON calls are:<br />
<br />
GET /ajax/messaging/service?action=all<br />
<br />
* session - A session ID previously obtained from the login module. <br />
<br />
Response: A standard response object containing an array of messaging service objects. <br />
<br />
<br />
GET /ajax/messaging/service?action=get<br />
<br />
* session - A session ID previously obtained from the login module. <br />
* id - The ID of the messaging service to load<br />
<br />
Response: A standard response object containing a messaging service object.<br />
<br />
== Messaging Accounts ==<br />
<br />
A messaging account represents the concrete configuration of an account of a given messaging service.<br />
A *messaging account* has the following structure:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Messaging Account<br />
! Field !! Type !! Description<br />
|-<br />
| id || Number || Identifies a given messaging account. This is not writeable and is generated by the server <br />
|-<br />
| messagingService || String || The messaging service id of the messaging service this account belongs to <br />
|-<br />
| displayName || String || User chosen String to identify a given account. Will also be translated into the folder name of the folder representing the accounts content <br />
|-<br />
| configuration || Object || Configuration data according to the formDescription of the relevant messagingService <br />
|-<br />
|}<br />
<br />
The available JSON calls are:<br />
<br />
PUT /ajax/messaging/account?action=new<br />
<br />
* session - A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON Object describing the account to be created.<br />
Response: A response object containing the new account id as its data.<br />
<br />
<br />
PUT /ajax/messaging/account?action=update<br />
<br />
* session - A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON Object describing the update to the account. Note that the "id" and "messagingService" must always be set.<br />
Response: A response object containing the number 1 as its data on success.<br />
<br />
GET /ajax/messaging/account?action=get<br />
<br />
* session - A session ID previously obtained from the login module.<br />
* messagingService - The messaging service id that the account belongs to<br />
* id - An account ID to load<br />
<br />
Response: A response object containing the JSON Object representing the loaded account as its data.<br />
<br />
GET /ajax/messaging/account?action=delete<br />
<br />
* session - A session ID previously obtained from the login module.<br />
* messagingService - The messaging service id that the account belongs to<br />
* id - An account ID to delete<br />
<br />
Response: A response object containing 1 as its data on success.<br />
<br />
GET /ajax/messaging/account?action=all<br />
<br />
* session - A session ID previously obtained from the login module<br />
* messagingService - (optional) list only those accounts that belong to the given messagingService.<br />
<br />
Response: A response object containing a JSON array of account objects in its data section.<br />
<br />
<br />
== Messaging Messages ==<br />
<br />
A Messaging Message represents a single message. It consists of some metadata, headers and a content. The content attribute varies by the content-type header. <br />
If the content type is text/* it is a string, if it is a multipart/* it is an array of objects, each representing a part of the multipart. If it is anything else<br />
it is considered binary and is a Base64 encoded string (ToDo : This is not smart enough yet. I suppose we'll have to include encoding options for binaries much like in our EAVJSONProposal).<br />
<br />
The folder id of a message follows a predefined format:<br />
<br />
<pre><br />
[messagingService]://[accountId]/[path]<br />
</pre><br />
<br />
for an imaginary example consider: "com.openexchange.messaging.twitter://535/defaultTimeline/directMessages"<br />
<br />
The structure of a Messaging Message is as follows:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Messaging Message<br />
! Field !! Type !! Description<br />
|-<br />
|id ||String || The id of this message. Only unique in the given folder. <br />
|-<br />
|folder ||String || The folder id. <br />
|-<br />
|threadLevel ||Number || The nesting level of this message according to the conversation it's belonged to. May not be set. <br />
|-<br />
|flags ||Number || Bitmask showing the state of this message. The same as in the module "mail". <br />
|-<br />
|receivedDate ||Time || The time this message was received. <br />
|-<br />
|colorLabel ||Number || An arbitrary number marking this message in a certain color. The same as the colorLabel common to all groupware objects (see HTTP API)<br />
|-<br />
|user ||Array || An array of strings. Represents user flags. <br />
|-<br />
|size ||Number || The binary size of this message in bytes. <br />
|-<br />
|picture || String || A string depicting the URL to a picture for this message <br />
|-<br />
|url || String || A string that contains a link to the messages origin. Currently used in RSS messages.<br />
|-<br />
|headers ||JSONObject || A JSON Object of header data. Usually the value is either a String or an Array (if the headers has more than one value). Certain headers are rendered as more complex structures, see the section "Complex Headers". <br />
|-<br />
|content ||String or Array || See introductory note for Messaging Messages. <br />
|-<br />
|}<br />
<br />
The structure of a Multipart Part (an element of the content array in a multipart/* message) is a s follows:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Multipart Element<br />
! Field !! Type !! Description<br />
|-<br />
|sectionId || String || The sectionId of this part.<br />
|-<br />
|headers || JSONObject || Same as above. <br />
|-<br />
|content || String or Array || Same as above. <br />
|-<br />
|}<br />
<br />
Some *Complex Headers* have a structure differing from simple key/value(s) pairs. These are:<br />
<br />
=== Content-Type ===<br />
<br />
The Content-Type header is represented as a JSON Object with the following structure:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Content Type Header<br />
! Field !! Type !! Description<br />
|-<br />
| type || String || The type string (eg. text/plain). This governs the rendering of the content of a message. <br />
|-<br />
| params || Object || An Object with the keys "charset", containing the charset of this message and "name" pointing to the filename this part or message should have. <br />
|-<br />
|}<br />
<br />
When setting the content-type header in a messaging messages generated on the client the header may also be sent in it's short form. The short form is the type followed by a semi-colon separated list of key=value pairs<br />
of the params. For example: "text/plain;charset=utf-8;name=something.txt".<br />
<br />
=== Address Headers ===<br />
<br />
Address headers ( From, To,Cc,Bcc,Reply-To,Resent-Reply-To,Disposition-Notification-To,Resent-To,Sender,Resent-Sender,Resent-To,Resent-Cc,Resent-Bcc ) are formatted as an array of objects, or in case of "From" as a single object, with the attributes *address* and *personal*:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Address Headers<br />
! Field !! Type !! Description<br />
|-<br />
| address || String || The technical part of the address<br />
|-<br />
| personal || String || A displayable description of the addressee. May be unset.<br />
|-<br />
|}<br />
<br />
When setting an address header the header may also be sent by clients in the short form <code>"personal &lt;address&gt;"</code>, for example <code>"Clark Kent &lt;clark.kent@dailyplanet.com&gt;"</code>. <br />
<br />
=== List renderings of Messaging Messages ===<br />
<br />
Actions returning lists of messages usually return only a selection of attributes of a message driven by a "columns" parameter. The columns that are addressable point either to attributes of the top-level message or its headers. <br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Header Equivalence<br />
! Column !! Refers To<br />
|-<br />
| *column* | *refers to* <br />
|-<br />
| id || The id attribute <br />
|-<br />
| folderId || The folder attribute <br />
|-<br />
| contentType || The "Content-Type" header <br />
|-<br />
| from || The "From" header <br />
|-<br />
| to || The "To" header <br />
|-<br />
| cc || The "Cc" header <br />
|-<br />
| bcc || The "Bcc" header <br />
|-<br />
| subject || The "Subject" header <br />
|-<br />
| size || The size attribute <br />
|-<br />
| sentDate || The "Date" header <br />
|-<br />
| receivedDate || The receivedDate attribute <br />
|-<br />
| flags || The flags attribute <br />
|-<br />
| threadLevel || The threadLevel attribute <br />
|-<br />
| dispositionNotificationTo || The "Disposition-Notification-To" header. <br />
|-<br />
| priority || The "X-Priority" header <br />
|-<br />
| colorLabel || The colorLabel attribute <br />
|-<br />
| url || The url attribute <br />
|-<br />
| body || The content attribute <br />
|-<br />
| headers || The headers attribute <br />
|-<br />
|}<br />
<br />
=== JSON calls ===<br />
<br />
GET /ajax/messaging/message?action=get<br />
<br />
* session - A session ID previously obtained from the login module<br />
* id - The ID of the message to load<br />
* peek - (optional) if set to "true" the read/unread state of the message will not change. Defaults to false.<br />
* folder - The folder id<br />
<br />
Response: An Object representing the loaded message.<br />
<br />
PUT /ajax/messaging/message?action=send<br />
<br />
* session - A session ID previously obtained from the login module<br />
* recipients - (optional) If set the message is sent to the given list of recipients, otherwise this defaults to the "To" header of the message.<br />
<br />
Request Body: The Request Body should contain the JSON Object representing the message to be sent.<br />
Response: "1" as the data of a regular response on success.<br />
<br />
GET or PUT /ajax/messaging/message?action=perform<br />
<br />
* session - A session ID previously obtained from the login module<br />
* action - The messaging action to invoke<br />
* id - The id of the message the action should be invoked on. Only used on actions of type "storage".<br />
* folder - The folder id.<br />
<br />
Request Body: On actions of type "message" the body should contain the JSON representation of the message the action should be applied to.<br />
Response: Either 1 if no further user interaction is needed or a messaging message that, after having the user modify it has to be supplied back to the follower action of this action.<br />
<br />
Thus, to invoke a messaging action of type "storage" the folder and id are needed. Messaging actions of type "message" need a folder and message in the body. <br />
Messaging actions of type "none" need a messaging message and account. <br />
<br />
==== List style requests ====<br />
<br />
GET /ajax/messaging/message?action=all<br />
<br />
* session - A session ID previously obtained from the login module<br />
* columns - A comma-separated list of column names.<br />
* sort - (optional) A column to sort by.<br />
* order - (optional) The order direction. "asc" for ascending or "desc" for descending. Defaults to "asc"<br />
* folder - The folder id.<br />
<br />
Response: An array of arrays with the sub arrays containing the values of the fields asked for by the the columns parameter.<br />
<br />
<br />
PUT /ajax/messaging/messages?action=list<br />
<br />
* session - A session ID previously obtained from the login module<br />
* columns - A comma-separated list of column names.<br />
<br />
Request Body: An array of arrays with the folder and id as elements each identifying a message. <br />
<br />
Response: An array of arrays with the sub arrays containing the values of the fields asked for by the columns parameter.<br />
<br />
== Snippet module (available with v7.0.0/v6.22.0) ==<br />
<br />
=== Gets a certain snippet by identifier ===<br />
<br />
GET /ajax/snippet?action=get<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
<br />
Response:<br />
The snippet's JSON representation; e.g.<br />
<br />
{<br />
"id": "1",<br />
"type": "signature",<br />
"props": {"x-custom": "any value"},<br />
"module": "mail",<br />
"displayname": "My signature",<br />
"misc": {"foo": "bar"},<br />
"createdby": 17,<br />
"content": "-- \\nMy name and position here",<br />
"accountid": 0,<br />
"shared": false,<br />
"files":<br />
[<br />
{<br />
"mimetype": "image/png; name=pic.png",<br />
"filename": "pic.png",<br />
"id": "46f49f8a-40d5-4f29-8bc9-728f3420864c",<br />
"size": 6074<br />
}<br />
]<br />
}<br />
<br />
=== Gets all snippets associated with the current user and context ===<br />
<br />
GET /ajax/snippet?action=all<br />
<br />
* session - The session identifier<br />
* type - Optional CSV of types to filter by; e.g. "signature"<br />
<br />
Response:<br />
A JSON array of snippets' JSON representations<br />
<br />
<br />
<br />
=== Gets certain snippets by identifiers ===<br />
<br />
GET /ajax/snippet?action=list<br />
<br />
* session - The session identifier<br />
<br />
Request body:<br />
A JSON array of snippet identifiers<br />
<br />
Response:<br />
A JSON array of snippets' JSON representations<br />
<br />
<br />
<br />
=== Gets a certain snippet's attachment by identifier ===<br />
<br />
GET /ajax/snippet?action=getattachment<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
* attachmentid - The attachment identifier<br />
<br />
Response:<br />
The attachment's raw data<br />
<br />
<br />
<br />
=== Creates a new snippet ===<br />
<br />
PUT /ajax/snippet?action=new<br />
<br />
* session - The session identifier<br />
<br />
Request body:<br />
A JSON representation of the snippet.<br />
Excluding its attachments (see attach/detach actions)<br />
<br />
Response:<br />
The created snippet's identifier<br />
<br />
<br />
<br />
=== Updates a certain snippet by identifier ===<br />
<br />
PUT /ajax/snippet?action=update<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
<br />
Request body:<br />
A JSON representation of the snippet providing the fields that should be changed.<br />
Excluding its attachments (see attach/detach actions)<br />
<br />
Response:<br />
The updated snippet's JSON representation<br />
<br />
<br />
<br />
=== Deletes a certain snippet by identifier ===<br />
<br />
PUT /ajax/snippet?action=delete<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier (otherwise provide one or more identifiers through request body's JSON array)<br />
<br />
Request body:<br />
A JSON array of identifiers denoting the snippets to delete<br />
<br />
Response:<br />
An empty/dummy result (don't care)<br />
<br />
<br />
<br />
=== Attaches one or more files to an existing snippet ===<br />
<br />
POST /ajax/snippet?action=attach<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
<br />
Request body:<br />
Multipart form data providing the upload files to attach to the snippet.<br />
<br />
Response:<br />
The updated snippet's identifier<br />
<br />
<br />
<br />
=== Detaches open or more files from an existing snippet ===<br />
<br />
PUT /ajax/snippet?action=detach<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
<br />
Request body:<br />
A JSON array providing the identifiers of the attachments to remove from snippet<br />
<br />
Response:<br />
The updated snippet's identifier<br />
<br />
== Picture Halo (since 7.4.1) ==<br />
<br />
GET /appsuite/api/halo/contact/picture<br />
* session - (optional) falls back to the public session cookie<br />
* internal_userid - (optional) The internal user id of a user whose picture you want to load<br />
* userid - (optional) an alias for internal_userid<br />
* user_id - (optional) an alias for internal_userid<br />
* id - (optional) a contact id<br />
* email - (optional) an email to search for. Will pick global address book matches before regular matches. After that picks the most recently changed contact<br />
* email1 - (optional) an alias for email<br />
* email2 - (optional) another email address to use to find matches<br />
* email3 - (optional) and yet another email address to use to find matches<br />
<br />
''At least one of the optional search parameters should be set. All parameters are connected by OR during the search. More specific parameters like user_id or id are prioritized in case of multiple matches.''<br />
<br />
Response:<br />
The picture with proper eTag and caching headers set, or an HTTP Status 404 response, if no picture could be found.<br />
<br />
<br />
== Module "capabilities" (available with v7.4.2) ==<br />
<br />
Provides access to capabilities, i.e. modules or features that are available on the backend and the user has access to.<br />
<br />
=== Get a capability ===<br />
<br />
GET <code>/ajax/capabilities?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The identifier of the capability<br />
<br />
Response: The requested capability as described in [[#Capability| Capability]], if available, otherwise an empty result<br />
<br />
{| id="Capability" cellspacing="0" border="1"<br />
|+ align="bottom" | Capability<br />
! Name !! Type !! Value<br />
|-<br />
| id || String || The identifier of the capability<br />
|-<br />
| attributes || Object || A JSON object holding optional properties of the capability <br />
|}<br />
<br />
=== Get all capabilities ===<br />
<br />
GET <code>/ajax/capabilities?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: An array of capability objects as described in [[#Capability| Capability]].<br />
<br />
<br />
== Module "jump" (available with v7.6.0) ==<br />
<br />
The jump module is used to pass an acquired identity token for an authenticated user from one system to another for a single sign-on.<br />
<br />
=== Acquire an identity token ===<br />
<br />
GET <code>/ajax/jump?action=identityToken</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>system</code> – The identifier for the external service/system<br />
<br />
Response: The acquired identity token wrapped by a simple JSON object as described in [[#Jump| Jump]]<br />
<br />
{| id="Jump" cellspacing="0" border="1"<br />
|+ align="bottom" | Jump<br />
! Name !! Type !! Value<br />
|-<br />
| token || String || The identifier of the token<br />
|}<br />
<br />
== Module "find" (preliminary, available with v7.6.1) ==<br />
The Find API consists of calls for performing searches within the modules mail, contacts, calendar, tasks and drive. It was designed to provide an iterative approach where the search criteria can be refined step-wise until the desired items are found. The starting point is always an "autocomplete" request, that suggests possible search filters based on a users input. Those filters are grouped into categories, called "facets". A facet may provide one or more "values" with every value being a possible filter. A client is meant to remember every value that was selected by a user and include it within the following "autocomplete" and "query" requests, while "query" performs the actual search and returns the found items.<br />
<br />
Every request is bound to a module that must be specified via the URL-Parameter "module". Possible modules are<br />
* mail<br />
* contacts<br />
* calendar<br />
* tasks<br />
* drive<br />
<br />
=== General assumptions ===<br />
Some of the objects returned by the server contain former user input. A client must never interpret strings as HTML but always as plain text to be not vulnerable for CSS attacks!<br />
<br />
=== Calls ===<br />
The find API provides two dedicated calls under the servlet path <code>find</code>:<br />
* action=autocomplete<br />
* action=query<br />
<br />
=== Facets ===<br />
The style of a facet is responsible for how the according object is structured, how it is handled on the server-side and how the client has to handle it.<br />
We distinguish three styles of facets:<br />
* simple<br />
* default<br />
* exclusive<br />
<br />
Every facet value contains an embedded "filter" object. The filter must not be changed by the client, it has to be seen as a black-box. Instead the filters<br />
of selected facet values have to be copied and sent to the server with the subsequent requests.<br />
<br />
==== Simple Facets ====<br />
A simple facet is a special facet that has exactly one value. The facets<br />
type and its value are strictly coupled, in a way that a display name for both,<br />
facet and value would be redundant. A simple facet generally denotes a logical field like<br />
'phone number'. Internally this logical field can map to several internal fields<br />
(e.g. 'phone_private', 'phone_mobile', 'phone_business'). In clients the facet as<br />
a whole can be displayed as a single item. Example: "Search for 'term' in field 'phone<br />
number'".<br />
<br />
<br />
{| id="Facet Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Facet Structure<br />
! Field !! Type !! Description<br />
|-<br />
| style || "simple" || Denotes that this is a facet of style simple<br />
|-<br />
| id || <string> || The id of this facet. Unique within an autocomplete response. Can be used to distinguish and filter certain facets.<br />
|-<br />
| name || <string> || A displayable (and localized) name for this facet. If absent, an "item" attribute is present.<br />
|-<br />
| item (optional) || <object> || A more complex object to display this facet. Attributes are "name", "detail" (optional) and "image_url" (optional).<br />
|-<br />
| filter || <object> || The filter to refine the search.<br />
|-<br />
| flags || <array> || An array of flags, represented as strings.<br />
|}<br />
<br />
Example:<br />
<pre><br />
{<br />
"id":"global",<br />
"style":"simple",<br />
"name":"test",<br />
"filter":{},<br />
"flags":[]<br />
}<br />
</pre><br />
<br />
==== Default Facets ====<br />
A default facet contains multiple values and may be present<br />
multiple times in search requests to filter results by a combination of different<br />
values (e.g. "mails with 'foo' and 'bar' in subject").<br />
<br />
Facet values may be one- or two-dimensional. A one-dimensional value can be displayed as is and contains an according filter object.<br />
A two-dimensional value contains an array "options" with every option defining different semantics of how the value is used to filter the search results.<br />
<br />
{| id="Default Facet Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Facet Structure<br />
! Field !! Type !! Description<br />
|-<br />
| style || "default" || Denotes that this is a facet of style default<br />
|-<br />
| id || <string> || The id of this facet. Unique within an autocomplete response. Can be used to distinguish and filter certain facets.<br />
|-<br />
| name || <string> || A displayable (and localized) name for this facet. If absent, an "item" attribute is present.<br />
|-<br />
| item (optional) || <object> || A more complex object to display this facet. Attributes are "name", "detail" (optional) and "image_url" (optional).<br />
|-<br />
| values || <array> || An array of facet values.<br />
|-<br />
| flags || <array> || An array of flags, represented as strings.<br />
|}<br />
<br />
{| id="Default Facet Value Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Value Structure<br />
! Field !! Type !! Description<br />
|-<br />
| id || <string> || The values id. Unique within one facet.<br />
|-<br />
| name || <string> || A displayable (and localized) name for this value. May be superseded with an "item" attribute. Absent if the value contains options.<br />
|-<br />
| item (optional) || <object> || A more complex object to display this value. Attributes are "name", "detail" (optional) and "image_url" (optional). Absent if the value contains options.<br />
|-<br />
| filter || <object> || The filter to refine the search. Absent if the value contains options.<br />
|-<br />
| options (optional) || <array> || An array of options.<br />
|}<br />
<br />
{| id="Default Facet Option Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Option Structure<br />
! Field !! Type !! Description<br />
|-<br />
| id || <string> || The options id. Unique within a set of options.<br />
|-<br />
| name || <string> || The displayable (and localized) name for this option.<br />
|-<br />
| filter || <object> || The filter to refine the search.<br />
|-<br />
|}<br />
<br />
Example:<br />
<pre><br />
{<br />
"id":"contacts",<br />
"style":"default",<br />
"name":"People",<br />
"values":[<br />
{<br />
"id":"contact/424242669/525793",<br />
"item":{<br />
"name":"Test Usere2123",<br />
"detail":"testuse1212r@example.com"<br />
},<br />
"options":[<br />
{<br />
"id":"from",<br />
"name":"From",<br />
"filter":{}<br />
},<br />
{<br />
"id":"to",<br />
"name":"To",<br />
"filter":{}<br />
},<br />
{<br />
"id":"all",<br />
"name":"From/To",<br />
"filter":{}<br />
}<br />
]<br />
}<br />
],<br />
"flags":[]<br />
}<br />
</pre><br />
<br />
==== Exclusive Facets ====<br />
An exclusive facet is a facet where the contained values are<br />
mutually exclusive. That means that the facet must only be present once<br />
in an autocomplete or query request.<br />
<br />
Facet values may be one- or two-dimensional. A one-dimensional value can be displayed as is and contains an according filter object.<br />
A two-dimensional value contains an array "options" with every option defining different semantics of how the value is used to filter the search results. <br />
<br />
{| id="Exclusive Facet Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Facet Structure<br />
! Field !! Type !! Description<br />
|-<br />
| style || "exclusive" || Denotes that this is a facet of style exclusive<br />
|-<br />
| id || <string> || The id of this facet. Unique within an autocomplete response. Can be used to distinguish and filter certain facets.<br />
|-<br />
| name || <string> || A displayable (and localized) name for this facet. If absent, an "item" attribute is present.<br />
|-<br />
| item (optional) || <object> || A more complex object to display this facet. Attributes are "name", "detail" (optional) and "image_url" (optional).<br />
|-<br />
| options || <array> || An array of facet values.<br />
|-<br />
| flags || <array> || An array of flags, represented as strings.<br />
|}<br />
<br />
{| id="Exclusive Facet Value Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Value Structure<br />
! Field !! Type !! Description<br />
|-<br />
| id || <string> || The values id. Unique within one facet.<br />
|-<br />
| name || <string> || A displayable (and localized) name for this value. May be superseded with an "item" attribute. Absent if the value contains options.<br />
|-<br />
| item (optional) || <object> || A more complex object to display this value. Attributes are "name", "detail" (optional) and "image_url" (optional). Absent if the value contains options.<br />
|-<br />
| filter || <object> || The filter to refine the search. Absent if the value contains options.<br />
|-<br />
| options (optional) || <array> || An array of options.<br />
|}<br />
<br />
{| id="Exclusive Facet Option Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Option Structure<br />
! Field !! Type !! Description<br />
|-<br />
| id || <string> || The options id. Unique within a set of options.<br />
|-<br />
| name || <string> || The displayable (and localized) name for this option.<br />
|-<br />
| filter || <object> || The filter to refine the search.<br />
|-<br />
|}<br />
<br />
Example:<br />
<pre><br />
{<br />
"id":"time",<br />
"style":"exclusive",<br />
"name":"Time",<br />
"options":[<br />
{<br />
"id":"last_week",<br />
"name":"last week",<br />
"filter":{}<br />
},<br />
{<br />
"id":"last_month",<br />
"name":"last month",<br />
"filter":{}<br />
},<br />
{<br />
"id":"last_year",<br />
"name":"last year",<br />
"filter":{}<br />
}<br />
],<br />
"flags":[]<br />
}<br />
</pre><br />
<br />
<br />
==== Active Facets ====<br />
Every value that has been selected by a user must be remembered and provided with every subsequent request. The representation of a facet within a request body differs from the one within an autocomplete response. We call those "active facets". Their representation is independent from their style.<br />
<br />
{| id="Active Facet Structure" cellspacing="0" border="1"<br />
|+ align="bottom" | Active Facet Structure<br />
! Field !! Type !! Description<br />
|-<br />
| facet || <string> || The id of the according facet.<br />
|-<br />
| value || <string> || The id of the according value. Must always be copied from the value object, not from a possibly according option (in the two-dimensional case).<br />
|-<br />
| filter || <object> || The filter object, copied from the value or option.<br />
|}<br />
<br />
<br />
=== Configuration ===<br />
According to the users configuration, some restrictions may apply that have to be heeded by clients. Those restrictions can be retrieved via the "config" or the "jslob" modules. The following restrictions may apply:<br />
<br />
* A user might have limited access to modules and therefore the Find API may only serve requests for a subset of all possible modules. The configuration object may contain an object with key "modules". Its value is an array containing all module identifiers that the user is allowed to use.<br />
<br />
* Some facets can be mandatory, i.e. they must be pre-defined by the client and provided with every request. Whether a facet is mandatory or not is decided on a per-module basis. The configuration object may contain an object with key "mandatory". Every facet that may be mandatory is specified via its id in that object (e.g. mandatory.folder). The value of such a key is either an array containing all module identifiers, where the facet is mandatory or null, if it is not manadatory in any module.<br />
<br />
* Due to performance reasons the service provider can enforce a minimium number of characters that have to be provided before an autocomplete request may be issued. That property is called "minimumQueryLength" and its value is an integer that specifies the minimum number of characters. If a client does not heed this property, the server will respond with an error if the provided user input is too short.<br />
<br />
==== Config Example ====<br />
<pre><br />
GET http://localhost/appsuite/api/config/search?session={{session}}<br />
Response:<br />
{<br />
"data": {<br />
"mandatory": {<br />
"folder": [<br />
"mail"<br />
]<br />
},<br />
"modules": [<br />
"mail",<br />
"contacts",<br />
"calendar",<br />
"tasks",<br />
"drive"<br />
]<br />
}<br />
}<br />
<br />
GET http://localhost/appsuite/api/config/minimumSearchCharacters?session={{session}}<br />
Response:<br />
{<br />
"data": 0<br />
}<br />
</pre><br />
<br />
==== JSLob Example ====<br />
<pre><br />
GET http://localhost/appsuite/api/jslob?action=get&id=io.ox/core&session={{session}}<br />
Response:<br />
{<br />
"data": {<br />
"id": "io.ox/core",<br />
"tree": {<br />
"search": {<br />
"modules": [<br />
"mail",<br />
"contacts",<br />
"calendar",<br />
"tasks",<br />
"drive"<br />
],<br />
"mandatory": {<br />
"folder": [<br />
"mail"<br />
]<br />
},<br />
"minimumQueryLength": 0<br />
}<br />
}<br />
}<br />
}<br />
</pre><br />
<br />
=== autocomplete ===<br />
Mandatory URL parameters:<br />
* action=autocomplete<br />
* module=<module-name><br />
* session=<session-id><br />
<br />
Optional URL parameters:<br />
* limit=<int> - The maximum number of values returned per facet<br />
<br />
Request body: A JSON object containing the users input (specified as "prefix"), already selected facets and possible options.<br />
<br />
<br />
==== Example ====<br />
<pre><br />
PUT http://localhost/appsuite/api/find?action=autocomplete&module=mail&limit=3&session={{session}}<br />
{<br />
"prefix":"test", <br />
"facets":[<br />
{<br />
"facet":"folder",<br />
"value":"default0/INBOX"<br />
}<br />
],<br />
"options":{<br />
"timezone":"UTC",<br />
"admin":false<br />
}<br />
}<br />
<br />
Response:<br />
{<br />
"data":{<br />
"facets":[<br />
{<br />
"id":"global",<br />
"style":"simple",<br />
"name":"test",<br />
"filter":{},<br />
"flags":[]<br />
}, <br />
{<br />
"id":"contacts",<br />
"style":"default",<br />
"name":"People",<br />
"values":[<br />
{<br />
"id":"contact/424242669/525793",<br />
"item":{<br />
"name":"Test Usere2123",<br />
"detail":"testuse1212r@example.com"<br />
},<br />
"options":[<br />
{<br />
"id":"from",<br />
"name":"From",<br />
"filter":{}<br />
},<br />
{<br />
"id":"to",<br />
"name":"To",<br />
"filter":{}<br />
},<br />
{<br />
"id":"all",<br />
"name":"From/To",<br />
"filter":{}<br />
}<br />
]<br />
}<br />
],<br />
"flags":[]<br />
},<br />
{<br />
"id":"time",<br />
"style":"exclusive",<br />
"name":"Time",<br />
"options":[<br />
{<br />
"id":"last_week",<br />
"name":"last week",<br />
"filter":{}<br />
},<br />
{<br />
"id":"last_month",<br />
"name":"last month",<br />
"filter":{}<br />
},<br />
{<br />
"id":"last_year",<br />
"name":"last year",<br />
"filter":{}<br />
}<br />
],<br />
"flags":[]<br />
}<br />
]<br />
}<br />
}<br />
</pre><br />
<br />
=== query ===<br />
Mandatory URL parameters:<br />
* action=query<br />
* module=<module-name><br />
* session=<session-id><br />
<br />
Optional URL parameters:<br />
* columns=<column-ids> - A comma-separated list of the module-specific columns that shall be contained in the response items.<br />
<br />
Request body: A JSON object containing the selected facets and possible options. For pagination the keys "start" and "size" can be set.<br />
<br />
==== Example ====<br />
<pre><br />
PUT http://localhost/appsuite/api/find?action=query&module=mail&columns=102,600,601,602,603,604,605,607,608,610,611,614,652&session={{session}}<br />
{<br />
"facets":[<br />
{<br />
"facet":"folder",<br />
"value":"default0/INBOX",<br />
"filter":null<br />
},<br />
{<br />
"facet":"subject",<br />
"value":1409579708116,<br />
"filter":{<br />
"fields":[<br />
"subject"<br />
],<br />
"queries":[<br />
"lorem"<br />
]<br />
}<br />
}<br />
],<br />
"options":{<br />
"timezone":"UTC",<br />
"admin":false<br />
},<br />
"start":0,<br />
"size":101<br />
}<br />
<br />
Response:<br />
{<br />
"data":{<br />
"num_found":-1,<br />
"start":0,<br />
"size":1,<br />
"results":[<br />
{<br />
"color_label":0,<br />
"id":"110458",<br />
"folder_id":"default0/INBOX",<br />
"attachment":false,<br />
"from":[<br />
[<br />
"John Doe",<br />
"john.doe@example.com"<br />
]<br />
],<br />
"to":[<br />
[<br />
"Jane Doe",<br />
"jane.doe@example.com"<br />
]<br />
],<br />
"cc":[<br />
<br />
],<br />
"subject":"Lorem Ipsum",<br />
"size":7501,<br />
"received_date":1408531387000,<br />
"flags":32,<br />
"priority":3,<br />
"account_name":"E-Mail",<br />
"account_id":0<br />
}<br />
]<br />
}<br />
}<br />
</pre><br />
<br />
=== Available Options ===<br />
Every request body may contain an "options" object to finetune some specific behavior. Currently possible options are:<br />
* timezone: <tz-name> - The timezone to use if any dates are returned.<br />
* admin: <boolean> - true to include the context admin if it matches any search criteria. If the context admin shall always be ignored (i.e. not returned), false has to be set.<br />
<br />
=== Possible Flags ===<br />
Every facet may carry one or more flags that describe further aspects of that facet. Currently possible flags are:<br />
* conflicts - Specified in the form of "conflicts:<other-id>". A facet carrying this flag must not be combined with a facet of type <other-id>.<br />
<br />
<br />
== Module "share/management" (preliminary, available with v7.8.0) ==<br />
<br />
Existing shares can be accessed via different actions in the "share/management" module. <br />
<br />
=== Get all shares ===<br />
<br />
GET <code>/ajax/share/management?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>module</code> – (optional) The module identifier to list all shares for.<br />
<br />
Response with timestamp: An array with share data. Each array element is a JSON object as described Share Info.<br />
<br />
{| id="ShareInfo" cellspacing="0" border="1"<br />
|+ align="bottom" | Share Info<br />
! Name !! Type !! Value<br />
|-<br />
| share_url || String || The URL to access the share.<br />
|-<br />
| token || String || The (fully qualified) token of the share target.<br />
|-<br />
| authentication || String || The authentication type used to access the share, one of ''guest_password'', ''anonymous'' or ''anonymous_password''. <br />
|-<br />
| created || Time || The time the share was created. <br />
|-<br />
| created_by || Number || The identifier of the user who created the share. <br />
|-<br />
| last_modified || Time || The time the share was last modified. <br />
|-<br />
| modified_by || Time || The identifier of the user who modified the share. <br />
|-<br />
| target || Object || The share target as described in Share Target <br />
|-<br />
| recipient || Object || Information about the recipient of the share, i.e. the guest user, as described in Share Recipient <br />
|}<br />
<br />
{| id="ShareTarget" cellspacing="0" border="1"<br />
|+ align="bottom" | Share Target<br />
! Name !! Type !! Value<br />
|-<br />
| module || String || The folder's module name, i.e. one of "tasks", "calendar", "contacts", "infostore" <br />
|-<br />
| folder || String || The folder identifier <br />
|-<br />
| item || String || (Optional) The object identifier, in case the share targets a single item <br />
|-<br />
| expiry_date || Time || (Optional) The end date / expiration time after which the share link is no longer accessible. Must be given in milliseconds after 01-01-1970 in the users time zone or the time zone contained as URL parameter <br />
|-<br />
| meta || JSON || Stores arbitrary JSON data as specified by client. <br />
|}<br />
<br />
{| id="ShareRecipient" cellspacing="0" border="1"<br />
|+ align="bottom" | Share Recipient<br />
! Name !! Type !! Value<br />
|-<br />
| type || String || The recipient type, one of ''guest'' or ''anonymous''. <br />
|-<br />
| base_token || String || The base token associated with the guest user. <br />
|-<br />
| password || String || The password to access the share, in case the used authentication mode is ''anonymous_password''. <br />
|-<br />
| email_address || String || The email address of the named guest user, in case the recipient type is ''guest''. <br />
|-<br />
| entity || Number || The identifier of the underlying guest user entity. <br />
|}<br />
<br />
=== Get a share ===<br />
<br />
GET <code>/ajax/share/management?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>token</code> – The (fully qualified) token of the share.<br />
<br />
Response with timestamp: A JSON object as described in Share Info.<br />
<br />
=== Delete shares ===<br />
<br />
PUT <code>/ajax/share/management?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An array containing the tokens of the shares to delete.<br />
<br />
Response with timestamp: An empty JSON result in case of no errors.<br />
<br />
=== Get a link ===<br />
<br />
PUT <code>/ajax/share/management?action=getLink</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON object describing the shares to be created as described in Get a link. It contains an array holding the share "targets" as well as some properties of the guest user to be created.<br />
<br />
Response with timestamp: Basic information about the created share as described in GetALinkResponse.<br />
<br />
{| id="GetALink" cellspacing="0" border="1"<br />
|+ align="bottom" | Get a link<br />
! Name !! Type !! Value<br />
|-<br />
| targets || Array || An array of objects as described in Share Target <br />
|-<br />
| bits || Number || (Optional) A number as described in Permission flags. For single items, the bits for reading, writing and deleting objects in folders are taken into account. At least one of those must grant permissions to all objects, not only own ones. The highest value will be chosen based on the following sequence: delete all > write all > read all. If not set, only read permissions are granted. <br />
|-<br />
| password || String || (Optional) An additional secret / pin number an anonymous user needs to enter when accessing the share <br />
|}<br />
<br />
{| id="GetALinkResponse" cellspacing="0" border="1"<br />
|+ align="bottom" | Get a link response<br />
! Name !! Type !! Value<br />
|-<br />
| url || String || The link to the share<br />
|-<br />
| token || String || The share token as a reference for consecutive requests <br />
|}<br />
<br />
=== Update a link ===<br />
<br />
PUT <code>/ajax/share/management?action=updateLink</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – The last modified timestamp of the share to be updated. Used to detect concurrent modifications.<br />
<br />
Request body: A JSON object describing the share to be updated as described in UpdateALink.<br />
<br />
Response with timestamp: An empty JSON result in case of no errors.<br />
<br />
{| id="UpdateALink" cellspacing="0" border="1"<br />
|+ align="bottom" | Update a link<br />
! Name !! Type !! Value<br />
|-<br />
| token || String || The token of the share to update<br />
|-<br />
| expiry_date || Time || (Optional) The end date / expiration time after which the share link is no longer accessible. Must be given in milliseconds after 01-01-1970 in the users time zone or the time zone contained as URL parameter.<br />
|-<br />
| password || String || (Optional) An additional secret / pin number an anonymous user needs to enter when accessing the share<br />
|-<br />
| bits || Number || (Optional) A number as described in Permission flags. For single items, the bits for reading, writing and deleting objects in folders are taken into account. At least one of those must grant permissions to all objects, not only own ones. The highest value will be chosen based on the following sequence: delete all > write all > read all. If not set, only read permissions are granted.<br />
|-<br />
| meta || JSON || Stores arbitrary JSON data as specified by client<br />
|}<br />
<br />
=== Delete a link ===<br />
<br />
GET <code>/ajax/share/management?action=deleteLink</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>token</code> – The token of the share to delete.<br />
<br />
Response with timestamp: An empty JSON result in case of no errors.<br />
<br />
=== Invite ===<br />
<br />
PUT <code>/ajax/share/management?action=invite</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON object representing the shares to be created as described in Invite Data.<br />
<br />
Response with timestamp: An array of share tokens for all created external recipients. The tokens are in the same order as the recipients in the request array. For internal users and groups a NULL value is set in the array.<br />
<br />
{| id="InviteData" cellspacing="0" border="1"<br />
|+ align="bottom" | Invite data<br />
! Name !! Type !! Value<br />
|-<br />
| targets || Array || An array of objects as described in Share Target <br />
|-<br />
| recipients || Array || An array of objects as described in Invited Recipient<br />
|-<br />
| message || String || (Optional) A custom message that will be contained in the notification mails for guests with mail addresses and password.<br />
|}<br />
<br />
{| id="InvitedRecipient" cellspacing="0" border="1"<br />
|+ align="bottom" | Invited recipient<br />
! Name !! Type !! Value<br />
|-<br />
| type || String || The recipient type, i.e. one of "user", "group", "guest", "anonymous"<br />
|-<br />
| bits || Number || A number as described in Permission flags. For single items, the bits for reading, writing and deleting objects in folders are taken into account. At least one of those must grant permissions to all objects, not only own ones. The highest value will be chosen based on the following sequence: delete all > write all > read all.<br />
|-<br />
| entity || Number || (for type "user" or "group") The user or group identifier of the recipient<br />
|-<br />
| password || String || (for type "anonymous", optional) An additional secret / pin number an anonymous user needs to enter when accessing the share<br />
|-<br />
| email_address || String || (for type "guest") The e-mail address of the recipient<br />
|-<br />
| display_name || String || (for type "guest", optional) The display name of the recipient<br />
|-<br />
| contact_id || String || (for type "guest", optional) The object identifier of the corresponding contact entry if the recipient was chosen from the address book<br />
|-<br />
| contact_folder || String || (for type "guest", required if "contact_id" is set) The folder identifier of the corresponding contact entry if the recipient was chosen from the address book<br />
|}</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:UI_manifests_explained&diff=19098AppSuite:UI manifests explained2015-02-05T13:19:28Z<p>Viktor.Pracht: Added double quotes to strings, manifests must be proper JSON now.</p>
<hr />
<div>{{Stability-experimental}}<br />
<br />
<div class="title">Manifests</div><br />
<br />
'''Abstract:''' Manifest files in the app suite declare either apps or plugins. They tell the AppSuite runtime which files to load when, so the code in it can take effect at the appropriate time. This document should be read by everyone that wants to either build a plugin or an app and contains a description of how to get app suite to run your code.<br />
<br />
== Declaring apps ==<br />
<br />
The minimal declaration for an app looks like this:<br />
<br />
<pre class="language-javascript"> <br />
{<br />
"title": "My App",<br />
"path": "com.example/myapp/main"<br />
} <br />
</pre><br />
It consists of a title for the app and the path to the main entry file, by convention always called main.js. This declaration is usually found in the file manifest.json right next to the app in question, but could theoretically be located anywhere. If the file is located in the same directory as the main entry file and the file is, as is the convention, called main.js you can leave out the path as it will be added automatically by the buildsystem, so the minimal definition then becomes:<br />
<br />
<pre class="language-javascript"> <br />
{<br />
"title": "My App"<br />
}<br />
</pre><br />
<br />
== Declaring a plugin ==<br />
<br />
In turn, this is the definition of a plugin file:<br />
<pre class="language-javascript"> <br />
{<br />
"namespace": "io.ox/contacts/view-detail",<br />
"path": "com.example/myapp/contacts/register"<br />
} <br />
</pre><br />
<br />
The namespace contains the name of a frontend module for which the plugin is relevant. Declaring a plugin like this has the effect, that the plugin is loaded before the file named as the namespace is loaded, so it can affect what the core file is doing, commonly by extending an extension point. The convention is to always put plugins into the file register.js, so again, the path can be omitted if the manifest.json is placed alongside the register.js containing the plugin. A plugin may be associated with more than one namespace, in that case, just use a list as the value for the namespace attribute:<br />
<br />
<pre class="language-javascript"> <br />
{<br />
"namespace": ["io.ox/contacts/view-detail", "io.ox/contacts/edit/view-form"]<br />
}<br />
</pre><br />
<br />
Whichever module is loaded first will trigger the plugin to be loaded.<br />
<br />
== Capabilities ==<br />
<br />
Sometimes a plugin or an app is only available if either the backend has a certain bundle installed or the user must have a certain permission. Both permissions and backend capabilities are rolled into the concept of a "capability". If your plugin, for example, is only relevant when the user has access to the calendar module, you can add a requires attribute to the declaration:<br />
<br />
<pre class="language-javascript"> <br />
{<br />
"namespace": "io.ox/contacts/view-detail",<br />
"requires": "calendar"<br />
}<br />
</pre> <br />
<br />
Which capabilities are available can be checked by either reading through existing manifests or by running this in the javascript console once logged into appsuite:<br />
<br />
<pre class="language-javascript"> <br />
_(ox.serverConfig.capabilities).pluck("id")<br />
</pre><br />
<br />
== Device tests ==<br />
<br />
If a plugin is designed only for specific devices, screen sizes or languages, then its loading can be disabling by specifying the criteria in a <tt>device</tt> attribute:<br />
<br />
<pre class="language-javascript"><br />
{<br />
"namespace": "io.ox/contacts/view-detail",<br />
"device": "ja_JP"<br />
}<br />
</pre><br />
<br />
The full list of available device tests is documented in the [[AppSuite:Device reference|Device reference]].<br />
<br />
== Multiple declarations in one file ==<br />
<br />
If you need more than declaration in a manifest.json file, you can include them in a list:<br />
<pre class="language-javascript"> <br />
[<br />
{<br />
"namespace": "io.ox/contacts/view-detail",<br />
"path": "com.example/myapp/contacts/viewPlugin"<br />
},<br />
{<br />
"namespace": "io.ox/contacts/view-form",<br />
"path": "com.example/myapp/contacts/formPlugin"<br />
}<br />
]<br />
</pre><br />
<br />
== What happens to these files? ==<br />
<br />
During a build run the buildsystem picks up these manifest files and consolidates them into a single file build/manifests/[myapp].json. This file, either by creating a symlink to a locally run backend or by installing the app package on a remote backend, winds up in the manifests directory of the backend and is processed and sent to the frontend. You can see all manifest declarations, that have been sent by the backend by looking at<br />
ox.serverConfig.manifests<br />
in the javascript console.<br />
<br />
== Special namespaces ==<br />
<br />
=== signin ===<br />
<br />
Plugins that choose "signin" as (or amongst) their namespace, are loaded when the login page is shown. The code can be used to rearrange parts of the signin page or add custom behaviour to it.<br />
<br />
=== core ===<br />
<br />
Core plugins are loaded as soon as the frontend starts up after successfully logging in or reauthenticating with the autologin. This is useful if you need to run code very early.<br />
<br />
[[Category:AppSuite]]<br />
[[Category:UI]]</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:UI_manifests_explained&diff=19097AppSuite:UI manifests explained2015-02-05T13:17:53Z<p>Viktor.Pracht: /* Device tests */</p>
<hr />
<div>{{Stability-experimental}}<br />
<br />
<div class="title">Manifests</div><br />
<br />
'''Abstract:''' Manifest files in the app suite declare either apps or plugins. They tell the AppSuite runtime which files to load when, so the code in it can take effect at the appropriate time. This document should be read by everyone that wants to either build a plugin or an app and contains a description of how to get app suite to run your code.<br />
<br />
== Declaring apps ==<br />
<br />
The minimal declaration for an app looks like this:<br />
<br />
<pre class="language-javascript"> <br />
{<br />
title: "My App",<br />
path: "com.example/myapp/main"<br />
} <br />
</pre><br />
It consists of a title for the app and the path to the main entry file, by convention always called main.js. This declaration is usually found in the file manifest.json right next to the app in question, but could theoretically be located anywhere. If the file is located in the same directory as the main entry file and the file is, as is the convention, called main.js you can leave out the path as it will be added automatically by the buildsystem, so the minimal definition then becomes:<br />
<br />
<pre class="language-javascript"> <br />
{<br />
title: "My App"<br />
}<br />
</pre><br />
<br />
== Declaring a plugin ==<br />
<br />
In turn, this is the definition of a plugin file:<br />
<pre class="language-javascript"> <br />
{<br />
namespace: "io.ox/contacts/view-detail",<br />
path: "com.example/myapp/contacts/register"<br />
} <br />
</pre><br />
<br />
The namespace contains the name of a frontend module for which the plugin is relevant. Declaring a plugin like this has the effect, that the plugin is loaded before the file named as the namespace is loaded, so it can affect what the core file is doing, commonly by extending an extension point. The convention is to always put plugins into the file register.js, so again, the path can be omitted if the manifest.json is placed alongside the register.js containing the plugin. A plugin may be associated with more than one namespace, in that case, just use a list as the value for the namespace attribute:<br />
<br />
<pre class="language-javascript"> <br />
{<br />
namespace: ["io.ox/contacts/view-detail", "io.ox/contacts/edit/view-form"]<br />
}<br />
</pre><br />
<br />
Whichever module is loaded first will trigger the plugin to be loaded.<br />
<br />
== Capabilities ==<br />
<br />
Sometimes a plugin or an app is only available if either the backend has a certain bundle installed or the user must have a certain permission. Both permissions and backend capabilities are rolled into the concept of a "capability". If your plugin, for example, is only relevant when the user has access to the calendar module, you can add a requires attribute to the declaration:<br />
<br />
<pre class="language-javascript"> <br />
{<br />
namespace: "io.ox/contacts/view-detail",<br />
requires: "calendar"<br />
}<br />
</pre> <br />
<br />
Which capabilities are available can be checked by either reading through existing manifests or by running this in the javascript console once logged into appsuite:<br />
<br />
<pre class="language-javascript"> <br />
_(ox.serverConfig.capabilities).pluck("id")<br />
</pre><br />
<br />
== Device tests ==<br />
<br />
If a plugin is designed only for specific devices, screen sizes or languages, then its loading can be disabling by specifying the criteria in a <tt>device</tt> attribute:<br />
<br />
<pre class="language-javascript"><br />
{<br />
"namespace": "io.ox/contacts/view-detail",<br />
"device": "ja_JP"<br />
}<br />
</pre><br />
<br />
The full list of available device tests is documented in the [[AppSuite:Device reference|Device reference]].<br />
<br />
== Multiple declarations in one file ==<br />
<br />
If you need more than declaration in a manifest.json file, you can include them in a list:<br />
<pre class="language-javascript"> <br />
[<br />
{<br />
namespace: "io.ox/contacts/view-detail",<br />
path: "com.example/myapp/contacts/viewPlugin"<br />
},<br />
{<br />
namespace: "io.ox/contacts/view-form",<br />
path: "com.example/myapp/contacts/formPlugin"<br />
}<br />
]<br />
</pre><br />
<br />
== What happens to these files? ==<br />
<br />
During a build run the buildsystem picks up these manifest files and consolidates them into a single file build/manifests/[myapp].json. This file, either by creating a symlink to a locally run backend or by installing the app package on a remote backend, winds up in the manifests directory of the backend and is processed and sent to the frontend. You can see all manifest declarations, that have been sent by the backend by looking at<br />
ox.serverConfig.manifests<br />
in the javascript console.<br />
<br />
== Special namespaces ==<br />
<br />
=== signin ===<br />
<br />
Plugins that choose "signin" as (or amongst) their namespace, are loaded when the login page is shown. The code can be used to rearrange parts of the signin page or add custom behaviour to it.<br />
<br />
=== core ===<br />
<br />
Core plugins are loaded as soon as the frontend starts up after successfully logging in or reauthenticating with the autologin. This is useful if you need to run code very early.<br />
<br />
[[Category:AppSuite]]<br />
[[Category:UI]]</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:Device_reference&diff=19096AppSuite:Device reference2015-02-05T13:05:42Z<p>Viktor.Pracht: Documented _.device()</p>
<hr />
<div>{{Stability-unstable}}<br />
<br />
<div class="title">_.device() reference</div><br />
<br />
The function <tt>_.device()</tt> is used to test various device-specific aspects of the runtime environment. It is also used to evaluate the <tt>device</tt> clause of manifest entries.<br />
<br />
__TOC__<br />
<br />
= Syntax =<br />
<br />
The single parameter of the function is a string describing the test to perform. The string is evaluated as a JavaScript expression which uses one or more pre-defined variables. The result is then always converted to a boolean value. Empty strings and other 'falsy' values evaluate to <tt>true</tt>. While the implementation currently simply uses the native JavaScript interpreter, only parentheses, boolean operators and numerical comparisons are guaranteed to actually work.<br />
<br />
= Variables =<br />
<br />
This section lists the supported variable names which can be passed to <tt>_.device()</tt>. The current list of variables and their values can be displayed by calling <tt>_.device()</tt> without arguments in the browser's JavaScript console. All variables are case-insensitive, and by convention are lower-case.<br />
<br />
While all variables can be used as boolean flags, most variables representing browsers and operating systems are actually numbers and can be used to check for specific browser or OS versions. The remaining browser and OS variables can become numbers in the future, too. The numbers are usually integers, i.e. they contain only the major version number.<br />
<br />
== Browsers ==<br />
<br />
* Numeric versions<br />
** <tt>ie</tt><br />
** <tt>opera</tt><br />
** <tt>safari</tt><br />
** <tt>phantomjs</tt><br />
** <tt>chrome</tt><br />
** <tt>firefox</tt><br />
* Boolean flags<br />
** <tt>webkit</tt><br />
** <tt>chromeios</tt><br />
** <tt>uiwebview</tt><br />
<br />
== Operating systems ==<br />
<br />
* Numeric versions<br />
** <tt>blackberry</tt><br />
** <tt>ios</tt><br />
** <tt>android</tt><br />
* Boolean flags<br />
** <tt>windowsphone</tt><br />
** <tt>macos</tt><br />
** <tt>windows</tt><br />
<br />
== Display metrics ==<br />
<br />
* <tt>small</tt> (up to 480px)<br />
* <tt>medium</tt> (481px to 1024px)<br />
* <tt>large</tt> (1025px and more)<br />
* <tt>landscape</tt><br />
* <tt>portrait</tt><br />
* <tt>retina</tt><br />
* <tt>smartphone</tt><br />
* <tt>tablet</tt><br />
* <tt>desktop</tt><br />
<br />
== Language ==<br />
<br />
The current language code is defined as a variable. To match any variant of the current language, the second part can be replaced by an asterisk. E.g. if the current language is en_US, then the following variables would be defined:<br />
<br />
* <tt>en_us</tt><br />
* <tt>en_*</tt><br />
<br />
== Miscellaneous ==<br />
<br />
* <tt>touch</tt><br />
* <tt>standalone</tt><br />
* <tt>emoji</tt><br />
<br />
= Examples =<br />
<br />
The simplest example is a single variable, e.g.<br />
<pre class="language-javascript">_.device('smartphone')</pre><br />
<pre class="language-javascript">_.device('firefox')</pre><br />
or<br />
<pre class="language-javascript">_.device('de_*')</pre><br />
<br />
Workarounds for specific older browsers can be enabled by testing for a specific version, e.g.<br />
<pre class="language-javascript">_.device('ie && (ie < 11)')</pre><br />
The additional check for the correct browser is necessary because in other browsers, the variable <tt>ie</tt> evaluates to <tt>undefined</tt>, and the comparisons with numbers always return <tt>false</tt>. This may or may not be what is desired, so an explicit check for the browser is less error-prone and easier to understand.</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=Portal:AppSuite_UI/Topics&diff=19095Portal:AppSuite UI/Topics2015-02-05T11:26:04Z<p>Viktor.Pracht: Added 'Device reference'</p>
<hr />
<div>== Getting started ==<br />
* [[AppSuite:GettingStarted | Getting started developing an external app]]<br />
* [[AppSuite:Upgrade_app_using_yo | Upgrade your external app to latest App Suite version]]<br />
* [[AppSuite:UI developer primer| Skills needed to develop the UI]]<br />
* [[AppSuite:Getting started developing the UI | Getting started developing the UI]]<br />
* [[AppSuite:UI_Development_Style_Guide | UI Development Style Guide]]<br />
* [[AppSuite:Appserver | Appserver]]<br />
* [[AppSuite:Apache Configuration | Apache Configuration]]<br />
* [[AppSuite:Definition of done|Definition of done]]<br />
* [[Appsuite:UI_FAQ | Frequently asked questions]]<br />
<br />
== Upgrading apps, plugins, and themes to 7.6 ==<br />
* [[AppSuite:Upgrading_to_7_6|Upgrading to 7.6]]<br />
<br />
== Testing ==<br />
* [[AppSuite:Test basics | Lessons learned while testing]]<br />
* [[AppSuite:RunTests | Running ui tests]]<br />
* [[AppSuite:Testing_3rd-party_code | In-depth article on testing]] aimed at external developers<br />
<br />
== How-to articles ==<br />
* [[AppSuite:Action links|Understanding action links]]<br />
** [[AppSuite:Files App Actions|Adding actions to the files app]]<br />
* [[AppSuite:Date_and_time|Date and time]]<br />
* [[AppSuite:i18n | Internationalization (i18n)]]<br />
* [[AppSuite:a11y | Accessibility (a11y)]]<br />
* [[AppSuite:Mediaplayer | Mediaplayer]]<br />
* [[AppSuite:Theming | Theming]]<br />
* [[AppSuite:UI manifests explained | UI manifests explained]]<br />
* [[AppSuite:Upsell | Upsell]]<br />
* [[AppSuite:VGrid | VGrid]]<br />
* [[AppSuite:Mobile | Mobile development]]<br />
* [[AppSuite:Upsell tools| Upsell tools]]<br />
* [[AppSuite:Guided tours| Guided tours]]<br />
* [[AppSuite:Browserdetection | Browser detection with form-login]]<br />
* [[AppSuite:BackboneMiniViews | Backbone mini views]]<br />
<br />
=== Server communication ===<br />
* [[AppSuite:APIs | APIs]]<br />
* [[AppSuite:API_Factory | API Factory]]<br />
* [[AppSuite:http.js | http.js]]<br />
<br />
=== Extension points ===<br />
* [[AppSuite:Extending_the_UI_(Hands-on_introduction)| Hands-on introduction]]<br />
* [[AppSuite:Extending_the_UI | General information on extension points]]<br />
* [[AppSuite:Modifying forms by using extension points | Modifying forms]]<br />
* [[AppSuite:Extension points for calendar |extension points: Calendar]]<br />
* [[AppSuite:Extension points for contact |extension points: Contact]]<br />
* [[AppSuite:Extension points for core | extension points: Core]]<br />
* [[AppSuite:Extension points for email | extension points: E-Mail]]<br />
* [[AppSuite:Extension points for files |extension points: Files]]<br />
* [[AppSuite:Extension points for tasks |extension points: Tasks]]<br />
* [[AppSuite:Extension points for miscellaneous |extension points: Miscellaneous]]<br />
<br />
=== Writing components ===<br />
* [[AppSuite:Writing a portal plugin | Writing a portal plugin]]<br />
** [[AppSuite:Configuring portal plugins|Configuring a portal plugin]]<br />
** [[AppSuite:Using the Upsell widget|Using the Upsell widget]]<br />
* [[AppSuite:Writing a simple application | Writing a simple application]]<br />
* [[AppSuite:Writing a notification area plugin | Writing a plugin for the notification area]]<br />
* [[AppSuite:Writing a wizard | Writing a wizard]]<br />
* [[AppSuite:Capabilities | Capabilities explained]] - if you want to enable or disable your plugin<br />
<br />
== Miscellaneous articles ==<br />
* [[AppSuite:External libraries for the UI | External libraries used by the UI]]<br />
* [[AppSuite:Configuration| Configuration]]<br />
* [[AppSuite:Custom configurations| Custom configurations]]<br />
* [[AppSuite:UI build system| The UI build system]]<br />
* [[AppSuite:Embedding your settings into AppSuite settings|How to embed your own settings into the Appsuite settings page]]<br />
* [[AppSuite:Debugging the UI|Debugging the UI]]<br />
* [[AppSuite:Memory leaks (UI)|Finding memory leaks in the UI]]<br />
* [[AppSuite:Device reference|_.device() reference]]<br />
* All articles regarding the UI are filed in the category [[:Category:UI]]</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=HTTP_API&diff=18218HTTP API2014-08-01T10:11:13Z<p>Viktor.Pracht: /* Get all mails */</p>
<hr />
<div>== Introduction ==<br />
<br />
This document defines the Open-Xchange HTTP API which is used by the new AJAX GUI. The first chapter describes general definitions and conventions which apply to all server modules. All other chapters describe individual server modules.<br />
<br />
=== Low level protocol ===<br />
<br />
The client accesses the server through HTTP GET, POST and PUT requests. HTTP cookies are used for authentication and must therefore be processed and sent back by the client as specified by [http://tools.ietf.org/html/rfc6265 RFC 6265]. The HTTP API is accessible at URIs starting with <code>/ajax</code>. Each server module has a unique name and its own sub-namespace with that name below <code>/ajax</code>, e. g. all access to the module "tasks" is via URIs starting with <code>/ajax/tasks</code>.<br />
<br />
Text encoding is always UTF-8. Data is sent from the server to the client as <code>text/javascript</code> and interpreted by the client to obtain an ECMAScript object. The HTTP API uses only a small subset of the ECMAScript syntax. This subset is roughly described by the following BNF:<br />
<br />
Value ::= "null" | Boolean | Number | String | Array | Object<br />
Boolean ::= "true" | "false"<br />
Number ::= see NumericLiteral in ECMA 262 3rd edition<br />
String ::= \"([^"\n\\]|\\["\n\\])*\"<br />
Array ::= "[]" | "[" Value ("," Value)* "]"<br />
Object ::= "{}" | "{" Name ":" Value ("," Name ":" Value)* "}"<br />
Name ::= [A-Fa-f][0-9A-Fa-f_]*<br />
<br />
Numbers are the standard signed integer and floating point numbers. Strings can contain any character, except double quotes, newlines and backslashes, which must be escaped by a backslash. Control characters in strings (other than newline) are not supported. Whitespace is allowed between any two tokens. See [http://json.org JSON] and [http://www.ecma-international.org/publications/standards/Ecma-262.htm ECMA 262, 3<sup>rd</sup> edition] for the formal definition.<br />
<br />
The response body consists of an object, which contains up to four fields as described in [[#ResponseBody | Response body]]. The field <code>data</code> contains the actual payload which is described in following chapters. The fields <code>timestamp</code>, <code>error</code> and <code>error_params</code> are present when data objects are returned, if an error occurred and if the error message contains conversion specifiers, respectively. Following sections describe the contents of these fields in more detail.<br />
<br />
{| id="ResponseBody" cellspacing="0" border="1"<br />
|+ align="bottom" | Response body<br />
! Name !! Type !! Value<br />
|-<br />
| data || Value || Payload of the response.<br />
|-<br />
| timestamp || Timestamp || The latest timestamp of the returned data (see [[HTTP_API#Updates|Updates]]).<br />
|-<br />
| error || String || The translated error message. Present in case of errors.<br />
|-<br />
| error_params || Array || As o 7.4.2: Empty JSON array. Before that: Parameters for the error message that would need to be replaced in the error string (in a printf-format style).<br />
|-<br />
| error_id || String || Unique error identifier to help finding this error instance in the server logs.<br />
|-<br />
| error_desc || String || The technical error message (always English) useful for debugging the problem. Might be the same as error message if there is no more information available<br />
|-<br />
| code || String || Error code consisting of an upper-case module identifier and a four-digit message number, separated by a dash; e.g. "MSG-0012"<br />
|-<br />
| error_stack || Array || If configured (see "com.openexchange.ajax.response.includeStackTraceOnError" in 'server.properties') this field provides the stack trace of associated Java exception represented as a JSON array<br />
|-<br />
| categories || String OR Array || Either a single (String) or list (Array) of upper-case category identifiers to which the error belongs. E.g.<br />
{| cellspacing="0" border="1"<br />
| "USER_INPUT" || An error resulting from wrong or missing input from front-end (e.g. mandatory field missing).<br />
|-<br />
| "CONFIGURATION" || An error related to user/system configuration which denies requested operation.<br />
|-<br />
| "PERMISSION_DENIED" || An error related to insufficient permission settings.<br />
|-<br />
| "TRY_AGAIN" || A requested operation could not be accomplished because a needed resource is temporary down or missing (e.g. imap server rejects connection because of too many established connections).<br />
|-<br />
| "SERVICE_DOWN" || A subsystem or third party service is down and therefore does not respond (e.g. database is down).<br />
|-<br />
| "CONNECTIVITY" || The underlying socket connection is corrupt, empty or closed. Only a temporary error that does not affect the whole system.<br />
|-<br />
| "ERROR" || A programming error which was caused by incorrect program code.<br />
|-<br />
| "CONFLICT" || A concurrent modification.<br />
|-<br />
| "CAPACITY" || The requested operation could not be performed cause an underlying resource is full or busy (e.g. IMAP folder exceeds quota).<br />
|-<br />
| "TRUNCATED" || The given data could not be stored into the database because an attribute contains a too long value.<br />
|-<br />
| "WARNING" || Action was at least partially successful, but a condition occurred that merited a warning<br />
|}<br />
|-<br />
| category || Number || Maintained for legacy reasons: The numeric representation of the first category:<br />
{| cellspacing="0" border="1"<br />
| 1 || An error resulting from wrong or missing input from front-end (e.g. mandatory field missing).<br />
|-<br />
| 2 || An error strictly related to user configuration which denies requested operation.<br />
|-<br />
| 3 || An error related to insufficient permission settings.<br />
|-<br />
| 4 || A requested operation could not be accomplished because a needed resource is temporary down or missing (e.g. imap server rejects connection because of too many established connections).<br />
|-<br />
| 5 || A subsystem or third party service is down and therefore does not respond (e.g. database is down).<br />
|-<br />
| 6 || The underlying socket connection is corrupt, empty or closed. Only a temporary error that does not affect the whole system.<br />
|-<br />
| 8 || A programming error which was caused by incorrect programm code.<br />
|-<br />
| 9 || A concurrent modification.<br />
|-<br />
| 11 || The requested operation could not be performed cause an underlying resource is full or busy (e.g. IMAP folder exceeds quota).<br />
|-<br />
| 12 || The given data could not be stored into the database because an attribute contains a too long value.<br />
|-<br />
| 13 || Action was at least partially successful, but a condition occurred that merited a warning<br />
|}<br />
|}<br />
<br />
Data from the client to the server can be sent in several formats. Small amounts of data are sent as <code>application/x-www-urlencoded</code> in query parameters in the request URI. For POST requests, some or all parameters may be sent in the request body instead of in the URI using any valid encoding for POST requests. Alternatively, some requests specify that data is sent as <code>text/javascript</code> in the body of a PUT request. The format of the request body for PUT requests is the same as for sending data from the server to the client, except that the payload is sent directly, without being wrapped in another object.<br />
<br />
When updating existing data, the client sends only fields that were modified. To explicitly delete a field, the field is sent with the value <code>null</code>. For fields of type <code>String</code>, the empty string <code>""</code> is equivalent to <code>null</code>.<br />
<br />
=== Error handling ===<br />
<br />
If the session of the user times out, if the client doesn't send a session ID or if the session for the specified session ID can not be found then the server returns the above described response object, that contains an error code and an error message. If the request URI or the request body is malformed or incomplete then the server returns the reponse object with an error message, too. In case of internal server errors, especially Java exceptions, or if the server is down, it returns the HTTP status code 503, Service Unavailable. Other severe errors may return other HTTP status values.<br />
<br />
Application errors, which can be caused by a user and are therefore expected during the operation of the groupware, are reported by setting the field error in the returned object, as described in [[#ResponseBody | Response body]]. Since the error messages are translated by the client, they can not be composed of multiple variable parts. Instead, the error message can contain simplified printf()-style conversion specifications, which are replaced by elements from the array in the field error_params. If error_params is not present, no replacement occurs, even if parts of the error message match the syntax of a conversion specification.<br />
<br />
A simplified conversion specification, as used for error messages, is either of the form %s or %''n''$s, where ''n'' is a 1-based decimal parameter index. The conversion specifications are replaced from left to right by elements from error_params, starting at the first element. %s is replaced by the current element and the current index is incremented. %''n''$s is replaced by the ''n''th element and the current index is set to the (''n'' + 1)th element.<br />
<br />
Some error message contain data sizes which must be expressed in Bytes or Kilobytes etc., depending on the actual value. Since the unit must be translated, this conversion is performed by the client. Unfortunately, standard printf()-style formatting does not have a specifier for this kind of translation. Therefore, the conversion specification for sizes is the same as for normal strings, and the client has to determine which parameters to translate based on the error code. The current error codes and the corresponding size parameters are listed in [[#DataSizeParameters | Data size parameters]]<br />
<br />
{| id="DataSizeParameters" cellspacing="0" border="1"<br />
|+ align="bottom" | Data size parameters<br />
! Error code !! Parameter indices<br />
|-<br />
| AJP-0006 || 1<br />
|-<br />
| AJP-0020 || 1, 2<br />
|-<br />
| CON-0101 || 2, 3<br />
|-<br />
| FLS-0003 || 1, 2, 3<br />
|-<br />
| MSG-0065 || 1, 3<br />
|-<br />
| MSG-0066 || 1<br />
|-<br />
| NON-0005 || 1, 2<br />
|-<br />
|}<br />
<br />
<br />
=== Date and time ===<br />
<br />
Dates without time are transmitted as the number of milliseconds between 00:00 UTC on that date and 1970-01-01 00:00 UTC. Leap seconds are ignored, therefore this number is always an integer multiple of 8.64e7.<br />
<br />
Because ECMAScript Date objects have no way to explicitly specify a timezone for calculations, timezone correction must be performed on the server. Dates with time are transmitted as the number of milliseconds since 1970-01-01 00:00 UTC (again, ignoring leap seconds) plus the offset between the ''user's'' timezone and UTC at the time in question. (See the Java method java.util.TimeZone.getOffset(long)). Unless optional URL parameter <code>'''timezone'''</code> is present. Then dates with time are transmitted as the number of milliseconds since 1970-01-01 00:00 UTC (again, ignoring leap seconds) plus the offset between the ''specified'' timezone and UTC at the time in question.<br />
<br />
For some date and time values, especially timestamps, monotonicity is more important than the actual value. Such values are transmitted as the number of milliseconds since 1970-01-01 00:00 UTC, ignoring leap seconds and without timezone correction. If possible, a unique strictly monotonic increasing value should be used instead, as it avoids some race conditions described below.<br />
<br />
This specification refers to these three interpretations of the type Number as separate data types. The types are described in [[#DateAndTimeTypes | Date and time types]].<br />
<br />
{| id="DateAndTimeTypes" cellspacing="0" border="1"<br />
|+ align="bottom" | Date and time types<br />
! Type !! Time !! Timezone !! Comment<br />
|-<br />
| Date || No || UTC || Date without time.<br />
|-<br />
| Time || Yes || User || Date and time.<br />
|-<br />
| Timestamp || Yes || UTC || Timestamp or unique sequence number.<br />
|-<br />
|}<br />
<br />
=== Updates ===<br />
<br />
To allow efficient synchronization of a client with changes made by other clients and to detect conflicts, the server stores a timestamp of the last modification for each object. Whenever the server transmits data objects to the client, the response object described in [[#ResponseBody | Response body]] includes the field timestamp. This field contains a timestamp value which is computed as the maximum of the timestamps of all transmitted objects.<br />
<br />
When requesting updates to a previously retrieved set of objects, the client sends the last timestamp which belongs to that set of objects. The response contains all updates with timestamps greater than the one specified by the client. The field timestamp of the response contains the new maximum timestamp value.<br />
<br />
If multiple different objects may have the same timestamp values, then a race condition exists when an update is processed between two such objects being modified. The first, already modified object will be included in the update response and its timestamp will be the maximum timestamp value sent in the timestamp field of the response. If the second object is modified later but gets the same timestamp, the client will never see the update to that object because the next update request from the client supplies the same timestamp value, but only modifications with greater timestamp values are returned.<br />
<br />
If unique sequence numbers can't be used as timestamps, then the risk of the race condition can be at least minimized by storing timestamps in the most precise format and/or limiting update results to changes with timestamp values which are measurably smaller than the current timestamp value.<br />
<br />
=== Editing ===<br />
<br />
Editing objects is performed one object at a time. There may be multiple objects being edited by the same client simulataneously, but this is achieved by repeating the steps required for editing a single object. There is no batch edit or upload command.<br />
<br />
To edit an object, a client first requests the entire object from the server. The server response contains the timestamp field described in the previous section. For in-place editing inside a view of multiple objects, where only already retrieved fields can be changed, retrieving the entire object is not necessary, and the last timestamp of the view is used as the timestamp of each object in it.<br />
<br />
When sending the modified object back to the server, only modified fields need to be included in the sent object. The request also includes the timestamp of the edited object. The timestamp is used by the server to ensure that the object was not edited by another client in the meantime. If the current timestamp of the object is greater than the timestamp supplied by the client, then a conflict is detected and the field error is set in the response. Otherwise, the object gets a new timestamp and the response to the client is empty.<br />
<br />
If the client displays the edited object in a view together with other objects, then the client will need to perform an update of that view immediately after successfully uploading an edited object.<br />
<br />
=== File uploads ===<br />
<br />
File uploads are made by sending a POST request that submits both the file and the needed fields as parts of a request of content-type “multipart/form-data” or “multipart/mixed”. The file metadata are stored in a form field “file” (much like an <input type=”file” name=”file” /> would do). In general a call that allows file uploads via POST will have a corresponding call using PUT to send object data. The JSON-encoded object-data that is send as the body of a corresponding PUT call is, when performed as a POST with file uploads, put into the request parameter “json”.<br />
<br />
Since the upload is performed directly by the browser and is not an Ajax call, the normal callback mechanism for asynchronous Javascript calls cannot be used to obtain the result. For this reason the server responds to these POST calls with a complete HTML page that performs the callback and should not be displayed to the user. The HTML response is functionally equivalent to:<br />
<br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html><br />
<head><br />
<META http-equiv="Content-Type" content=\"text/html; charset=UTF-8\"><br />
<script type="text/javascript"><br />
(parent["callback_<b>action</b>"] || window.opener && window.opener["callback_<b>action</b>"])<br />
(<b>{json}</b>)<br />
</script><br />
</head><br />
</html><br />
<br />
The placeholders <code>{json}</code> is replaced by the response with the timestamp that would be expected from the corresponding PUT method. The placeholder <code>action</code> is replaced by the value of the parameter <code>action</code> of the request (except for the import bundle, which is named "import" instead of the action name for legacy purposes). The content-type of the answer is <code>text/html</code>.<br />
<br />
Non-browser clients don't need to interpret HTML or JavaScript. The JSON data can be recognized by the outermost <code>({</code> and <code>})</code>, where the inner braces are part of the JSON value. For example, the regular expression <code>\((\{.*\})\)</code> captures the entire JSON value in its first capturing group.<br />
<br />
=== Documentation conventions ===<br />
<br />
The rest of this document describes all available requests for each module. A module usually supports several different requests, which are differentiated by the used HTTP method, URI path and supplied URI parameters. The description of each method generally contains the following elements:<br />
* the HTTP method followed by the request URI, inclusing the URI parameter action, which is used to differentiate methods,<br />
* a list of URI parameters which can or must be supplied by the client,<br />
* for PUT requests, content of the request body,<br />
* "Response with timestamp:"if the timestamp field is required in the response body or simply "Response:" if not,<br />
* content of the response payload, unless it is supposed to be empty.<br />
<br />
=== Common object data ===<br />
<br />
This table contains common fields which apply for any module's data type and is referenced throughout this document whenever a module's data type is described.<br />
<br />
{| id="CommonObjectData" cellspacing="0" border="1"<br />
|+ align="bottom" | Common object data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 1 || id || String || Object ID<br />
|-<br />
| 2 || created_by || String || User ID of the user who created this object.<br />
|-<br />
| 3 || modified_by || String || User ID of the user who last modified this object.<br />
|-<br />
| 4 || creation_date || Time || Date and time of creation.<br />
|-<br />
| 5 || last_modified || Time || Date and time of the last modification.<br />
|-<br />
| 20 || folder_id || String || Object ID of the parent folder.<br />
|-<br />
| 100 || categories || String || String containing comma separated the categories. Order is preserved. Changing the order counts as modification of the object. Not present in folder objects.<br />
|-<br />
| 101 || private_flag || Boolean || Overrides folder permissions in shared private folders: When true, this object is not visible to anyone except the owner. Not present in folder objects.<br />
|-<br />
| 102 || color_label || Number || Color number used by Outlook to label the object. The assignment of colors to numbers is arbitrary and specified by the client. The numbers are integer numbers between 0 and 10 (inclusive). Not present in folder objects.<br />
|-<br />
| 104 || number_of_attachments || Number || Number of attachments <br />
|-<br />
| 105 || lastModifiedOfNewestAttachmentUTC || Time || Date and time of the newest attachment written with UTC time zone.<br />
|}<br />
<br />
== Module "login" ==<br />
<br />
The login module is used to obtain a session from the user's login credentials. To understand the details of the different login methods, see the article titled "[[Login variations]]".<br />
<br />
=== Login ===<br />
<br />
POST <code>/ajax/login?action=login</code><br />
<br />
Parameters:<br />
* <code>name</code> – The login name.<br />
* <code>password</code> – The password.<br />
* <code>authId</code> (optional) – Identifier for tracing every single login request passed between different systems in a cluster. The value should be some token that is unique for every login request. This parameter must be given as URL parameter and not inside the body of the POST request.<br />
* <code>client</code> (optional) – Identifier of the client using the HTTP/JSON interface. This is for statistic evaluations what clients are used with Open-Xchange.<br />
* <code>version</code> (optional) – Used version of the HTTP/JSON interface client.<br />
* <code>clientIP</code> (optional) – IP address of the client host for that the session is created. If this parameter is not specified the IP address of the HTTP client doing this request is used.<br />
* <code>clientUserAgent</code> (optional) – Value of the User-Agent header of the client host for that the session is created. If this parameter is not specified the User-Agent of the current HTTP client doing this request is used.<br />
<br />
Response: A JSON object containing the session ID used for all subsequent requests. Additionally a random token is contained to be used for the Easy Login method.<br />
<br />
=== Form Login (since 6.20) ===<br />
<br />
POST <code>/ajax/login?action=formlogin</code><br />
<br />
This request implements a possible login to the web frontend by only using a simple HTML form. An example for such a form can be found in the backend's documentation folder (<code>/usr/share/doc/open-xchange</code>) under <code>examples/login.html</code>.<br />
<br />
Parameters:<br />
* <code>login</code> – The login name.<br />
* <code>password</code> – The password.<br />
* <code>authId</code> – Identifier for tracing every single login request passed between different systems in a cluster. The value should be some token that is unique for every login request. This parameter must be given as URL parameter and not inside the body of the POST request.<br />
* <code>client</code> – Identifier of the client using the HTTP/JSON interface. This is for statistic evaluations what clients are used with Open-Xchange. If the autologin request should work the client must be the same as the client sent by the UI in the normal login request.<br />
* <code>version</code> – Used version of the HTTP/JSON interface client.<br />
* <code>autologin</code> – True or false. True tells the UI to issue a store request for the session cookie. This store request is necessary if you want the autologin request not to fail.<br />
* <code>uiWebPath</code> (optional) – Defines another path on the web server where the UI is located. If this parameter is not defined the configured default of the backend is used.<br />
* <code>clientIP</code> (optional) – IP address of the client host for that the session is created. If this parameter is not specified the IP address of the HTTP client doing this request is used.<br />
* <code>clientUserAgent</code> (optional) – Value of the User-Agent header of the client host for that the session is created. If this parameter is not specified the User-Agent of the current HTTP client doing this request is used.<br />
<br />
Response: A redirect to the web UI. The URL of the web UI is either taken from the given parameter or from the configured default of the backend.<br />
<br />
For a complete description of the FormLogin-Process please see [[FormLogin|this documentation]]<br />
<br />
=== Token Login (since 7.0.1) ===<br />
<br />
POST <code>/ajax/login?action=tokenLogin</code><br />
<br />
This request allows every possible client to create a very short living session. This session can then be transferred to any other client preferably a browser entering then the normal web interface. Then the sessions life time will be extended equally to every other session.<br />
<br />
Compared to the login mechanism using the random token, this request is more secure because two tokens are used. One of these tokens is only known to the client and one is generated by the server. Only the combination of both tokens allows to use the session. The combination of both tokens must be done by the client creating the session.<br />
<br />
Parameters:<br />
* <code>login</code> – The login information.<br />
* <code>password</code> – The password.<br />
* <code>clientToken</code> – Client side identifier for accessing the session later. The value should be some token that is unique for every login request.<br />
* <code>authId</code> – Identifier for tracing every single login request passed between different systems in a cluster. The value should be some token that is unique for every login request. This parameter must be given as URL parameter and not inside the body of the POST request.<br />
* <code>client</code> – Identifier of the client using the HTTP/JSON interface. This is for statistic evaluations what clients are used with Open-Xchange. If the autologin request should work the client should be the same as the client sent by the UI in the normal login request. For security considerations it can become necessary to define here the correct client that will use the session.<br />
* <code>version</code> – Version of the HTTP/JSON interface client. Only for statistic evaluations.<br />
* <code>autologin</code> – True or false. True tells the UI to issue a store request for the session cookie. This store request is necessary if you want the autologin request not to fail. This must be enabled on the server and a client can test with the autologin request if it is enabled or not.<br />
* <code>uiWebPath</code> (optional) – Defines another path on the web server where the UI is located. If this parameter is not defined the configured default of the backend is used.<br />
* <code>clientIP</code> (optional) – IP address of the client host for that the session is created. If this parameter is not specified the IP address of the HTTP client doing this request is used. Currently the IP address may change when using the session with both tokens. This can be disabled in future releases for security considerations.<br />
* <code>clientUserAgent</code> (optional) – Value of the User-Agent header of the client host for that the session is created. If this parameter is not specified the User-Agent of the current HTTP client doing this request is used. Currently the User-Agent may change when using the session. This can be disabled in future releases for security considerations.<br />
<br />
<br />
Response: A redirect to the web UI. The URL of the web UI is either taken from the given parameter or from the configured default of the backend. This redirect will only contain the server side token. The client side token sent in the request must be appended by the client creating the session. The final URL must have the form <code style="white-space: nowrap"><var>redirect_URL</var>&amp;clientToken=<var>token</var></code>. Both tokens are necessary to use the session and both tokens must match. Otherwise the session is terminated.<br />
<br />
=== Tokens (since 7.0.1) ===<br />
<br />
POST <code>/ajax/login?action=tokens</code><br />
<br />
This request allows clients to access a session created with the [[#Token_Login_.28since_7.0.1.29 | tokenLogin]] request. When accessing the session its life time is extended equally to every other session.<br />
<br />
Parameters:<br />
* <code>serverToken</code> – Server side identifier for accessing the session. This identifier was created by the server and is contained in the tokenLogin response.<br />
* <code>clientToken</code> – Client side identifier for accessing the session. This identifier was created by the client and passed within the POST data of the tokenLogin request.<br />
* <code>client</code> – Identifier of the client using the HTTP/JSON interface. Currently this request allows to change the client identifier for the session. This eases creating the session because the identifier of the client using the session must not be known. For security considerations it can become necessary to drop this parameter.<br />
<br />
<br />
Response: A JSON object conform to the normal [[#ResponseBody | response body]] contrary to the JSON object of the normal login request. This JSON object contains the session identifier, the login, the identifier and the locale of the user.<br />
<br />
=== Logout ===<br />
<br />
GET <code>/ajax/login?action=logout</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
=== Refresh secret cookie (since 6.18.2) ===<br />
<br />
GET <code>/ajax/login?action=refreshSecret</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
=== Refresh auto-login cookie ===<br />
<br />
GET <code>/ajax/login?action=store</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
=== Redirect ===<br />
<br />
GET <code>/ajax/login;jsessionid=1157370816112.OX1?action=redirect</code><br />
<br />
'''SECURITY WARNING!''' Utilizing this request is '''INSECURE'''! This request allows to access a session with a single one time token. This one time token may be delivered to the wrong client if the AJP protocol has an error or Apache or the load balancer make a mistake. This will cause a wrong user to be in a wrong session. '''IMMEDIATELY''' consider not to use this request anymore. You have been warned. Use instead the FormLogin that does not need to use the redirect request.<br />
<br />
Parameters:<br />
* <code>random</code> – A session random token to jump into the session. This random token is part of the login response. Only a very short configurable time after the login it is allowed to jump into the session with the random token.<br />
* <code>client</code> (optional) – The client can be defined here newly if it is not correct on the login request itself.<br />
* <code>store</code> (optional) – Tells the UI to do a store request after login to be able to use autologin request.<br />
* <code>uiWebPath</code> (optional) – The optional path on the webserver to the UI. If this parameter is not given the configured uiWebPath is used.<br />
<br />
=== Change IP ===<br />
<br />
The following request is especially for integration with systems located in the providers infrastructure. If those systems create a session with the following request the client host IP address in the session can be changed. The IP check for following requests will be done using this newly set client host IP address.<br />
<br />
POST <code>/ajax/login?action=changeip</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>clientIP</code> – New IP address of the client host for the current session.<br />
<br />
Response: A JSON object containing the string "1" as data attribute.<br />
<br />
=== Redeem Token (since 7.4.0)===<br />
<br />
POST <code>/ajax/login?action=redeemToken</code><br />
<br />
Parameters:<br />
* <code>token</code> – The token created with [[#Get_a_login_token | acquireToken]].<br />
* <code>authId</code> – Identifier for tracing every single login request passed between different systems in a cluster. The value should be some token that is unique for every login request. This parameter must be given as URL parameter and not inside the body of the POST request. <br />
* <code>client</code> – Identifier of the client using the HTTP/JSON interface. The client must identifier must be the same for each request after creating the login session. <br />
* <code>secret</code> – The value of the secret string for token logins. This is configured through the tokenlogin-secrets configuration file.<br />
<br />
Response: A JSON object containing the session ID used for all subsequent requests. Additionally a random token is contained to be used for the Easy Login method. If configured within tokenlogin-secrets configuration file even the user password will be returned.<br />
<br />
== Module "config" ==<br />
<br />
The config module is used to retrieve and set user-specific configuration. The configuration is stored in a tree. Each node of the tree has a name and a value. The values of leaf nodes are strings which store the actual configuration data. The values of inner nodes are defined recursively as objects with one field for each child node. The name and the value of each field is the name and the value of the corresponding child node, respectively.<br />
<br />
The namespace looks like the following:<br />
<br />
* <code>/ajax/config/</code><br />
** <code>gui</code> – A string containing GUI-specific settings (currently, it is a huge [[#Low_level_protocol | JSON]] object).<br />
** <code>fastgui</code> - A string containing GUI-specific settings. This is a JSON object that must be kept small for performance.<br />
** <code>context_id</code> - the unique identifier of the context (read-only, added 2008-01-28).<br />
** <code>cookielifetime</code> - the cookie life time in seconds or <code>-1</code> for session cookie (read-only, added 2010-11-16).<br />
** <code>identifier</code> – the unique identifier of the user (read-only).<br />
** <code>contact_id</code> – the unique identifier of the contact data of the user (read-only).<br />
** <code>language</code> – the configured language of the user.<br />
** <code>timezone</code> – the configured timezone of the user.<br />
** <code>availableTimeZones</code> – a JSON object containing all available time zones. The key is the time zone identifier and the value contains its name in users language. (read-only, added 2010-07-08/v6.18).<br />
** <code>calendarnotification</code> - send a mail notification for appointments (deprecated since 2008-12-11)<br />
** <code>tasknotification</code> - send a mail notification for tasks (deprecated since 2008-12-11)<br />
** <code>reloadTimes</code> - Selectable times for GUI reload<br />
** <code>serverVersion</code> - Version string of the server.<br />
** <code>currentTime</code> - User timezone specific long of the current server time.<br />
** <code>maxUploadIdleTimeout</code> - Timeout after that idle uploads are deleted.<br />
** <code>folder/</code> – the standard folder of the user<br />
*** <code>tasks</code> – the standard task folder (read-only)<br />
*** <code>calendar</code> – the standard calendar folder (read-only)<br />
*** <code>contacts</code> – the standard contacts folder (read-only)<br />
*** <code>infostore</code> – the private infostore folder (read-only, since v6.20.1)<br />
*** <code>eas</code> – whether EAS folder selection is enabled (read-only)<br />
** <code>mail/</code> – settings for the email module (deprecated 2008-04-29)<br />
*** <code>addresses</code> – all email addresses of the user including the primary address (read-only, deprecated 2008-04-29)<br />
*** <code>defaultaddress</code> – primary email address of the user (read-only, deprecated 2008-04-29)<br />
*** <code>sendaddress</code> – one email address out of the addresses list that are email sent with. (deprecated 2008-04-29)<br />
*** <code>folder/</code> – the standard email folders (read-only, deprecated 2008-04-29)<br />
**** <code>inbox</code> – identifier of the folder that gets all incoming mails (read-only, deprecated 2008-04-29)<br />
**** <code>drafts</code> – identifier of the folder with the mail drafts (read-only, deprecated 2008-04-29)<br />
**** <code>trash</code> – identifier of the folder with the deleted mails (read-only, deprecated 2008-04-29)<br />
**** <code>spam</code> – identifier of the folder with the spam mails (read-only, deprecated 2008-04-29)<br />
**** <code>sent</code> – identifier of the folder with the sent mails (read-only, deprecated 2008-04-29)<br />
*** <code>htmlinline</code> – activate inlining of HTML attachments. (deprecated 2008-04-29)<br />
*** <code>colorquote</code> – color quoted lines. (deprecated 2008-04-29)<br />
*** <code>emoticons</code> – display emoticons as graphics. (deprecated 2008-04-29)<br />
*** <code>harddelete</code> – delete emails at once. (deprecated 2008-04-29)<br />
*** <code>inlineforward</code> – forward messages as inline or attachment. (deprecated 2008-04-29)<br />
*** <code>vcard</code> – attach vcard when sending mails. (deprecated 2008-04-29)<br />
*** <code>notifyonreadack</code> – notify on read acknowledgement. (deprecated 2008-04-29)<br />
*** <code>msgpreview</code> – show a message preview. (deprecated 2008-04-29)<br />
*** <code>ignorereplytext</code> (deprecated 2008-04-29)<br />
*** <code>nocopytosent</code> – don't put a copy to the sent folder when sending mails. (deprecated 2008-04-29)<br />
*** <code>spambutton</code> - Spam Button should be displayed in GUI or not. (deprecated 2008-04-29)<br />
** <code>participants</code><br />
*** <code>autoSearch</code> - If a search for all users, groups and resources when participant selection dialog is opened. (read-only, added 2008-10-09/SP5)<br />
*** <code>maximumNumberParticipants</code> – Defines the maximum number of participants for appointments and tasks. (read-only, added 2008-10-20/SP5)<br />
*** <code>showWithoutEmail</code> - If external participants without email should be shown.<br />
*** <code>showDialog</code> – Enables participant selection dialog for appointments and tasks. (read-only, added 2008-04-30/SP4)<br />
** <code>availableModules</code> – Contains a JSON array listing all enabled modules for a user. GUI loads Plugins through this list. To get your plugin listed here, create a subtree below <code>modules/</code> without a <code>module</code> subelement or with a subelement containing <code>true</code> (read-only, added 2008-02-25)<br />
** <code>minimumSearchCharacters</code> – Minimum number of characters a search pattern must have to prevent large responses and slow queries. (read-only, added 2008-10-20/SP5)<br />
** <code>modules</code><br />
*** <code>portal</code><br />
**** <code>gui</code> GUI settings for portal module<br />
**** <code>module</code><br />
*** <code>mail</code><br />
**** <code>addresses</code> – all email addresses of the user including the primary address (read-only, added 2008-02-25)<br />
**** <code>appendmailtext</code> – (added 2008-02-25)<br />
**** <code>allowhtmlimages</code> – Alters default setting whether external images contained in HTML content are allowed or not (added 2008-05-27)<br />
**** <code>colorquoted</code> – color quoted lines (added 2008-02-25)<br />
**** <code>contactCollectFolder</code> – contact folder id to save mail addresses from sent mails (added 2008-10-16)<br />
**** <code>contactCollectEnabled</code> – switch contact collection on/off (added 2008-10-16)<br />
**** <code>contactCollectOnMailAccess</code> – enables/disables contact collection for incoming mails. Default is true. (added 2009-09-24)<br />
**** <code>contactCollectOnMailTransport</code> – enables/disables contact collection for outgoing mails. Default is true. (added 2009-09-24)<br />
**** <code>defaultaddress</code> – primary email address of the user (read-only, added 2008-02-25)<br />
**** <code>deletemail</code> – delete emails or move to trash (added 2008-02-25)<br />
**** <code>emoticons</code> – display emoticons as graphics (added 2008-02-25)<br />
**** <code>defaultFolder</code><br />
***** <code>drafts</code> – identifier of the folder with the mail drafts (read-only, added 2008-02-25)<br />
***** <code>inbox</code> – identifier of the folder that gets all incoming mails (read-only, added 2008-02-25)<br />
***** <code>sent</code> – identifier of the folder with the sent mails (read-only, added 2008-02-25)<br />
***** <code>spam</code> – identifier of the folder with the spam mails (read-only, added 2008-02-25)<br />
***** <code>trash</code> – identifier of the folder with the deleted mails (read-only, added 2008-02-25)<br />
**** <code>forwardmessage</code> – forward messages as inline or attachment (added 2008-02-25)<br />
**** <code>gui</code> GUI settings for mail module<br />
**** <code>inlineattachments</code> – activate inlining of HTML attachments (added 2008-02-25)<br />
**** <code>linewrap</code> – (added 2008-02-25)<br />
**** <code>module</code> – if mail module is enabled or not (added 2008-02-25)<br />
**** <code>phishingheaders</code> – header(s) identifying phishing headers (added 2008-05-27)<br />
**** <code>replyallcc</code> – put all recipients on reply all into CC (added 2008-12-16/SP5)<br />
**** <code>sendaddress</code> – one email address out of the addresses list that are email sent with (added 2008-02-25)<br />
**** <code>spambutton</code> – Spam Button should be displayed in GUI or not (added 2008-02-25)<br />
**** <code>vcard</code> – attach vcard when sending mails (added 2008-02-25)<br />
*** <code>calendar</code><br />
**** <code>calendar_conflict</code><br />
**** <code>calendar_freebusy</code><br />
**** <code>calendar_teamview</code><br />
**** <code>gui</code> GUI settings for the calendar module<br />
**** <code>module</code><br />
**** <code>notifyNewModifiedDeleted</code> receive mail notification for new, modified or deleted appointments (added 2008-12-11/SP5)<br />
**** <code>notifyAcceptedDeclinedAsCreator</code> receive mail notification for accepted or declined appointments created by the user (added 2008-12-11/SP5)<br />
**** <code>notifyAcceptedDeclinedAsParticipant</code> receive mail notification for accepted or declined appointments that the user participates (added 2008-12-11/SP5)<br />
**** <code>defaultStatusPrivate</code> Default status for new appointments in private folders, where the user is participant. This does not affect appointments created by this user, which always have the status "accepted". The status are described in [[#UserParticipantObject | User participant object]]. Default is 0:none (added 2009-07-20/6.12)<br />
**** <code>defaultStatusPublic</code> Default status for new appointments in public folders, where the user is participant. This does not affect appointments created by this user, which always have the status "accepted". The status are described in [[#UserParticipantObject | User participant object]]. Default is 0:none (added 2009-07-20/6.12)<br />
*** <code>contacts</code><br />
**** <code>gui</code> GUI settings for the contacts module<br />
**** <code>mailAddressAutoSearch</code> – Define if a search is triggered when the recipient selection dialog is opened or the folder is changed. (read-only, added 2008-10-20/SP5)<br />
**** <code>module</code> True if the contact module is enabled for the current user, false otherwise.<br />
**** <code>singleFolderSearch</code> – True if the current user is allowed to search for contacts only in a single folder. False if contact searches across all folders are allowed. (read-only, added 2009-02-04/SP5 U1)<br />
**** <code>characterSearch</code> – True if the side bar for searching for contacts by a start letter should be displayed. False if the side bar should be hidden. (read-only, added 2009-05-29/6.10)<br />
**** <code>allFoldersForAutoComplete</code> – true if an auto complete search may omit the folder identifier array and search for contacts in all readable folders. This is configured through the contact.properties configuration file. (read-only, added 2010-07-22/v6.18.0)<br />
*** <code>tasks</code><br />
**** <code>gui</code> GUI settings for the tasks module<br />
**** <code>module</code><br />
**** <code>delegate_tasks</code><br />
**** <code>notifyNewModifiedDeleted</code> receive mail notification for new, modified or deleted tasks (added 2008-12-11/SP5)<br />
**** <code>notifyAcceptedDeclinedAsCreator</code> receive mail notification for accepted or declined tasks created by the user (added 2008-12-11/SP5)<br />
**** <code>notifyAcceptedDeclinedAsParticipant</code> receive mail notification for accepted or declined taks that the user participates (added 2008-12-11/SP5)<br />
*** <code>infostore</code><br />
**** <code>gui</code> GUI settings for the infostore module<br />
**** <code>folder</code> – the standard infostore folders (read-only, since 7.6.0)<br />
***** <code>trash</code> – identifier of the default infostore trash folder (read-only, since 7.6.0)<br />
**** <code>module</code><br />
*** <code>interfaces</code><br />
**** <code>ical</code><br />
**** <code>vcard</code><br />
**** <code>syncml</code><br />
*** <code>folder</code><br />
**** <code>gui</code> UI settings for the folder tree<br />
**** <code>public_folders</code><br />
**** <code>read_create_shared_folders</code><br />
**** <code>tree</code> – Selected folder tree, the user wants to use. Currents trees are 0 for the known OX folder tree and 1 for the new virtual folder tree. (added 2010-04-09/6.18)<br />
*** <code>com.openexchange.extras</code><br />
**** <code>module</code> – Extras link in the configuration (read only, added 2008-04-29)<br />
*** <code>com.openexchange.user.passwordchange</code><br />
**** <code>module</code> – Will load Plug-In which allows to change the Password within the users configuration (read only, added 2008-07-09)<br />
*** <code>com.openexchange.user.personaldata</code><br />
**** <code>module</code> – Will load Plug-In which allows to edit personal contact information within the users configuration (read only, added 2008-07-09)<br />
*** <code>com.openexchange.group</code><br />
**** <code>enabled</code> – Specifies whether the user is allowed to edit groups and loads the corresponding Plug-In. (read only, added 2008-08-08)<br />
*** <code>com.openexchange.resource</code><br />
**** <code>enabled</code> – Specifies whether the user is allowed to edit resources and loads the corresponding Plug-In. (read only, added 2008-08-08)<br />
*** <code>com.openexchange.publish</code><br />
**** <code>enabled</code> – Specifies whether the user is allowed to publish items. (read only, added 2009-05-27)<br />
*** <code>com.openexchange.subscribe</code><br />
**** <code>enabled</code> – Specifies whether the user is allowed to subscribe sources. (read only, added 2009-05-27)<br />
*** <code>olox20</code><br />
**** <code>active</code> – Tells the UI if the user is allowed to use the OXtender for Microsoft Outlook 2. (read only, added 2011-03-15/6.20)<br />
**** <code>module</code> – Is set to false to prevent the UI from trying to load a plugin. (read only, added 2011-03-15/6.20)<br />
***<code>com.openexchange.oxupdater</code><br />
****<code>module</code> – Is true if the OXUpdater package is installed and started. (read only, added 2011-06-01/6.20)<br />
****<code>active</code> – Is true if the user is allowed to download the OXUpdater. Otherwise it's false. (read only, added 2011-06-01/6.20)<br />
***<code>com.openexchange.passwordchange</code><br />
**** <code>showStrength</code> – Show a widget, which displays the current passwort Strength while entering. (default: false)<br />
**** <code>minLength</code> – The minimum length of an entered password. (default: 4)<br />
**** <code>maxLength</code> – The maximum length of an entered password. 0 for unlimited. (default: 0)<br />
**** <code>regexp</code> – Defines the class of allowed special characters as Regular Expression. (default: [^a-z0-9])<br />
**** <code>special</code> – Shows an example of allowed special characters to the user. Should be a subset of "regexp" in a human readable format. (default: $, _, or %) <br />
<br />
=== Get configuration data ===<br />
<br />
GET <code>/ajax/config/path</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: Value of the node specified by path.<br />
<br />
=== Set configuration data ===<br />
<br />
PUT <code>/ajax/config/path</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: The new value of the node specified by path.<br />
<br />
== Module "folders" ==<br />
<br />
The folders module is used to access the OX folder structure.<br />
<br />
=== Special System Folders ===<br />
<br />
Folders with some kind of special.<br />
<br />
{| cellspacing="0" border="1"<br />
! ID !! Type !! Description<br />
|-<br />
| 6 || contacts || System Users<br />
|}<br />
<br />
=== Get root folders ===<br />
<br />
GET <code>/ajax/folders?action=root</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Response: An array with data for all folders at the root level of the folder structure. Each array element describes one folder and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="CommonFolderData" cellspacing="0" border="1"<br />
|+ align="bottom" | Common folder data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 1 || id || String || Object ID<br />
|-<br />
| 2 || created_by || String || User ID of the user who created this object.<br />
|-<br />
| 3 || modified_by || String || User ID of the user who last modified this object.<br />
|-<br />
| 4 || creation_date || Time || Date and time of creation.<br />
|-<br />
| 5 || last_modified || Time || Date and time of the last modification.<br />
|-<br />
| 6 || last_modified_utc || Timestamp || Timestamp of the last modification. Note that the type is Timestamp, not Time. See [[#Date and time]] for details. (added 2008-10-17, with SP5, temporary workaround)<br />
|-<br />
| 20 || folder_id || String || Object ID of the parent folder.<br />
|}<br />
<br />
{| id="DetailedFolderData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed folder data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 300 || title || String || Name of this folder.<br />
|-<br />
| 301 || module || String || Name of the module which implements this folder; e.g. "tasks", "calendar", "contacts", "infostore", or "mail"<br />
|-<br />
| 302 || type || Number || Type of folder:<br />
{| cellspacing="0" border="1"<br />
| 1 || private<br />
|-<br />
| 2 || public<br />
|-<br />
| 3 || shared<br />
|-<br />
| 5 || system folder<br />
|-<br />
| 16 || trash<br />
|}<br />
|-<br />
| 304 || subfolders || Boolean || true if this folder has subfolders.<br />
|-<br />
| 305 || own_rights || Number or String || Permissions which apply to the current user, as described either in [[#PermissionFlags | Permission flags]] or in RFC 2086.<br />
|-<br />
| 306 || permissions || Array || Each element is an object described in [[#PermissionObject | Permission object]].<br />
|-<br />
| 307 || summary || String || Information about contained objects.<br />
|-<br />
| 308 || standard_folder || Boolean || Indicates whether or not folder is marked as a default folder (only OX folder)<br />
|-<br />
| 309 || total || Number || The number of objects in this Folder.<br />
|-<br />
| 310 || new || Number || The number of new objects in this Folder.<br />
|-<br />
| 311 || unread || Number || The number of unread objects in this Folder.<br />
|-<br />
| 312 || deleted || Number || The number of deleted objects in this Folder.<br />
|-<br />
| 313 || capabilities || Number || Bit mask containing information about mail folder capabilites, as described in [[#Capabilities | capabilities]].<br />
|-<br />
| 314 || subscribed || Boolean || Indicates whether this folder should appear in folder tree or not.<br />
|-<br />
| 315 || subscr_subflds || Boolean || Indicates whether subfolders should appear in folder tree or not.<br />
|-<br />
| 316 || standard_folder_type || Number || Indicates the default folder type. Zero for non-default folder. See [[#DefaultTypes | Standard folder types]]<br />
|-<br />
| 317 || supported_capabilities || Array || Each element is a String identifying a supported folder capability as described in [[#SupportedCapabilities | supported capabilities]]. Only applicable for non-mail folders. Read Only, Since 7.4.0.<br />
|-<br />
| 3010 || com.openexchange.publish.publicationFlag || Boolean || Indicates whether this folder is published. Read Only, provided by the com.openexchange.publish plugin, since 6.14.<br />
|-<br />
| 3020 || com.openexchange.subscribe.subscriptionFlag || Boolean || Indicates whether this folder has subscriptions storing their content in this folder. Read Only, provided by the com.openexchange.subscribe plugin, since 6.14.<br />
|-<br />
| 3030 || com.openexchange.folderstorage.displayName || String || Provides the display of the folder's owner. Read Only, Since 6.20.<br />
|}<br />
<br />
<br />
<br />
<br />
{| id="PermissionFlags" cellspacing="0" border="1"<br />
|+ align="bottom" | Permission flags<br />
! Bits !! Value<br />
|-<br />
| 0-6 || Folder permissions:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || See the folder.<br />
|-<br />
| 2 || Create objects in the folder. '''Note''': '''Does not apply to folders of module ''system'''''.<br />
|-<br />
| 4 || Create subfolders.<br />
|-<br />
| 64 || All permissions. This is currently the same as "Create subfolders" but in the future additional permissions may be added that will be given to the user when using this value.<br />
|}<br />
The values are scalars and not bit sets. Any other than the described values should not be used. If they are used expect an exception from the backend. Every value automatically contains the access rights covered by lower values.<br>'''NOTE''': ''Create objects in the folder'' is not covered by ''Create subfolders'' if folder's module is ''system''.<br />
|-<br />
| 7-13 || Read permissions for objects in the folder:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || Read only own objects.<br />
|-<br />
| 2 || Read all objects.<br />
|-<br />
| 64 || All permissions. This is currently the same as "Read all objects" but in the future additional permissions may be added that will be given to the user when using this value.<br />
|}<br />
The values are scalars and not bit sets. Any other than the described values should not be used. If they are used expect an exception from the backend. Every value automatically contains the access rights covered by lower values.<br />
|-<br />
| 14-20 || Write permissions for objects in the folder:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || Modify only own objects.<br />
|-<br />
| 2 || Modify all objects.<br />
|-<br />
| 64 || All permissions. This is currently the same as "Modify all objects" but in the future additional permissions may be added that will be given to the user when using this value.<br />
|}<br />
The values are scalars and not bit sets. Any other than the described values should not be used. If they are used expect an exception from the backend. Every value automatically contains the access rights covered by lower values.<br />
|-<br />
| 21-27 || Delete permissions for objects in the folder:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || Delete only own objects.<br />
|-<br />
| 2 || Delete all objects.<br />
|-<br />
| 64 || All permissions. This is currently the same as "Delete all objects" but in the future additional permissions may be added that will be given to the user when using this value.<br />
|}<br />
The values are scalars and not bit sets. Any other than the described values should not be used. If they are used expect an exception from the backend. Every value automatically contains the access rights covered by lower values.<br />
|-<br />
| 28 || Admin flag:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || Every operation modifying the folder in some way requires this permission. This are e.g. changing the folder name, modifying the permissions, deleting or moving the folder.<br />
|}<br />
|}<br />
<br />
{| id="PermissionObject" cellspacing="0" border="1"<br />
|+ align="bottom" | Permission object<br />
! Name !! Type !! Value<br />
|-<br />
| bits || Number || For non-mail folders, a number as described in [[#PermissionFlags | Permission flags]].<br />
|-<br />
| rights || String || For mail folders, the rights string as defined in RFC 2086.<br />
|-<br />
| entity || Number || User ID of the user or group to which this permission applies.<br />
|-<br />
| group || Boolean || true if entity refers to a group, false if it refers to a user.<br />
|}<br />
<br />
{| id="Capabilities" cellspacing="0" border="1"<br />
|+ align="bottom" | Capabilities<br />
! Bit !! Description<br />
|-<br />
| 0 || Mailing system supports permissions.<br />
|-<br />
| 1 || Mailing system supports ordering mails by their thread reference.<br />
|-<br />
| 2 || Mailing system supports quota restrictions.<br />
|-<br />
| 3 || Mailing system supports sorting.<br />
|-<br />
| 4 || Mailing system supports folder subscription.<br />
|}<br />
<br />
{| id="DefaultTypes" cellspacing="0" border="1"<br />
|+ align="bottom" | Standard Folder Types<br />
! Bit !! Description<br />
|-<br />
| 0 || No default folder.<br />
|-<br />
| 1 || Task.<br />
|-<br />
| 2 || Calendar.<br />
|-<br />
| 3 || Contact.<br />
|-<br />
| 7 || Inbox.<br />
|-<br />
| 8 || Infostore.<br />
|-<br />
| 9 || Drafts.<br />
|-<br />
| 10 || Sent.<br />
|-<br />
| 11 || Spam.<br />
|-<br />
| 12 || Trash.<br />
|}<br />
<br />
{| id="SupportedCapabilities" cellspacing="0" border="1"<br />
|+ align="bottom" | Supported Capabilities<br />
! Name !! Description<br />
|-<br />
| permissions || Folder storage supports permissions.<br />
|-<br />
| publication || Folder storage supports folder publication.<br />
|-<br />
| quota || Folder storage supports quota restrictions.<br />
|-<br />
| sort || Folder storage supports sorting.<br />
|-<br />
| subscription || Folder storage supports folder subscription.<br />
|}<br />
<br />
=== Get subfolders ===<br />
<br />
GET <code>/ajax/folders?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>parent</code> – Object ID of a folder, which is the parent folder of the requested folders.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
* <code>all</code> – Set to <code>1</code> to list even not subscribed folders.<br />
* <code>tree</code> – The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
* <code>errorOnDuplicateName</code> – An optional flag to enable or disable (default) check for duplicate folder names within returned folder response (since v6.20.1). If a duplicate folder name is detected, an appropriate error is returned as [[#ResponseBody | response]].<br />
<br />
Response with timestamp: An array with data for all folders, which have the folder with the requested object ID as parent. Each array element describes one folder and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get path ===<br />
<br />
GET <code>/ajax/folders?action=path</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of a folder.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Response with timestamp: An array with data for all parent nodes until root folder. Each array element describes one folder and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get updated folders ===<br />
<br />
GET <code>/ajax/folders?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>parent</code> – Object ID of a folder, which is the parent folder of the requested folders.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested folders.<br />
* <code>ignore</code> (optional) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Response with timestamp: An array with data for new, modified and deleted folders. New and modified folders are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted folders (should the <code>ignore</code> parameter be ever implemented) would be identified by their object IDs as plain strings, without being part of a nested array.<br />
<br />
=== Get a folder ===<br />
<br />
GET <code>/ajax/folders?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested folder.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Response with timestamp: An object containing all data of the requested folder. The fields of the object are listed in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]]. The field id is not present. Since OX access controls are folder-based, the folder object also defines the permissions for the objects it contains. The permissions for a given user or group are defined by the object described in [[#PermissionObject | Permission object]]. The format of the actual permissions depends on the type of the folder. The permissions of mail folders are transmitted as a rights string as defined in section 3 of RFC 2086. Permissions of all other folders are transmitted as a single nonnegative integer number. The permissions for any given action on the folder or on contained objects is defined by a group of bits in the binary representation of this number. Each group of bits is interpreted as a separate number. Zero always means "no permissions". Any other values add new permissions and always include the permissions of all lower values. The individual values are described in [[#PermissionFlags | Permission flags]].<br />
<br />
=== Update a folder ===<br />
<br />
PUT <code>/ajax/folders?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated folder.<br />
* <code>timestamp</code> – Timestamp of the updated folder. If the folder was modified after the specified timestamp, then the update must fail.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Request body: Folder object as described in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]]. Only modified fields are present.<br />
<br />
=== Create a folder ===<br />
<br />
PUT <code>/ajax/folders?action=new</code><br />
<br />
Parameters:<br />
* <code>folder_id</code> – The parent folder of the newly created folder<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Request body: Folder object as described in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]]. The field id should not be present.<br />
<br />
Provided that permission is granted to create a folder, its module is bound to the limitation, that the new folder's module must be equal to parent folder's module except that:<br />
* Parent folder is one of the system folders <code>private</code>, <code>public</code>, or <code>shared</code>. Below these folders task, calendar, and contact modules are permitted.<br />
* Parent folder's module is one of task, calendar, or contact. Below this kind of folders task, calendar, and contact modules are permitted.<br />
<br />
Response: Object ID of the newly created folder.<br />
<br />
=== Delete folders ===<br />
<br />
PUT <code>/ajax/folders?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted folders.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered. <br />
* <code>hardDelete</code> - Optional, defaults to \"false\". If set to \"true\", the folders are deleted permanently. Otherwise, and if the underlying storage supports a trash folder and the folders are not yet located below the trash folder, they are moved to the trash folder.<br />
<br />
Request body: An array with object IDs of the folders that shall be deleted.<br />
<br />
Response: An array with object IDs of folders that were '''NOT''' deleted. There may be a lot of different causes for a not deleted folder: A folder has been modified in the mean time, the user does not have the permission to delete it or those permissions have just been removed, the folder does not exist, etc.<br />
<br />
=== Clearing a folder's content ===<br />
PUT <code>/ajax/folders?action=clear</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Request body: A JSON array containing the folder ID(s) whose content should be cleared. '''NOTE:''' Although the requests offers to clear multiple folders at once it is recommended to clear only one folder per request since if any exception occurs<br />
(e.g. missing permissions) the complete request is going to be aborted.<br />
<br />
Response: A JSON array containing the IDs of folders that could not be cleared due to a concurrent modification. Meaning you receive an empty JSON array if everything worked well.<br />
<br />
=== Get all visible folder of a certain module (since v6.18.2) ===<br />
PUT <code>/ajax/folders?action=allVisible</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>tree</code> – The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>content_type</code> – The desired content type (either numbers or strings; e.g. "tasks", "calendar", "contacts", "mail")<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
<br />
Request body: None<br />
<br />
Response with timestamp: A JSON object containing three fields: "private", "public, and "shared". Each field is a JSON array with data for all folders. Each folder is itself described by an array.<br />
<br />
== Module "tasks" ==<br />
<br />
The tasks module is used to access task information.<br />
<br />
=== Get all tasks ===<br />
<br />
GET <code>/ajax/tasks?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for tasks are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response with timestamp: An array with task data. Each array element describes one task and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedTaskAndAppointmentData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed task and appointment data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 200 || title || String || Short description.<br />
|-<br />
| 201 || start_date || Date or Time || Inclusive start of the event as Date for tasks and whole day appointments and Time for normal appointments. For sequencies, this date must be part of the sequence, i. e. sequencies always start at this date.<br />
|-<br />
| 202 || end_date || Date or Time || Exclusive end of the event as Date for tasks and whole day appointments and as Time for normal appointments.<br />
|-<br />
| 203 || note || String || Long description.<br />
|-<br />
| 204 || alarm || Number or Time || Specifies when to notify the participants as the number of minutes before the start of the appointment (-1 for "no alarm"). For tasks, the Time value specifies the absolute time when the user should be notified.<br />
|-<br />
| 209 || recurrence_type || Number || Specifies the type of the recurrence for a task sequence:<br />
{| cellspacing="0" border="1"<br />
| 0 || none (single event)<br />
|-<br />
| 1 || daily<br />
|-<br />
| 2 || weekly<br />
|-<br />
| 3 || monthly<br />
|-<br />
| 4 || yearly<br />
|}<br />
|-<br />
| 212 || days || Number || Specifies which days of the week are part of a sequence. The value is a bitfield with bit 0 indicating sunday, bit 1 indicating monday and so on. May be present if recurrence_type > 1. If allowed but not present, the value defaults to 127 (all 7 days).<br />
|-<br />
| 213 || day_in_month || Number || Specifies which day of a month is part of the sequence. Counting starts with 1. If the field "days" is also present, only days selected by that field are counted. If the number is bigger than the number of available days, the last available day is selected. Present if and only if recurrence_type > 2.<br />
|-<br />
| 214 || month || Number || Month of the year in yearly sequencies. 0 represents January, 1 represents February and so on. Present if and only if recurrence_type = 4.<br />
|-<br />
| 215 || interval || Number || Specifies an integer multiplier to the interval specified by recurrence_type. Present if and only if recurrence_type > 0. Must be 1 if recurrence_type = 4.<br />
|-<br />
| 216 || until || Date || Inclusive end date of a sequence. May be present only if recurrence_type > 0. The sequence has no end date if recurrence_type > 0 and this field is not present. Note: since this is a Date, the entire day after the midnight specified by the value is included.<br />
|-<br />
| 217 || notification || Boolean || If true, all participants are notified of any changes to this object. This flag is valid for the current change only, i. e. it is not stored in the database and is never sent by the server to the client.<br />
|-<br />
| 220 || participants || Array || Each element identifies a participant, user, group or booked resource as described in [[#Participant | participant table]].<br />
|-<br />
| 221 || users || Array || Each element represents a participant as described in [[#UserParticipantObject | User participant object]]. User groups are resolved and are represented by their members. Any user can occur only once.<br />
|-<br />
| 222 || occurrences || Number || Specifies how often a recurrence should appear. May be present only if recurrence_type > 0.<br />
|-<br />
| 223 || uid || String || Can only be written when the object is created. Internal and external globally unique identifier of the appointment or task. Is used to recognize appointments within iCal files. If this attribute is not written it contains an automatic generated UUID.<br />
|-<br />
| 224 || organizer || String || Contains the email address of the appointment organizer which is not necessarily an internal user. Not implemented for tasks.<br />
|-<br />
| 225 || sequence || Number || iCal sequence number. Not implemented for tasks. Must be incremented on update. Will be incremented by the server, if not set.<br />
|-<br />
| 226 || confirmations || Array || Each element represents a confirming participant as described in [[#ConfirmingParticipant | confirming participant]]. This can be internal and external user. Not implemented for tasks.<br />
|-<br />
| 227 || organizerId || Number || Contains the userIId of the appointment organizer if it is an internal user. Not implemented for tasks. (Introduced with 6.20.1)<br />
|-<br />
| 228 || principal || String || Contains the email address of the appointment principal which is not necessarily an internal user. Not implemented for tasks. (Introduced with 6.20.1)<br />
|-<br />
| 229 || principalId || Number || Contains the userIId of the appointment principal if it is an internal user. Not implemented for tasks. (Introduced with 6.20.1)<br />
|}<br />
<br />
{| id="Participant" cellspacing="0" border="1"<br />
|+ align="bottom" | Participant identifier<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || User ID<br />
|-<br />
| type || Number || Type of participant:<br />
{|<br />
| 1 || user<br />
|-<br />
| 2 || user group<br />
|-<br />
| 3 || resource<br />
|-<br />
| 4 || resource group<br />
|-<br />
| 5 || external user<br />
|}<br />
|-<br />
| mail || String || mail address of an external participant<br />
|}<br />
<br />
{| id="UserParticipantObject" cellspacing="0" border="1"<br />
|+ align="bottom" | User participant object<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || User ID. Confirming for other users only works for appointments and not for tasks.<br />
|-<br />
| display_name || String || Displayable name of the participant.<br />
|-<br />
| confirmation || Number ||<br />
{| cellspacing="0" border="1"<br />
| 0 || none<br />
|-<br />
| 1 || accepted<br />
|-<br />
| 2 || declined<br />
|-<br />
| 3 || tentative<br />
|}<br />
|-<br />
| confirmmessage || String || Confirm Message of the participant<br />
|}<br />
<br />
{| id="ConfirmingParticipant" cellspacing="0" border="1"<br />
|+ align="bottom" | Confirming participant<br />
! Name !! Type !! Value<br />
|-<br />
| type || Number || Type of participant:<br />
{|<br />
| 1 || user<br />
|-<br />
| 5 || external user<br />
|}<br />
|-<br />
| mail || String || email address of external participant<br />
|-<br />
| display_name || String || display name of external participant<br />
|-<br />
| status || Number ||<br />
{|<br />
| 0 || none<br />
|-<br />
| 1 || accepted<br />
|-<br />
| 2 || declined<br />
|-<br />
| 3 || tentative<br />
|}<br />
|-<br />
| message || String || Confirm Message of the participant<br />
|}<br />
<br />
{| id="DetailedTaskData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed task data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 300 || status || Number || Status of the task:<br />
{| cellspacing="0" border="1"<br />
| 1 || not started<br />
|-<br />
| 2 || in progress<br />
|-<br />
| 3 || done<br />
|-<br />
| 4 || waiting<br />
|-<br />
| 5 || deferred<br />
|}<br />
|-<br />
| 301 || percent_completed || Number || How much of the task is completed. An integer number between 0 and 100.<br />
|-<br />
| 302 || actual_costs|| Number || A monetary attribute to store actual costs of a task. Allowed values must be in the range -9999999999.99 and 9999999999.99.<br />
|-<br />
| 303 || actual_duration<br />
|-<br />
| 304 || after_complete || Date || Deprecated. Only present in AJAX interface. Value will not be stored on OX server.<br />
|-<br />
| 305 || billing_information<br />
|-<br />
| 307 || target_costs|| Number || A monetary attribute to store target costs of a task. Allowed values must be in the range -9999999999.99 and 9999999999.99.<br />
|-<br />
| 308 || target_duration<br />
|-<br />
| 309 || priority || Number || 1 = LOW, 2 = MEDIUM, 3 = HIGH<br />
|-<br />
| 312 || currency<br />
|-<br />
| 313 || trip_meter<br />
|-<br />
| 314 || companies<br />
|-<br />
| 315 || date_completed<br />
|}<br />
<br />
=== Get a list of tasks ===<br />
<br />
PUT <code>/ajax/tasks?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for tasks are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]].<br />
<br />
Request body: An array of with object IDs of requested tasks.<br />
<br />
Response with timestamp: An array with task data. Each array element describes one task and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get updated tasks ===<br />
<br />
GET <code>/ajax/tasks?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for tasks are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested tasks.<br />
* <code>ignore</code> – Which kinds of updates should be ignored. Omit this parameter or set it to "deleted" to not have deleted tasks identifier in the response. Set this parameter to "false" and the response contains deleted tasks identifier.<br />
<br />
Response with timestamp: An array with new, modified and deleted tasks. New and modified tasks are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted tasks would be identified by their object IDs as plain strings, without being part of a nested array.<br />
<br />
=== Get a task ===<br />
<br />
GET <code>/ajax/tasks?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested task.<br />
* <code>folder</code> – Object ID of the task's folder.<br />
<br />
Response with timestamp: An object containing all data of the requested task. The fields of the object are listed in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]]. The field id is not included.<br />
<br />
=== Update a task ===<br />
<br />
PUT <code>/ajax/tasks?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Folder Identifier through that the task is accessed. This is necessary for checking the permissions.<br />
* <code>id</code> – Object ID of the updated task.<br />
* <code>timestamp</code> – Timestamp of the updated task. If the task was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: Task object as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]]. Only modified fields are present.<br />
<br />
=== Create a task ===<br />
<br />
PUT <code>/ajax/tasks?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Task object as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]]. The field id is not present.<br />
<br />
Response: A json objekt with attribute <code>id</code> of the newly created task.<br />
<br />
=== Delete task ===<br />
<br />
PUT <code>/ajax/tasks?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted tasks.<br />
<br />
Request body: An object in the field “id” and “folder”.<br />
<br />
Response: An array with object IDs of tasks which were modified after the specified timestamp and were therefore not deleted.<br />
<br />
=== Delete tasks (since v6.22) ===<br />
<br />
PUT <code>/ajax/tasks?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted tasks.<br />
<br />
Request body: An array of objects with the fields “id” and “folder”.<br />
<br />
Response: An array with object IDs of tasks which were modified after the specified timestamp and were therefore not deleted.<br />
<br />
=== Confirm task ===<br />
<br />
PUT <code>/ajax/tasks?action=confirm</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the to confirm task.<br />
* <code>folder</code> – ID of the folder through that the task is accessed.<br />
* <code>timestamp</code> – Timestamp of the last update of the to confirm task.<br />
<br />
Request body: An object with the fields "confirmation" and "confirmmessage" as described in [[#UserParticipantObject | User participant object]].<br />
<br />
Response: Nothing, except the standard response object with empty data, the timestamp of the confirmed and thereby updated task, and maybe errors.<br />
<br />
=== Search for tasks ===<br />
<br />
PUT <code>/ajax/tasks?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified , then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Request Body: A JSON object with attributes described in [[#SearchTasks | Search tasks]]<br />
<br />
{| id="SearchTasks" cellspacing="0" border="1"<br />
|+ align="bottom" | Search tasks<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find tasks. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|-<br />
| folder || Number || (optional) Defines the folder to search for tasks in. If this is omitted in all task folders will be searched.<br />
|-<br />
| start || Date or Time || (optional) Inclusive start date for a time range the tasks should end in. If start is omitted end is ignored.<br />
|-<br />
| end || Date or Time || (optional) Exclusive end date for a time range the tasks should end in. If this parameter is omitted the time range has an open end.<br />
|}<br />
<br />
Response with timestamp: An array with matching tasks. Tasks are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
== Module "contacts" ==<br />
<br />
The contacts module is used to access contact information.<br />
<br />
=== Get all contacts ===<br />
<br />
GET <code>/ajax/contacts?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried (optional from 6.22.2 on: If not set, the contents of all visible folders are used instead).<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for contacts are defined in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (preliminary, since 6.20) – allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedContactData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed contact data<br />
! ID !! Displayed name !! Name !! Type !! Value<br />
|-<br />
| 223 || || uid || String || Can only be written when the object is created. Internal and external globally unique identifier of the contact. Is used to recognize contacts within vCard files. If this attribute is not written it contains an automatic generated UUID.<br />
|-<br />
| 500 || Display name || display_name || String<br />
|-<br />
| 501 || Given name || first_name || String || First name.<br />
|-<br />
| 502 || Sur name || last_name || String || Last name.<br />
|-<br />
| 503 || Middle name || second_name || String<br />
|-<br />
| 504 || Suffix || suffix || String<br />
|-<br />
| 505 || Title || title || String<br />
|-<br />
| 506 || Street home || street_home || String<br />
|-<br />
| 507 || Postal code home || postal_code_home || String<br />
|-<br />
| 508 || City home || city_home || String<br />
|-<br />
| 509 || State home || state_home || String<br />
|-<br />
| 510 || Country home || country_home || String<br />
|-<br />
| 511 || Birthday || birthday || Date<br />
|-<br />
| 512 || Martial status || marital_status || String<br />
|-<br />
| 513 || Number of children || number_of_children || String<br />
|-<br />
| 514 || Profession || profession || String<br />
|-<br />
| 515 || Nickname || nickname || String<br />
|-<br />
| 516 || Spouse name || spouse_name || String<br />
|-<br />
| 517 || Anniversay || anniversary || Date<br />
|-<br />
| 518 || Note || note || String<br />
|-<br />
| 519 || Department || department || String<br />
|-<br />
| 520 || Position || position || String<br />
|-<br />
| 521 || Employee type || employee_type || String<br />
|-<br />
| 522 || Room number || room_number || String<br />
|-<br />
| 523 || Street business || street_business || String<br />
|-<br />
| 524 || || internal_userid || Number<br />
|-<br />
| 525 || Postal code business || postal_code_business || String<br />
|-<br />
| 526 || City business || city_business || String<br />
|-<br />
| 527 || State business || state_business || String<br />
|-<br />
| 528 || Country business || country_business || String<br />
|-<br />
| 529 || Number of employee || number_of_employees || String<br />
|-<br />
| 530 || Sales volume || sales_volume || String<br />
|-<br />
| 531 || Tax id || tax_id || String<br />
|-<br />
| 532 || Commercial register || commercial_register || String<br />
|-<br />
| 533 || Branches || branches || String<br />
|-<br />
| 534 || Business category || business_category || String<br />
|-<br />
| 535 || Info || info || String<br />
|-<br />
| 536 || Manager's name || manager_name || String<br />
|-<br />
| 537 || Assistant's name || assistant_name || String<br />
|-<br />
| 538 || Street other || street_other || String<br />
|-<br />
| 539 || City other || city_other || String<br />
|-<br />
| 540 || Postal code other || postal_code_other || String<br />
|-<br />
| 541 || Country other || country_other || String<br />
|-<br />
| 542 || Telephone business 1 || telephone_business1 || String<br />
|-<br />
| 543 || Telephone business 2 || telephone_business2 || String<br />
|-<br />
| 544 || FAX business || fax_business || String<br />
|-<br />
| 545 || Telephone callback || telephone_callback || String<br />
|-<br />
| 546 || Telephone car || telephone_car || String<br />
|-<br />
| 547 || Telephone company || telephone_company || String<br />
|-<br />
| 548 || Telephone home 1 || telephone_home1 || String<br />
|-<br />
| 549 || Telephone home 2 || telephone_home2 || String<br />
|-<br />
| 550 || FAX home || fax_home || String<br />
|-<br />
| 551 || Cellular telephone 1 || cellular_telephone1 || String<br />
|-<br />
| 552 || Cellular telephone 2 || cellular_telephone2 || String<br />
|-<br />
| 553 || Telephone other || telephone_other || String<br />
|-<br />
| 554 || FAX other || fax_other || String<br />
|-<br />
| 555 || Email 1 || email1 || String<br />
|-<br />
| 556 || Email 2 || email2 || String<br />
|-<br />
| 557 || Email 3 || email3 || String<br />
|-<br />
| 558 || URL || url || String<br />
|-<br />
| 559 || Telephone ISDN || telephone_isdn || String<br />
|-<br />
| 560 || Telephone pager || telephone_pager || String<br />
|-<br />
| 561 || Telephone primary || telephone_primary || String<br />
|-<br />
| 562 || Telephone radio || telephone_radio || String<br />
|-<br />
| 563 || Telephone telex || telephone_telex || String<br />
|-<br />
| 564 || Telephone TTY/TDD || telephone_ttytdd || String<br />
|-<br />
| 565 || Instantmessenger 1 || instant_messenger1 || String<br />
|-<br />
| 566 || Instantmessenger 2 || instant_messenger2 || String<br />
|-<br />
| 567 || Telephone IP || telephone_ip || String<br />
|-<br />
| 568 || Telephone assostant || telephone_assistant || String<br />
|-<br />
| 569 || Company || company || String<br />
|-<br />
| 570 || || image1 || String<br />
|-<br />
| 571 || Dynamic Field 1 || userfield01 || String<br />
|-<br />
| 572 || Dynamic Field 2 || userfield02 || String<br />
|-<br />
| 573 || Dynamic Field 3 || userfield03 || String<br />
|-<br />
| 574 || Dynamic Field 4 || userfield04 || String<br />
|-<br />
| 575 || Dynamic Field 5 || userfield05 || String<br />
|-<br />
| 576 || Dynamic Field 6 || userfield06 || String<br />
|-<br />
| 577 || Dynamic Field 7 || userfield07 || String<br />
|-<br />
| 578 || Dynamic Field 8 || userfield08 || String<br />
|-<br />
| 579 || Dynamic Field 9 || userfield09 || String<br />
|-<br />
| 580 || Dynamic Field 10 || userfield10 || String<br />
|-<br />
| 581 || Dynamic Field 11 || userfield11 || String<br />
|-<br />
| 582 || Dynamic Field 12 || userfield12 || String<br />
|-<br />
| 583 || Dynamic Field 13 || userfield13 || String<br />
|-<br />
| 584 || Dynamic Field 14 || userfield14 || String<br />
|-<br />
| 585 || Dynamic Field 15 || userfield15 || String<br />
|-<br />
| 586 || Dynamic Field 16 || userfield16 || String<br />
|-<br />
| 587 || Dynamic Field 17 || userfield17 || String<br />
|-<br />
| 588 || Dynamic Field 18 || userfield18 || String<br />
|-<br />
| 589 || Dynamic Field 19 || userfield19 || String<br />
|-<br />
| 590 || Dynamic Field 20 || userfield20 || String || Contains a UUID if one was assigned (after 6.18.2)<br />
|-<br />
| 592 || || distribution_list || Array || If this contact is a distribution list, then this field is an array of objects. Each object describes a member of the list as defined in [[#DistributionListMember | Distribution list member]].<br />
|-<br />
| 594 || Number of distributionlists || number_of_distribution_list || Number<br />
|-<br />
| 596 || || number_of_images || Number<br />
|-<br />
| 597 || || image_last_modified || Timestamp<br />
|-<br />
| 598 || State other || state_other || String<br />
|-<br />
| 599 || || file_as || String<br />
|-<br />
| 601 || || image1_content_type || String<br />
|-<br />
| 602 || || mark_as_distributionlist || Boolean<br />
|-<br />
| 605 || Default address || default_address || Number<br />
|-<br />
| 606 || || image1_url || String<br />
|-<br />
| 608 || || useCount || Number || In case of sorting purposes the column 609 is also available, which places global address book contacts at the beginning of the result. If 609 is used, the order direction (ASC, DESC) is ignored.<br />
|-<br />
| 610 || || yomiFirstName || String || Kana based representation for the First Name. Commonly used in japanese environments for searchin/sorting issues. (since 6.20)<br />
|-<br />
| 611 || || yomiLastName || String || Kana based representation for the Last Name. Commonly used in japanese environments for searchin/sorting issues. (since 6.20)<br />
|-<br />
| 612 || || yomiCompany || String || Kana based representation for the Company. Commonly used in japanese environments for searchin/sorting issues. (since 6.20)<br />
|-<br />
| 613 || || addressHome || String || Support for Outlook 'home' address field. (since 6.20.1)<br />
|-<br />
| 614 || || addressBusiness || String || Support for Outlook 'business' address field. (since 6.20.1)<br />
|-<br />
| 615 || || addressOther || String || Support for Outlook 'other' address field. (since 6.20.1)<br />
|}<br />
<br />
<br />
{| id="DistributionListMember" cellspacing="0" border="1"<br />
|+ align="bottom" | Distribution list member<br />
! Name !! Type !! Value<br />
|-<br />
| id || String || Object ID of the member's contact if the member is an existing contact.<br />
|-<br />
| folder_id || String || Parent folder ID of the member's contact if the member is an existing contact (preliminary, from 6.22 on).<br />
|-<br />
| display_name || String || Display name<br />
|-<br />
| mail || String || Email address (mandatory before 6.22, afterwards optional if you are referring to an internal contact)<br />
|-<br />
| mail_field || Number || Which email field of an existing contact (if any) is used for the mail field.<br />
{| cellspacing="0" border="1"<br />
| 0 || independent contact<br />
|-<br />
| 1 || default email field (email1)<br />
|-<br />
| 2 || second email field (email2)<br />
|-<br />
| 3 || third email field (email3)<br />
|}<br />
|}<br />
<br />
=== Get a list of contacts ===<br />
<br />
PUT <code>/ajax/contacts?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for contacts are defined in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]].<br />
<br />
Request body: An array with objects. Each object contains fields “id” and “folder” of requested contacts.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a list of users ===<br />
<br />
PUT <code>/ajax/contacts?action=listuser</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for contacts are defined in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]].<br />
<br />
Request body: An array with id<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
Available with SP4<br />
<br />
=== Get updated contacts ===<br />
<br />
GET <code>/ajax/contacts?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for contacts are defined in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested contacts.<br />
* <code>ignore</code> (mandatory - should be set to "deleted") (deprecated) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
<br />
Response with timestamp: An array with new, modified and deleted contacts. New and modified contacts are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted contacts (should the <code>ignore</code> parameter be ever implemented) would be identified by their object IDs as plain strings, without being part of a nested array.<br />
<br />
=== Get a contact ===<br />
<br />
GET <code>/ajax/contacts?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested contact.<br />
* <code>folder</code> – Object ID of the contact's folder.<br />
<br />
Response with timestamp: An object containing all data of the requested contact. The fields of the object are listed in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]]. The field id is not included.<br />
<br />
=== Get contact by user ID ===<br />
<br />
GET <code>/ajax/contacts?action=getuser</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – User ID (not Object ID) of the requested user.<br />
<br />
Response with timestamp: An object containing all data of the requested contact. The fields of the object are listed in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]]. <br />
<br />
Available with SP4 package.<br />
<br />
=== Update a contact ===<br />
<br />
PUT <code>/ajax/contacts?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Folder identifier through that the contact is accessed. This is necessary for checking the permissions.<br />
* <code>id</code> – Object ID of the updated contact.<br />
* <code>timestamp</code> – Timestamp of the updated contact. If the contact was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: Contact object as described in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]]. Only modified fields are present.<br />
<br />
To remove some contact image send the image attribute set to <code>null</code>.<br />
<br />
To change or add some contact image the PUT command must be replaced with a POST command and all data must be provided within a <code>multipart/form-data</code> body. The normal request body must be placed into a form field named <code>json</code> while the image file must be placed in a file field named <code>file</code>. The response is then an HTML page as described in section [[#File_uploads | File uploads]].<br />
<br />
=== Create a contact ===<br />
<br />
PUT <code>/ajax/contacts?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Contact object as described in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]]. The field id is not included.<br />
<br />
Response: A json objekt with attribute <code>id</code> of the newly created contact.<br />
<br />
To add some contact image the PUT command must be replaced with a POST command and all data must be provided within a <code>multipart/form-data</code> body. The normal request body must be placed into a form field named <code>json</code> while the image file must be placed in a file field named <code>file</code>. The response is then an HTML page as described in section [[#File uploads | File uploads]].<br />
<br />
=== Delete a contact ===<br />
<br />
PUT <code>/ajax/contacts?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted contacts.<br />
<br />
Request body: An object with the fields “id” and “folder”.<br />
<br />
=== Delete contacts (since v6.22)===<br />
<br />
PUT <code>/ajax/contacts?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted contacts.<br />
<br />
Request body: An array of objects with the fields “id” and “folder”.<br />
<br />
=== Search contacts ===<br />
<br />
PUT <code>/ajax/contacts?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified. In case of use of column 609 (use count depending order for collected contacts with global address book) the parameter "order" ist NOT necessary and will be ignored.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (preliminary, since 6.20) – allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Request body: An Object as described in [[#SearchContacts | Search contacts]].<br />
<br />
{| id="SearchContacts" cellspacing="0" border="1"<br />
|+ align="bottom" | Search contacts<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find contacts. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves. Matching is performed against any substring of the field <code>display_name</code>.<br />
|-<br />
| startletter || String || Search contacts with the given startletter. If this field is present, the pattern is matched against the contact field which is specified by the property contact_first_letter_field on the server (default: last name). Otherwise, the pattern is matched against the display name.<br />
|-<br />
| folder || Array of Number || If a list of folder identifiers or at least a single folder identifier is given, only in that folders will be searched for contacts. This paramenter is optional but searching in all contact folders that are viewable and where objects can be read in is more expensive on that database than searching in a dedicated number of them. The possibility to provide here an array of folder identifier has been added with 6.10.<br />
|}<br />
<br />
Alternative request body: An Object as described in [[#SearchContactsAlternative | Search contacts alternative]].<br />
<br />
{| id="SearchContactsAlternative" cellspacing="0" border="1"<br />
|+ align="bottom" | Search contacts alternative<br />
! Name !! Type !! Value<br />
|-<br />
| last_name || String || Searches contacts where the last name match with the given last name.<br />
|-<br />
| first_name || String || Searches contacts where the first name match with the given first name.<br />
|-<br />
| display_name || String || Searches contacts where the display name match with the given display name.<br />
|-<br />
| email1 || String || Searches contacts where the email1 address match with the given search pattern. (requires version >= 6.12)<br />
|-<br />
| email2 || String || Searches contacts where the email2 address match with the given search pattern. (requires version >= 6.12)<br />
|-<br />
| email3 || String || Searches contacts where the email3 address match with the given search pattern. (requires version >= 6.12)<br />
|-<br />
| company || String || Searches contacts where the company match with the given search pattern. (requires version >= 6.12)<br />
|-<br />
| categories || String || Searches contacts where the categories match with the given search pattern. <br />
|-<br />
| orSearch || Boolean || If set to true, a contact is returned if any specified pattern matches at the start of the corresponding field. Otherwise, a contact is returned if all specified patterns match any substring of the corresponding field.<br />
|-<br />
| emailAutoComplete || Boolean || If set to true, results are guaranteed to contain at least one email adress and the search is performed as if orSearch were set to true. The actual value of orSearch is ignored.<br />
|-<br />
| exactMatch || Boolean || If set to true, contacts are returned where the specified patterns match the corresponding fields exactly. Otherwise, a 'startsWith' or 'substring' comparison is used based on the 'orSearch' parameter. (requires version > 6.22.1)<br />
|}<br />
<br />
Response: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Search contacts by filter (since 6.20) ===<br />
<br />
PUT <code>/ajax/contacts?action=advancedSearch</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified. <br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (preliminary, since 6.20) – allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Request body: An Object as described in [[#Module_.22search.22_.28alternative_suggestion.2C_still_preliminary.29 | Search Filter]]<br />
<br />
Response: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Search contacts by anniversary (Since 6.22.1, Preliminary) ===<br />
<br />
Find contacts whose anniversary falls into a timerange.<br />
<br />
GET <code>/ajax/contacts?action=anniversaries</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>start</code> – The lower (inclusive) limit of the requested time-range.<br />
* <code>end</code> – The upper (exclusive) limit of the requested time-range.<br />
* <code>columns</code> – The requested fields.<br />
* <code>folder</code> (optional) – Object ID of the parent folder that is searched. If not set, all visible folders are used.<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If not specified, the results are sorted ascending by their anniversary in the supplied timerange. If this parameter is specified, then the parameter order must be also specified. <br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (optional) – Allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Search contacts by birthday (Since 6.22.1, Preliminary) ===<br />
<br />
Find contacts whose birthday falls into a timerange.<br />
<br />
GET <code>/ajax/contacts?action=birthdays</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>start</code> – The lower (inclusive) limit of the requested time-range.<br />
* <code>end</code> – The upper (exclusive) limit of the requested time-range.<br />
* <code>columns</code> – The requested fields.<br />
* <code>folder</code> (optional) – Object ID of the parent folder that is searched. If not set, all visible folders are used.<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If not specified, the results are sorted ascending by their birthday in the supplied timerange. If this parameter is specified, then the parameter order must be also specified. <br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (optional) – Allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
== Module "calendar" ==<br />
<br />
The calendar module is used to access calendar data.<br />
<br />
=== Get all appointments ===<br />
<br />
GET <code>/ajax/calendar?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> (optional) – Object ID of the folder, whose contents are queried. If not specified, defaults to all calendar folders.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]].<br />
* <code>start</code> – Lower inclusive limit of the queried range as a Date. Only appointments which start on or after this date are returned.<br />
* <code>end</code> – Upper exclusive limit of the queried range as a Date. Only appointments which end before this date are returned.<br />
* <code>recurrence_master</code> – Extract the recurrence to several appointments. The default value is false so every appointment of the recurrence will be calculated.<br />
* <code>showPrivate</code> (optional) – only works in shared folders: When enabled, shows private appointments of the folder owner. Such appointments are anonymized by stripping away all information except start date, end date and recurrence information (since 6.18)<br />
<br />
Response with timestamp: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Appointment sequencies are broken up into individual appointments and each occurrence of a sequence in the requested range is returned separately. The appointments are sorted in ascending order by the field start_date.<br />
<br />
{| id="DetailedAppointmentData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed appointment data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 206 || recurrence_id || Number || Object ID of the entire appointment sequence. Present on series and change exception appointments. Equals to object identifier on series appointment and is different to object identifier on change exceptions.<br />
|-<br />
| 207 || recurrence_position || Number || 1-based position of an individual appointment in a sequence. Present if and only if recurrence_type > 0.<br />
|-<br />
| 208 || recurrence_date_position || Date || Date of an individual appointment in a sequence. Present if and only if recurrence_type > 0.<br />
|-<br />
| 210 || change_exceptions || Array || An array of Dates, representing all change exceptions of a sequence.<br />
|-<br />
| 211 || delete_exceptions || Array || An array of Dates, representing all delete exceptions of a sequence.<br />
|-<br />
| 400 || location || String || Location<br />
|-<br />
| 401 || full_time || Boolean || True if the appointment is a whole day appointment, false otherwise.<br />
|-<br />
| 402 || shown_as || Number || Describes, how this appointment appears in availability queries:<br />
{| cellspacing="0" border="1"<br />
| 1 || reserved<br />
|-<br />
| 2 || temporary<br />
|-<br />
| 3 || absent<br />
|-<br />
| 4 || free<br />
|}<br />
|-<br />
| 408 || timezone || String || Timezone<br />
|-<br />
| 410 || recurrence_start || Date || Start of a sequence without time<br />
|-<br />
| || ignore_conflicts || Boolean || Ignore soft conflicts for the new or modified appointment. This flag is valid for the current change only, i. e. it is not stored in the database and is never sent by the server to the client. <br />
|}<br />
<br />
=== Get appointment information ===<br />
<br />
GET <code>/ajax/calendar?action=has</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>start</code> – Lower inclusive limit of the queried range as a Date. Only appointments which end on or after this date are returned.<br />
* <code>end</code> – Upper exclusive limit of the queried range as a Date. Only appointments which start before this date are returned.<br />
<br />
Response is an array of booleans. Array length is the number of days. Each entry in the array corresponds with one day in the range that was queried, explaining whether there is an appointment on this day or not.<br />
<br />
=== Get a list of appointments ===<br />
<br />
PUT <code>/ajax/calendar?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]].<br />
* <code>recurrence_master</code> – Extract the recurrence to several appointments. The default value is false so every appointment of the recurrence will be calculated.<br />
<br />
Request body: An array with full object IDs (folder, id and optionally either recurrence_position or recurrence_date_position) of requested appointments.<br />
<br />
Response with timestamp: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="FullIdentifierForAnAppointment" cellspacing="0" border="1"<br />
|+ align="bottom" | Full identifier for an appointment<br />
! Name !! Type !! Value<br />
|-<br />
| id || String || Object ID<br />
|-<br />
| pos || Number || Value of the field recurrence_position, if present in the appointment.<br />
|}<br />
<br />
=== Get updated appointments ===<br />
<br />
GET <code>/ajax/calendar?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]].<br />
* <code>timestamp</code> – Timestamp of the last update of the requested appointments.<br />
* <code>start</code> (optional) – Lower inclusive limit of the queried range as a Date. Only appointments which end on or after this date are returned.<br />
* <code>end</code> (optional) – Upper exclusive limit of the queried range as a Date. Only appointments which start before this date are returned.<br />
* <code>ignore</code> (mandatory - should be set to "deleted") (deprecated) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
* <code>recurrence_master</code> – Extract the recurrence to several appointments. The default value is false so every appointment of the recurrence will be calculated.<br />
* <code>showPrivate</code> (optional) – only works in shared folders: When enabled, shows private appointments of the folder owner. Such appointments are anonymized by stripping away all information except start date, end date and recurrence information (since 6.18)<br />
<br />
Response with timestamp: An array with new, modified and deleted appointments. New and modified appointments are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted appointments (should the <code>ignore</code> parameter be ever implemented) would be identified by objects described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]] instead of arrays. Appointment sequencies are broken up into individual appointments and each modified occurrence of a sequence in the requested range is returned separately. The appointments are sorted in ascending order by the field start_date.<br />
<br />
=== Get an appointment ===<br />
<br />
GET <code>/ajax/calendar?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested appointment.<br />
* <code>folder</code> – Folder ID of the requested appointment.<br />
* <code>recurrence_position</code> (optional) – Recurrence Position requested appointment.<br />
<br />
Response with timestamp: An object containing all data of the requested appointment. The fields of the object are listed in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]]. The field id is not included.<br />
<br />
=== Update an appointment ===<br />
<br />
PUT <code>/ajax/calendar?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated appointment.<br />
* <code>folder</code> - Object ID of the appointment's folder.<br />
* <code>timestamp</code> – Timestamp of the updated appointment. If the appointment was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: Appointment object as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]]. The field recurrence_id is always present if it is present in the original appointment. The field recurrence_position is present if it is present in the original appointment and only this single appointment should be modified. The field id is not present because it is already included as a parameter. Other fields are present only if modified.<br />
<br />
=== Create an appointment ===<br />
PUT <code>/ajax/calendar?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Appointment object as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]]. The field id is not present.<br />
<br />
Response: If the appointment was created successfully, an object with the attribute <code>id</code> of the newly created appointment. If the appointment could not be created due to conflicts, the response body is an object with the field <code>conflicts</code>, which is an array of appointment objects which caused the conflict. Each appointment object which represents a resource conflict contains an additional field <code>hard_conflict</code> with the Boolean value true. If the user does not have read access to a conflicting appointment, only the fields <code>id</code>, <code>start_date</code>, <code>end_date</code>, <code>shown_as</code> and <code>participants</code> are present and the field <code>participants</code> contains only the participants which caused the conflict.<br />
<br />
=== Delete an appointment ===<br />
<br />
PUT <code>/ajax/calendar?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted appointments.<br />
<br />
Request body: The appointment object to delete. The fields for the object are described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]]. <br />
<br />
Response: An array of objects identifying the appointments which were modified after the specified timestamp and were therefore not deleted. The fields of each object are described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]].<br />
<br />
=== Delete appointments (since v6.22) ===<br />
<br />
PUT <code>/ajax/calendar?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted appointments.<br />
<br />
Request body: An array of appointment objects to delete. The fields for the object are described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]]. <br />
<br />
Response: An array of objects identifying the appointments which were modified after the specified timestamp and were therefore not deleted. The fields of each object are described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]].<br />
<br />
=== Confirm appointment ===<br />
<br />
PUT <code>/ajax/calendar?action=confirm</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the appointment to confirm.<br />
* <code>occurrence</code> – The numeric identifier of the occurrence to which the confirmation applies (in case "id" denotes a series appointment). Available with v7.6.0<br />
* <code>folder</code> – ID of the folder through which the appointment is accessed.<br />
* <code>timestamp</code> – Timestamp of the last update of the to confirmed appointment.<br />
<br />
Request body: An object with the fields "confirmation", "confirmmessage" and "id" (optional) as described in [[#UserParticipantObject | User participant object]].<br />
<br />
Response: Nothing, except the standard response object with empty data, the timestamp of the confirmed and thereby updated task, and maybe errors.<br />
<br />
=== Free & Busy ===<br />
<br />
GET <code>/ajax/calendar?action=freebusy</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> - Internal user id. Must be obtained from the contact module.<br />
* <code>type</code> - Constant for user or resource (1 for users, 3 for resources)<br />
* <code>start</code> – Lower inclusive limit of the queried range as a Date. Only appointments which end on or after this date are returned.<br />
* <code>end</code> – Upper exclusive limit of the queried range as a Date. Only appointments which start before this date are returned.<br />
<br />
Response: An array of objects identifying the appointments which lie between start and end as described.<br><br />
This objects consist of:<br />
{| id="FreeAndBusyAppointment" cellspacing="0" border="1"<br />
! Name !! Type !! Value<br />
|-<br />
| shown_as || Number || Describes, how this appointment appears in availability queries:<br />
{| cellspacing="0" border="1"<br />
| 1 || reserved<br />
|-<br />
| 2 || temporary<br />
|-<br />
| 3 || absent<br />
|-<br />
| 4 || free<br />
|}<br />
|-<br />
| start_date || Date or Time || see [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]]<br />
|- <br />
| end_date || Date or Time || see [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]]<br />
|-<br />
| id || String || Object ID<br />
|-<br />
| folder_id || String || Folder ID. Only set, if the user has the right to see the object. (added 2009-08-18/6.12) <br />
|-<br />
| full_time || Boolean || True if the appointment is a whole day appointment, not present otherwise.<br />
|}<br />
<br />
=== Search appointments ===<br />
<br />
PUT <code>/ajax/calendar?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
<br />
Request body: An Object as described in [[#SearchAppointments | Search appointments]].<br />
<br />
{| id="SearchAppointments" cellspacing="0" border="1"<br />
|+ align="bottom" | Search appointments<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find appointments. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|-<br />
| startletter || String || Search appointments with the given starting letter.<br />
|}<br />
<br />
Request body: An Object as described in [[#SearchAppointments | Search appointments]].<br />
<br />
Response: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get new appointments ===<br />
<br />
GET <code>/ajax/calendar?action=newappointments</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
* <code>start</code> – Lower inclusive limit of the queried range as a Date. Only appointments which end on or after this date are returned.<br />
* <code>end</code> – Upper exclusive limit of the queried range as a Date. Only appointments which start before this date are returned.<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified and holds a column number, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>limit</code> – limits the number of returned object to the given value.<br />
<br />
Response: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Resolve UID ===<br />
<br />
GET <code>/ajax/calendar?action=resolveuid</code><br />
<br />
Parameters<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>uid</code> – The UID to be resolved.<br />
<br />
Response: An object object with the field "id" containing the ox-object id, if existing, an error message otherwise.<br />
<br />
=== Get all Change Exceptions (Since v7.2.0) ===<br />
<br />
GET <code>/ajax/calendar?action=getChangeExceptions</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object id of the appointment series.<br />
* <code>folder</code> – Folder ID of the requested appointments. <br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier.<br />
<br />
Response with timestamp: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
== Module "mail" ==<br />
<br />
The mail module is used to access mail data.<br />
<br />
When mails are stored on an IMAP server, some functionality is not available due to restrictions of the IMAP protocol. Such functionality is marked with "not IMAP".<br />
<br />
=== Get mail count ===<br />
<br />
GET <code>/ajax/mail?action=count</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder whose mail count is queried<br />
<br />
Response (not IMAP: with timestamp): An integer value representing folder's mail count<br />
<br />
=== Get all mails ===<br />
<br />
GET <code>/ajax/mail?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#DetailedMailData | Detailed mail data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response or the string “thread” to return thread-sorted messages. If this parameter is specified and holds a column number, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>left_hand_limit</code> - A positive integer number to specify the "right-hand" limit of the range to return<br />
* <code>right_hand_limit</code> - A positive integer number to specify the "left-hand" limit of the range to return<br />
* <code>limit</code> - A positive integer number to specify how many items shall be returned according to given sorting; overrides <code>left_hand_limit</code>/<code>right_hand_limit</code> parameters and is equal to <code>left_hand_limit=0</code> and <code>right_hand_limit=&lt;limit&gt;</code><br />
<br />
Response (not IMAP: with timestamp): An array with mail data. Each array element describes one mail and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedMailData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed mail data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 102 || color_label || Number || Color number used by Outlook to label the object. The assignment of colors to numbers is arbitrary and specified by the client. The numbers are integer numbers between 0 and 10 (inclusive).<br />
|-<br />
| 600 || id || String || Object ID<br />
|-<br />
| 601 || folder_id || String || Object ID of the parent folder<br />
|-<br />
| 602 || attachment || Boolean || Specifies whether this mail has attachments.<br />
|-<br />
| 603 || from || Array || Each element is a two-element array specifying one sender. The first element of each address is the personal name, the second element is the email address. Missing address parts are represented by <code>null</code> values.<br />
|-<br />
| 604 || to || Array || Each element is a two-element array (see the from field) specifying one receiver.<br />
|-<br />
| 605 || cc || Array || Each element is a two-element array (see the from field) specifying one carbon-copy receiver.<br />
|-<br />
| 606 || bcc || Array || Each element is a two-element array (see the from field) specifying one blind carbon-copy receiver.<br />
|-<br />
| 607 || subject || String || Subject line.<br />
|-<br />
| 608 || size || Number || Size of the mail in bytes.<br />
|-<br />
| 609 || sent_date || Time || Date and time as specified in the mail by the sending client.<br />
|-<br />
| 610 || received_date || Time || Date and time as measured by the receiving server.<br />
|-<br />
| 611 || flags || Number || Various system flags. A sum of zero or more of following values:<br />
{| cellspacing="0" border="1"<br />
| 1 || answered<br />
|-<br />
| 2 || deleted<br />
|-<br />
| 4 || draft<br />
|-<br />
| 8 || flagged<br />
|-<br />
| 16 || recent<br />
|-<br />
| 32 || seen<br />
|-<br />
| 64 || user<br />
|-<br />
| 256 || forwarded<br />
|}<br />
See javax.mail.Flags.Flag for details.<br />
|-<br />
| 612 || level || Number || Zero-based nesting level in a thread.<br />
|-<br />
| 613 || disp_notification_to || String || Content of message's header “Disposition-Notification-To”<br />
|-<br />
| 614 || priority || Number || Value of message's “X-Priority” header:<br />
{| cellspacing="0" border="1"<br />
| 0 || No priority<br />
|-<br />
| 5 || Very Low<br />
|-<br />
| 4 || Low<br />
|-<br />
| 3 || Normal<br />
|-<br />
| 2 || High<br />
|-<br />
| 1 || Very High<br />
|}<br />
|-<br />
| 615 || msg_ref || String || Message reference on reply/forward.<br />
|-<br />
| 651 || flag_seen || String || Special field to sort mails by seen status<br />
|-<br />
| 652 || account_name || String || Message's account name.<br />
|-<br />
| 653 || account_id || int || Message's account identifier. Since v6.20.2<br />
|-<br />
| || user || Array || An array with user-defined flags as strings.<br />
|-<br />
| || headers || Object || An object with a field for every non-standard header. The header name is the field name. The header value is the value of the field as string.<br />
|-<br />
| || attachments || Array || Each element is an attachment as described in [[#Attachment | Attachment]]. The first element is the mail text. If the mail has multiple representations (multipart-alternative), then the alternatives are placed after the mail text and have the field disp set to alternative.<br />
|-<br />
| || nested_msgs || Array || Each element is a mail object as described in this table, except for fields id, folder_id and attachment.<br />
|-<br />
| || truncated || boolean || true/false if the mail content was trimmed. Since v7.6.1<br />
|-<br />
| || source || String || RFC822 source of the mail. Only present for <tt>action=get&attach_src=true</tt><br />
|}<br />
<br />
{| id="Attachment" cellspacing="0" border="1"<br />
|+ align="bottom" | Attachment<br />
! Name !! Type !! Value<br />
|-<br />
| id || String || Object ID (unique only inside the same message)<br />
|-<br />
| content_type || String || MIME type<br />
|-<br />
| content || String || Content as text. Present only if easily convertible to text.<br />
|-<br />
| filename || String || Displayed filename (mutually exclusive with content).<br />
|-<br />
| size || Number || Size of the attachment in bytes.<br />
|-<br />
| disp || String || Attachment's disposition: null, inline, attachment or alternative.<br />
|}<br />
<br />
=== Get all mail conversations (since v7.x) ===<br />
<br />
GET <code>/ajax/mail?action=threadedAll</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#DetailedMailData | Detailed mail data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response or the string “thread” to return thread-sorted messages. If this parameter is specified and holds a column number, then the parameter order must be also specified. <b>Note</b>: Applies only to root-level messages.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified. <b>Note</b>: Applies only to root-level messages.<br />
* <code>includeSent</code> - A boolean value to signal that conversations also include messages taken from special "sent" aka "sent items" folder<br />
* <code>left_hand_limit</code> - A positive integer number to specify the "right-hand" limit of the range to return. <b>Note</b>: Applies only to root-level messages.<br />
* <code>right_hand_limit</code> - A positive integer number to specify the "left-hand" limit of the range to return. <b>Note</b>: Applies only to root-level messages.<br />
* <code>limit</code> - A positive integer number to specify how many items shall be returned according to given sorting; overrides <code>left_hand_limit</code>/<code>right_hand_limit</code> parameters and is equal to <code>left_hand_limit=0</code> and <code>right_hand_limit=&lt;limit&gt;</code>. <b>Note</b>: Applies only to root-level messages.<br />
<br />
Response (not IMAP: with timestamp): An JSON array consisting of JSON objects, each representing a conversation's root message along with its message thread. The root message's JSON object is filled according to specified columns and is enhanced by special <code>"thread"</code> JSON field representing the full message thread (including the root message itself). The <code>"thread"</code> JSON field is a JSON array of JSON objects; each representing a message in the conversation sorted by time-line, also filled with specified columns. E.g.<br />
<br />
<pre><br />
{<br />
"flags":32,<br />
"color_label":0,<br />
"unreadCount":0,<br />
"id":"263852",<br />
"folder_id":"default0/INBOX",<br />
"thread":[<br />
{<br />
"id":"263852",<br />
"folder_id":"default0/INBOX",<br />
"flags":32,<br />
"color_label":0<br />
},<br />
{<br />
"id":"263853",<br />
"folder_id":"default0/INBOX",<br />
"flags":32,<br />
"color_label":0<br />
},<br />
{<br />
"id":"26323",<br />
"folder_id":"default0/Sent",<br />
"flags":32,<br />
"color_label":0<br />
},<br />
{<br />
"id":"263854",<br />
"folder_id":"default0/INBOX",<br />
"flags":32,<br />
"color_label":0<br />
}<br />
]<br />
}<br />
</pre><br />
<br />
=== Search mails ===<br />
<br />
PUT <code>/ajax/mail?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#DetailedMailData | Detailed mail data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response or the string “thread” to return thread-sorted messages. If this parameter is specified and holds a column number, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Request Body: A JSON array of JSON objects each containing the search field and its search pattern: e.g.:<br />
<code>[{"col": 612, "pattern": "Joe"}, {"col": 614, "pattern": "Tuesday"}]</code> Supported values for <code>col</code> are 603 to 607 (from, to, cc, bcc and subject) and -1 for full text search.<br />
<br />
Response (not IMAP: with timestamp): An array with mail data. Each array element describes one mail and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a list of mails ===<br />
<br />
PUT <code>/ajax/mail?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for mails are defined in [[#DetailedMailData | Detailed mail data]].<br />
* <code>headers</code> - (preliminary) A comma-separated list of header names. Each name requests denoted header from each mail<br />
<br />
Request body: An array with one object for each requested mail. Each object contains the fields <code>folder</code> and <code>id</code>.<br />
<br />
Response (not IMAP: with timestamp): An array with mail data. Each array element describes one mail and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter followed by requested headers.<br />
<br />
=== Copy mails ===<br />
<br />
PUT <code>/ajax/mail?action=copy</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested mail.<br />
* <code>folder</code> – Object ID of the source folder.<br />
<br />
Request Body: A JSON object containing the id of the destination folder inside the "folder_id" field: e.g.:<br />
<code>{"folder_id": 1376}</code><br />
<br />
Response: A JSON array containing the ID of the copied mail<br />
<br />
=== Move mails ===<br />
<br />
PUT <code>/ajax/mail?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested mail.<br />
* <code>folder</code> – Object ID of the source folder.<br />
<br />
Request Body: A JSON object containing the id of the destination folder inside the "folder_id" field: e.g.:<br />
<code>{"folder_id": 1376}</code><br />
<br />
<br />
Response: A JSON array containing the ID of the moved mail<br />
<br />
=== Update mails ===<br />
<br />
PUT <code>/ajax/mail?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested mail.<br />
* <code>message_id</code> – (Preliminary) The value of "Message-Id" header of the requested mail. This parameter is a substitute for "id" parameter.<br />
* <code>folder</code> – Object ID of the folder.<br />
<br />
'''Note''': If neither parameter "<code>id</code>" nor parameter "<code>message_id</code>" is specified, all folder's messages are updated accordingly. Available with v6.20.<br />
<br />
Request Body: A JSON object which carries the new values that ought to be applied to mail as described in [[#UpdateMail | Update mail]] or [[#UpdateMailExtended | Update mail extended]] (available with SP6 v6.10).<br />
<br />
Response: A JSON object containing the Object ID of the updated mail and its folder.<br />
<br />
{| id="UpdateMail" cellspacing="0" border="1"<br />
|+ align="bottom" | Update mail<br />
! Name !! Type !! Value<br />
|-<br />
| color_label || Number || The color number between 0 and 10.<br />
|-<br />
| flags || Number || A set of flags to add or remove. Note: Flags for "recent" (8) and "user" (64) are ignored.<br />
|-<br />
| value || Boolean || <code>true</code> to add the flags specified by <code>flags</code> (logical OR), <code>false</code> to remove them (logical AND with the inverted value).<br />
|}<br />
<br />
<br />
<br />
{| id="UpdateMailExtended" cellspacing="0" border="1"<br />
|+ align="bottom" | Update mail extended (available with SP6 v6.10)<br />
! Name !! Type !! Value<br />
|-<br />
| set_flags || Number || A set of flags to add. Note: Flags for "recent" (8) and "user" (64) are ignored.<br />
|-<br />
| clear_flags || Number || A set of flags to remove. Note: Flags for "recent" (8) and "user" (64) are ignored.<br />
|}<br />
<br />
<br />
=== Mark all mails as seen (available with v7.6.0) ===<br />
<br />
PUT <code>/ajax/mail?action=all_seen</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder.<br />
<br />
Request Body: n.a.<br />
<br />
Response: <code>true</code><br />
<br />
=== Not IMAP: Get updated mails ===<br />
<br />
GET <code>/ajax/mail?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: Just an empty JSON array is going to be returned since this action cannot be applied to IMAP.<br />
<br />
=== Get a mail ===<br />
<br />
GET <code>/ajax/mail?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested mail.<br />
* <code>message_id</code> – (Preliminary) The value of "Message-Id" header of the requested mail. This parameter is a substitute for "id" parameter.<br />
* <code>folder</code> – Object ID of the mail's folder.<br />
* <code>edit</code> (optional) – 1 indicates that this request should fill the message compose dialog to edit a message and thus display-specific date is going to be withheld.<br />
* <code>hdr</code> (optional) – 1 to let the response contain only the (formatted) message headers as plain text<br />
* <code>src</code> (optional) – 1 to let the response contain the complete message source as plain text<br />
* <code>save</code> (optional) – 1 to write the complete message source to output stream. '''NOTE:''' This parameter will only be used if parameter <code>src</code> is set to 1.<br />
* <code>view</code> (optional - available with SP4)<br />
** "raw" returns the content as it is, meaning no preparation are performed and thus no guarantee for safe contents is given (available with SP6 v6.10).<br />
** "text" forces the server to deliver a text-only version of the requested mail's body, even if content is HTML.<br />
** "textNoHtmlAttach" is the same as "text", but does not deliver the HTML part as attachment in case of multipart/alternative content.<br />
** "html" to allow a possible HTML mail body being transferred as it is (but white-list filter applied).<br />
** "noimg" to allow a possible HTML content being transferred but without original image src attributes which references external images: Can be used to prevent loading external linked images (spam privacy protection).<br />
** '''NOTE:''' if set, the corresponding gui config setting will be ignored.<br />
* <code>unseen</code> (optional) – "1" or "true" to leave an unseen mail as unseen although its content is requested<br />
* <code>max_size</code> (optional - available since v7.6.1) A positive integer number (greater than 10000) to specify how many characters of the message content will be returned. If the number is smaller than 10000 the value will be ignored and 10000 used.<br />
* <code>attach_src</code> (optional - available since v7.6.1) 1 to let the JSON mail representation being extended by <code>"source"</code> field containing the mail raw RFC822 source data<br />
<br />
Response (not IMAP: with timestamp): An JSON object containing all data of the requested mail. The fields of the object are listed in [[#DetailedMailData | Detailed mail data]]. The fields id and attachment are not included. '''NOTE:''' Of course response is not a JSON object if either parameter <code>hdr</code> or parameter <code>src</code> are set to "1". Then the response contains plain text. Moreover if optional parameter <code>save</code> is set to "1" the complete message source is going to be directly written to output stream to open browser's save dialog.<br />
<br />
=== Get multiple mails as a ZIP file ===<br />
<br />
GET <code>/ajax/mail?action=zip_messages</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – The folder identifier.<br />
* <code>id</code> – A comma-separated list of Object IDs of the requested mails<br />
<br />
Response body: The raw byte data of the ZIP file.<br />
<br />
=== Get a mail attachment ===<br />
<br />
GET <code>/ajax/mail?action=attachment</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – The folder identifier.<br />
* <code>id</code> – Object ID of the mail which contains the attachment.<br />
* <code>attachment</code> – ID of the requested attachment '''OR'''<br />
* <code>cid</code> – Value of header 'Content-ID' of the requested attachment<br />
* <code>save</code> – 1 overwrites the defined mimetype for this attachment to force the download dialog, otherwise 0.<br />
* <code>filter</code> (optional) – 1 to apply HTML white-list filter rules if and only if requested attachment is of MIME type <code>text/htm*</code> '''AND''' parameter <code>save</code> is set to 0.<br />
<br />
Response body: The raw byte data of the document. The response type for the HTTP Request is set accordingly to the defined mimetype for this attachment, except the parameter save is set to 1.<br />
<br />
=== Get multiple mail attachments as a ZIP file ===<br />
<br />
GET <code>/ajax/mail?action=zip_attachments</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – The folder identifier.<br />
* <code>id</code> – Object ID of the mail which contains the attachments.<br />
* <code>attachment</code> – A comma-separated list of IDs of the requested attachments<br />
<br />
Response body: The raw byte data of the ZIP file.<br />
<br />
=== Send a mail ===<br />
<br />
POST <code>/ajax/mail?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request Body: This method uses the encoding multipart/form-data or multipart/mixed.<br />
* The form filed <code>json_0</code> contains the rudimentary mail as JSON object as described in [[#DetailedMailData | Detailed mail data]] with just its message body (as html content) defined in nested JSON array "attachments" and its header data (from, to, subject, etc.). The field "content_type" defines whether the mail ought to be sent as plain text ("text/plain"), as html ("text/html") or as multipart/alternative ("ALTERNATIVE"). Sending a mail requires some special fields inside JSON mail object. The field "infostore_ids" defines a JSON array of infostore document ID(s) that ought to be appended to this mail as attachments. The field "msgref" indicates the ID of the referenced original mail. Moreover the field "sendtype" indicates the type of the message:<br />
** 0 - A normal new mail (optional)<br />
** 1 - A reply mail. The field "msgref" must be present<br />
** 2 - A forward mail. The field "msgref" must be present<br />
** 3 - A draft edit operation. The field "msgref" must be present in order to delete previous draft message since e.g. IMAP does not support changing/replacing a message but requires a delete-and-insert sequence<br />
** 4 - Transport of a draft mail. The field "msgref" must be present<br />
** 6 - This type signals that user intends to send out a saved draft message and expects the draft message (referenced by "msgref" field) being deleted after successful transport<br />
Example of a normal new mail which appends user's VCard and requests a read receipt from receiver:<br />
<br />
<code>Content-Disposition: form-data; name="json_0"....{"from":"\u0022Muster, Karl\u0022 <karl.muster@somewhere.com>","to":"someone@somewhere.com","cc":"","bcc":"",<br />
"subject":"Mail Subject","priority":"3","disp_notification_to":true,"vcard":1,<br />
"attachments":[{"content_type":"ALTERNATIVE","content":"Simple Mail Text!&lt;br&gt;&lt;br&gt;\u000a\u000a"}]}</code><br />
* The request accepts file fields in upload form that denote referenced files that are going to be appended as attachments<br />
* For "text/plain" mail bodies, the JSON boolean field "raw" may be specified inside the body's JSON representation to signal that the text content shall be kept as-is; meaning to keep all formatting intact<br />
<br />
==== Attach data sources ====<br />
Moreover the JSON representation may contain data sources which should be appended as file attachments to the mail. Then the mail contains the <code>"datasources"</code> key which is expected to be a JSON array of data source descriptions.<br />
<br />
A data source description follows the [[#Module_.22conversion.22_.28preliminary.29 | conversion specification]].<br />
<br />
For example to attach a file through an URL the field looks like this (available with v6.18.2):<br />
<br />
<pre><br />
{<br />
"from": "someone@somewhere.com,<br />
...<br />
"datasources"<br />
[<br />
{<br />
"identifier": "com.openexchange.url.mail.attachment",<br />
"args":<br />
{<br />
"url": <url-string>,<br />
"timeout": <optional-timeout-millis-int, default is 2500msec>,<br />
"contentType": <optional-content-type-string>,<br />
"charset": <optional-charset-string>,<br />
"size": <optional-size-int>,<br />
"disposition": <optional-disposition-string>,<br />
"fileName": <optional-file-name-string>,<br />
}<br />
}<br />
]<br />
}<br />
</pre><br />
<br />
Response: Object ID of the newly created mail.<br />
<br />
=== Send/Save mail as MIME data block (RFC822) (added in SP5) ===<br />
<br />
PUT <code>/ajax/mail?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> - A session ID previously obtained from the login module.<br />
* <code>folder</code> (optional) - In case the mail should not be sent out, but saved in a specific folder, the "folder" parameter can be used. If the mail should be sent out to the recipient, the "folder" parameter must not be included and the mail is stored in the folder "Sent Items". Example "folder=default.INBOX/Testfolder"<br />
* <code>flags</code> (optional) - In case the mail should be stored with status "read" (e.g. mail has been read already in the client inbox), the parameter "flags" has to be included. If no "folder" parameter is specified, this parameter must not be included. For infos about mail flags see [[#DetailedMailData | Detailed mail data]] spec.<br />
<br />
Request Body: The MIME Data Block<br />
<br />
Response: Object ID of the newly created/moved mail.<br />
<br />
=== Import of mails as MIME data block (RFC822) (added with 6.18) ===<br />
<br />
This request can be used to store a single or a lot of mails in the OX mail storage backend. This action should be used instead of <code>action=new</code> because it is faster and tolerant to 8bit encoded emails.<br />
<br />
<code>POST /ajax/mail?action=import</code><br />
<br />
Parameters:<br />
* <code>session</code> - A session ID previously obtained from the login module.<br />
* <code>folder</code> - For the import this parameter is required to specify the folder into that the emails should be imported. Example "folder=default.INBOX/Testfolder"<br />
* <code>flags</code> (optional) - In case the mail should be stored with status "read" (e.g. mail has been read already in the client inbox), the parameter "flags" has to be included. For infos about mail flags see [[#DetailedMailData | Detailed mail data]] spec.<br />
*<code>force</code> (optional) - If this parameter is set to true, the server skips checking the valid From-address<br />
<br />
Request Body: A multipart/form-data with a single or multiple file parts each having a different name and containing the RFC822 encoded email as binary data like in a file upload.<br />
<br />
Response: A JSON object containing the folder identifier and the object identifier of the imported mail or a JSON array of those JSON objects if multiple mails are imported.<br />
<br />
=== Reply/Forward a mail ===<br />
<br />
GET <code>/ajax/mail?action=reply</code><br><br />
GET <code>/ajax/mail?action=replyall</code><br><br />
GET <code>/ajax/mail?action=forward</code><br><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested Message.<br />
* <code>folder</code> - Object ID of the folder, whose contents are queried.<br />
* <code>view</code> (optional - available with SP6) - "text" forces the server to deliver a text-only version of the requested mail's body, even if content is HTML. "html" to allow a possible HTML mail body being transferred as it is (but white-list filter applied).'''NOTE:''' if set, the corresponding gui config setting will be ignored.<br />
* <code>setFrom</code> (optional - available since v7.6.0) A flag ("true"/"false") that signals if "From" header shall be pre-selected according to a suitable recipient address that matches one of user's E-Mail address aliases; only supported for <code>/ajax/mail?action=replyall</code> and <code>/ajax/mail?action=reply</code><br />
* <code>max_size</code> (optional - available since v7.6.1) A positive integer number (greater than 10000) to specify how many characters of the message content will be returned. If the number is smaller than 10000 the value will be ignored and 10000 used.<br />
<br />
Response (not IMAP: with timestamp): An object containing all data of the requested mail. The fields of the object are listed in [[#DetailedMailData | Detailed mail data]]. The fields id and attachment are not included.<br />
<br />
=== Delete mails ===<br />
<br />
PUT <code>/ajax/mail?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* Not IMAP: <code>timestamp</code> – Timestamp of the last update of the deleted mails.<br />
<br />
Request body: An array of objects providing folder IDs and object IDs of the deleted mails.<br />
<code><br><br />
[<br><br />
&nbsp;{&nbsp;&quot;folder&quot;:&quot;default0/INBOX&quot;,&nbsp;&quot;id&quot;:&quot;123&quot;&nbsp;}<br><br />
&nbsp;...<br><br />
&nbsp;{&nbsp;&quot;folder&quot;:&quot;default0/MyFolder&quot;,&nbsp;&quot;id&quot;:&quot;134&quot;&nbsp;}<br><br />
]<br><br />
</code><br />
<br />
Not IMAP: Response: An array with object IDs of mails which were modified after the specified timestamp and were therefore not deleted.<br />
<br />
=== Clear mail folder(s) ===<br />
<br />
PUT <code>/ajax/mail?action=clear</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* Not IMAP: <code>timestamp</code> – Timestamp of the last update of the deleted mails.<br />
<br />
Request body: An array with IDs of the mail folders to clear<br />
<br />
Response: An array with IDs of mail folder that could not be cleared; meaning the response body is an empty JSON array if everything went well.<br />
<br />
== Module "groups" ==<br />
<br />
The group module allows to query available groups. It is mainly used by the dialog for the selection of participants.<br />
<br />
=== Get a group ===<br />
<br />
GET <code>/ajax/group?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The group id.<br />
<br />
Response: A group object as described in [[#GroupData | Group data]].<br />
<br />
=== List groups ===<br />
<br />
PUT <code>/ajax/group?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An array with group identifiers.<br />
<br />
Response: An array of group objects as described in [[#GroupData | Group data]].<br />
<br />
=== Search for groups ===<br />
<br />
PUT <code>/ajax/group?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An object with search parameters as described in [[#GroupSearch | Group search]].<br />
<br />
{| id="GroupSearch" cellspacing="0" border="1"<br />
|+ align="bottom" | Group search<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find groups. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|}<br />
<br />
Response with timestamp: An array of group objects as described in [[#GroupData | Group data]].<br />
<br />
{| id="GroupData" cellspacing="0" border="1"<br />
|+ align="bottom" | Group data<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || ID<br />
|-<br />
| display_name || String || Display name<br />
|-<br />
| name || String || Name with character restrictions<br />
|-<br />
| members || Array || The array contains identifier of users that are member of the group.<br />
|}<br />
<br />
=== Create a group ===<br />
<br />
introduced 2008-06-12<br />
<br />
PUT <code>/ajax/group?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Group object as described in [[#GroupData | Group data]]. The field id is not present.<br />
<br />
Response: A json objekt with attribute <code>id</code> of the newly created group.<br />
<br />
=== Delete a group ===<br />
<br />
introduced 2008-06-12<br />
<br />
PUT <code>/ajax/group?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the group to delete.<br />
<br />
Request body: An object with the field “id” containing the unique identifier of the group.<br />
<br />
Response: An empty json array if the group was deleted successfully.<br />
<br />
=== Change a group ===<br />
<br />
introduced 2008-06-12<br />
<br />
PUT <code>/ajax/group?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the group to update.<br />
* <code>timestamp</code> – Time stamp of the group to update. If the group was modified after the specified time stamp, then the update must fail. <br />
<br />
Request body: Group object as described in [[#GroupData | Group data]]. Only modified fields are present and the field id is omitted.<br />
<br />
=== Get updates (since v6.18.1) ===<br />
<br />
introduced 2010-09-13<br />
<br />
GET <code>/ajax/group?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested groups.<br />
<br />
Response with timestamp: An array with new, modified and deleted groups. New, modified and deleted groups are represented by JSON objects as described in [[#GroupData | Group data]].<br />
<br />
== Module "resource" ==<br />
<br />
The resource module allows to query available resources. It is mainly used by the dialog for the selection of participants.<br />
<br />
=== Get all resources ===<br />
<br />
GET <code>/ajax/resource?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: An array of resource identifier.<br />
<br />
=== List resources ===<br />
<br />
PUT <code>/ajax/resource?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
<br />
Request body: An array with resources ids.<br />
<br />
Response: An array of resource objects as described in [[#ResourceResponse | Resource response]].<br />
<br />
=== Get a resource ===<br />
<br />
GET <code>/ajax/resource?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The resource id.<br />
<br />
Response: An array of resource objects as described in [[#ResourceResponse | Resource response]].<br />
<br />
=== Search for resources ===<br />
<br />
PUT <code>/ajax/resource?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An object with search parameters as described in [[#ParticipantSearch | Participant search]].<br />
<br />
{| id="ParticipantSearch" cellspacing="0" border="1"<br />
|+ align="bottom" | Participant search<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find resources. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|}<br />
<br />
Response: An array of resource objects as described in [[#ResourceResponse | Resource response]].<br />
<br />
{| id="ResourceResponse" cellspacing="0" border="1"<br />
|+ align="bottom" | Resource Response<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || ID<br />
|-<br />
| display_name || String || Display name<br />
|-<br />
| name || String || internal name<br />
|-<br />
| mailaddress || String || email address<br />
|-<br />
| availability || Boolean || can be false to mark the resource currently unavailable<br />
|-<br />
| description || String || description of the resource<br />
|-<br />
| last_modified || Time || Date and time of the last modification.<br />
|-<br />
| last_modified_utc || Timestamp || Date and time of the last modification.<br />
|}<br />
<br />
=== Create a resource ===<br />
<br />
PUT <code>/ajax/resource?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Resource object as described in [[#ResourceResponse | Resource response]]. The field id is not present.<br />
<br />
Response: An object with attribute <code>id</code> of the newly created resource.<br />
<br />
=== Delete a resource ===<br />
<br />
PUT <code>/ajax/resource?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the resource to delete.<br />
<br />
Request body: An object with the field “id” containing the unique identifier of the resource.<br />
<br />
Response: An empty json array if the resource was deleted successfully.<br />
<br />
=== Delete resources (since v6.22) ===<br />
<br />
PUT <code>/ajax/resource?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the resource to delete.<br />
<br />
Request body: An array of objects with the field “id” containing the unique identifier of the resource.<br />
<br />
Response: An empty json array if the resources were deleted successfully.<br />
<br />
=== Change a resource ===<br />
<br />
PUT <code>/ajax/resource?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the resource to update.<br />
* <code>timestamp</code> – Time stamp of the resource to update. If the resource was modified after the specified time stamp, then the update must fail. <br />
<br />
Request body: Resource object as described in [[#ResourceResponse | Resource response]]. Only modified fields are present and the field id is omitted.<br />
<br />
=== Get updates (since v6.18.1) ===<br />
<br />
introduced 2010-09-13<br />
<br />
GET <code>/ajax/resource?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested resources.<br />
<br />
Response with timestamp: An array with new, modified and deleted resources. New, modified and deleted resources are represented by JSON objects as described in [[#ResourceResponse | Resource response]].<br />
<br />
== Module "infostore" or "Filestore" or "Files" or "Drive" ==<br />
This module has been renamed quite often. Whatever its name, it combines the knowledge database, bookmarks and document storage.<br />
<br />
=== Get all infoitems ===<br />
<br />
GET <code>/ajax/infostore?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for infoitems are defined in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response with timestamp: An array with infoitem data. Each array element describes one infoitem and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedInfoitemData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed infoitem data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 700 || title || String || Title<br />
|-<br />
| 701 || url || String || Link/URL<br />
|-<br />
| 702 || filename || String || Displayed filename of the document.<br />
|-<br />
| 703 || file_mimetype || String || MIME type of the document. The client converts known types to more readable names before displaying them.<br />
|-<br />
| 704 || file_size || Number || Size of the document in bytes.<br />
|-<br />
| 705 || version || Number || Version number of the document. New documents start at 1. Every update increments the version by 1.<br />
|-<br />
| 706 || description || String || Description<br />
|-<br />
| 707 || locked_until || Time || The time until which this item will presumably be locked. Only set if the docment is currently locked, 0 otherwise.<br />
|-<br />
| 708 || file_md5sum || String || MD5Sum of the document. Not yet implemented, so this is currently always empty.<br />
|-<br />
| 709 || version_comment || String || A version comment is used to file a changelog for the file.<br />
|-<br />
| 710 || current_version || Boolean || “true” if this version is the current version “false” otherwise. . Note: This is not writeable<br />
|-<br />
| 711 || number_of_versions || Number || The number of all versions of the infoitem. Note: This is not writeable.<br />
|}<br />
<br />
=== Get a list of infoitems ===<br />
<br />
PUT <code>/ajax/infostore?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for infoitems are defined in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
<br />
Request body: An array with object IDs of requested infoitems.<br />
<br />
Response with timestamp: An array with infoitem data. Each array element describes one infoitem and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get updated infoitems ===<br />
<br />
GET <code>/ajax/infostore?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for infoitems are defined in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested infoitems.<br />
* <code>ignore</code> (optional) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
<br />
Response with timestamp: An array with new, modified and deleted infoitems. New and modified infoitems are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted infoitems (should the <code>ignore</code> parameter be ever implemented) would be identified by their object IDs as plain strings, without being part of a nested array.<br />
<br />
=== Get an infoitem ===<br />
<br />
GET <code>/ajax/infostore?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested infoitem.<br />
* <code>version</code> (optional) – If present the infoitem data describes the given version. Otherwise the current version is returned <br />
<br />
Response with timestamp: An object containing all data of the requested infoitem. The fields of the object are listed in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. The field id is not included.<br />
<br />
=== Search infoitems ===<br />
<br />
PUT <code>/ajax/infostore?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields as per tables [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>start</code> (optional) – The start index (inclusive) in the ordered search, that is requested.<br />
* <code>end</code> (optional) – The last index (inclusive) from the ordered search, that is requested.<br />
<br />
Request body: An Object as described in [[#SearchContacts | Search contacts]].<br />
<br />
=== Get an infoitem document ===<br />
<br />
GET <code>/ajax/infostore/[filename]?action=document</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested infoitem.<br />
* <code>folder</code> – Object ID of the infoitem's folder.<br />
* <code>version</code> (optional) – If present the infoitem data describes the given version. Otherwise the current version is returned <br />
* <code>content_type</code>(optional) – If present the response declares the given content_type in the Content-Type header.<br />
<br />
Response body: The raw byte data of the document. The response type for the HTTP Request is set accordingly to the defined mimetype for this infoitem or the content_type given.<br />
<br />
Note: The Filename may be added to the customary infostore path to suggest a filename to a Save-As dialog.<br />
<br />
=== Get all versions ===<br />
<br />
GET <code>/ajax/infostore?action=versions</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the infoitem whose versions are requested.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for infoitems are defined in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response with timestamp: An array with infoitem data. Each array element describes one infoitem and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. The timestamp is the timestamp relating to the requested infostore item.<br />
<br />
=== Get multiple documents as a ZIP archive (available with v7.4.0) ===<br />
<br />
GET <code>/ajax/infostore?action=zipdocuments</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>body</code> – A URL-encoded JSON array; see below for details<br />
<br />
Parameter <code>body</code>: A JSON array of JSON object tuples specifying the documents' versions to include in the requested ZIP archive; e.g<br><br />
<pre><br />
[{"id":"61820","folder":"70303"},{"id":"61821","folder":"70303", "version": "1"}]<br />
</pre><br />
The field <code>"version"</code> is optional; if missing it refers to latest/current version.<br><br />
So, a valid parameter would look like:<br />
<pre><br />
...&body=%5B%7B%22id%22%3A%2261820%22%2C%22folder%22%3A%2270303%22%7D%2C%7B%22id%22%3A%2261821%22%2C%22folder%22%3A%2270303%22%2C%22version%22%3A%221%22%7D%5D<br />
</pre><br />
<br />
Response: The download offer for the requested ZIP archive containing specified document versions<br />
<br />
=== Update an infoitem via PUT ===<br />
<br />
PUT <code>/ajax/infostore?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated infoitem.<br />
* <code>timestamp</code> – Timestamp of the updated infoitem. If the infoitem was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. Only modified fields are present.<br />
<br />
=== Update an infoitem via POST ===<br />
<br />
POST <code>/ajax/infostore?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated infoitem.<br />
* <code>timestamp</code> – Timestamp of the updated infoitem. If the infoitem was modified after the specified timestamp, then the update must fail.<br />
* <code>json</code> - Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. Only modified fields are present.<br />
* <code>file</code> – File Metadata as per <input type=”file” /><br />
<br />
Request Body: Body of content-type “multipart/form-data” or “multipart/mixed” containing the above mentioned fields and file-data.<br />
<br />
Response: The response is sent as a HTML document (see introduction).<br />
<br />
=== Create an infoitem via PUT ===<br />
<br />
PUT <code>/ajax/infostore?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. The field id is not included.<br />
<br />
Response: Object ID of the newly created infoitem.<br />
<br />
=== Create an infoitem via POST ===<br />
<br />
POST <code>/ajax/infostore?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>json</code> - Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. The field id is not included.<br />
* <code>file</code> – File metadata as per <input type=”file” /><br />
<br />
Request Body: Body of content-type “multipart/form-data” or “multipart/mixed” containing the above mentioned fields and file-data.<br />
<br />
Response: Object ID of the newly created infoitem. The response is sent as a HTML document (see introduction).<br />
<br />
=== Save an attachment in the infostore ===<br />
<br />
PUT <code>/ajax/infostore?action=saveAs</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>attached</code> – The Object ID of the Object with the attachment<br />
* <code>folder</code> – The Folder ID of the Object with the attachment<br />
* <code>module</code> – The Module type of the Object with the attachment.<br />
* <code>Attachment</code> – The id of the attachement to save.<br />
<br />
Request body: Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. The field id is not included. The fields in this infoitem object override values from the attachment. The folder_id must be given.<br />
<br />
Response: Object ID of the newly created infoitem.<br />
<br />
=== Delete infoitems ===<br />
<br />
PUT <code>/ajax/infostore?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted infoitems.<br />
* <code>hardDelete</code> - Optional, defaults to \"false\". If set to \"true\", the file is deleted permanently. Otherwise, and if the underlying storage supports a trash folder and the file is not yet located below the trash folder, it is moved to the trash folder.<br />
<br />
Request body: An array with objects to delete. The fields for the object are described in [[#FullIdentifierForAnInfostoreDocument|Full identifier for an infostore document]].<br />
<br />
Response: An array with [[]]. <br />
<br />
{| id="FullIdentifierForAnInfostoreDocument" cellspacing="0" border="1"<br />
|+ align="bottom" | Full identifier for an infostore document<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || Object ID<br />
|-<br />
| folder || Number || Folder ID<br />
|}<br />
<br />
=== Delete versions of infostore documents ===<br />
<br />
PUT <code>/ajax/infostore?action=detach</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the base Object<br />
* <code>folder</code> – The Folder of the Object<br />
* <code>timestamp</code> - Timestamp of the infostore object<br />
<br />
Request body: A List of arrays with the version numbers of the infoitems to detach.<br />
<br />
Response: An array with version numbers that were not deleted.<br />
<br />
Note: When the current version of a document is deleted the new current version will be the newest version.<br />
<br />
=== Delete all versions of infostore documents ===<br />
<br />
PUT <code>/ajax/infostore?action=revert</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the base Object<br />
* <code>folder</code> – The Folder of the Object<br />
* <code>timestamp</code> - Timestamp of the infostore object<br />
<br />
Removes all versions of the infostore document leaving only the base object.<br />
<br />
=== Copy an infostore document via PUT ===<br />
<br />
PUT <code>/ajax/infostore?action=copy</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the base Object<br />
* <code>folder</code> – The Folder of the Object<br />
* <code>timestamp</code> - Timestamp of the infostore object<br />
<br />
Request body: Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. Only modified fields are present.<br />
<br />
Response: The id of the newly created object<br />
<br />
Note: Only the fields (and the file) of the current document will be copied. Those fields present in the request are modified accordingly.<br />
<br />
=== Copy an infostore document via POST ===<br />
<br />
POST <code>/ajax/infostore?action=copy</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated infoitem.<br />
* <code>timestamp</code> – Timestamp of the updated infoitem. If the infoitem was modified after the specified timestamp, then the update must fail.<br />
* <code>json</code> - Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. Only modified fields are present.<br />
* <code>file</code> – File Metadata as per <input type=”file” /><br />
<br />
Request Body: Body of content-type “multipart/form-data” or “multipart/mixed” containing the above mentioned fields and file-data.<br />
<br />
Response: The response is sent as a HTML document (see introduction).<br />
<br />
Note: Only the fields (and the file) of the current document will be copied. Those fields present in the request are modified accordingly.<br />
<br />
=== Lock an infoitem ===<br />
<br />
GET <code>/ajax/infostore?action=lock</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the infoitem that should be locked.<br />
* <code>diff</code> (optional) – If present the value is added to the current time on the server (both in ms). The document will be locked until that time. If this parameter is not present, the document will be locked for a duration as configured on the server.<br />
<br />
Response with timestamp: Can only include errors.<br />
<br />
=== Unlock an infoitem ===<br />
<br />
GET <code>/ajax/infostore?action=unlock</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the infoitem that should be unlocked.<br />
<br />
Response with timestamp: Can only contain errors.<br />
<br />
<br />
== Module "Attachments" ==<br />
<br />
The Attachment Module allows file attachments to arbitrary objects. An Attachment always belongs to an object (called 'attached') in a certain folder of a certain module. <br />
<br />
=== Get All Attachments for an Object ===<br />
<br />
GET <code>/ajax/attachment?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>attached</code> – The Object ID of the Object<br />
* <code>folder</code> – The Folder ID of the Object<br />
* <code>module</code> – The Module type of the Object<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for attachment's are defined in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response: An array with attachment data. Each array element describes one attachment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a list of attachments ===<br />
<br />
PUT <code>/ajax/attachment?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for attachments are defined in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]].<br />
* <code>attached</code> – The Object ID of the Object<br />
* <code>folder</code> – The Folder ID of the Object<br />
* <code>module</code> – The Module type of the Object<br />
<br />
Request body: An array of with object IDs of requested tasks.<br />
<br />
Response with timestamp: An array with attachment data. Each array element describes one attachment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Create an Attachment ===<br />
<br />
POST <code>/ajax/attachment?action=attach</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>json_[index]</code> – The JSON representation of an attachment object as described in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]].<br />
* <code>file_[index]</code> – The file metadata as per <input type=file /> upload.<br />
<br />
Note: The JSON Object and file fields describe the corresponding attachment. For ex.: json_0 contains metadata for file_0, json_1 for file_1 and so on. Indexes start with 0.<br />
<br />
Request body: multipart/form-data or multipart/mixed containing the file data of the attached file and the above fields.<br />
<br />
Response: HTML page with javascript callback as per introduction. Contains a JSON-Array of ids of the newly created attachments. The order of the ids corresponds to the indexes in the request.<br />
<br />
{| id="AttachmentObject" cellspacing="0" border="1"<br />
|+ align="bottom" | Attachment Object<br />
! ID !! Name !! Type !! Description<br />
|-<br />
| 800 || folder || Number || The ID of the first Folder in which the attached object resides.<br />
|-<br />
| 801 || attached || Number || The object id of the object this attachement is attached to.<br />
|-<br />
| 802 || module || Number || The Module of this Object Possible Values:<br />
{| cellspacing="0" border="1"<br />
| 1 || Appointment<br />
|-<br />
| 4 || Task<br />
|-<br />
| 7 || Contact<br />
|-<br />
| 137 || Infostore<br />
|}<br />
|-<br />
| 803 || filename || String || The filename of the attached file.<br />
|-<br />
| 804 || file_size || Number || The file size (in bytes) of the attached file.<br />
|-<br />
| 805 || file_mimetype || String || The MIME-Type of the attached file<br />
|-<br />
| 806 || rft_flag || Boolean || If the attachment is a RTF Attachment of Outlook. (Outlook descriptions can be stored as RTF Documents).<br />
|}<br />
<br />
=== Delete Attachment ===<br />
<br />
PUT <code>/ajax/attachment?action=detach</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>attached</code> – The ID of the base Object<br />
* <code>module</code> – The type of the Object<br />
* <code>folder</code> – The Folder of the Object<br />
<br />
Request body: An array with the ids of the attachments to delete.<br />
<br />
=== Get updated attachments ===<br />
<br />
GET <code>/ajax/attachment?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>attached</code> – Object ID of the object to which the attachments are attached.<br />
* <code>module</code> – Module ID (as per [[#AttachmentObject | Attachment object]]) of the attached object.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for attachments are defined in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested infoitems.<br />
ignore (optional) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
<br />
Response with timestamp: An array with new and deleted attachments for the specified object. New attachments are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted attachments (should the <code>ignore</code> parameter be ever implemented) would be identified by their object IDs as plain numbers, without being part of a nested array.<br />
<br />
=== Get an attachment ===<br />
<br />
GET <code>/ajax/attahment?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>attached</code> – Object ID of the object to which the attachments are attached.<br />
* <code>module</code> – Module ID (as per [[#AttachmentObject | Attachment object]]) of the attached object.<br />
* <code>id</code> – Object ID of the requested attachment.<br />
<br />
Response with timestamp: An object containing all data of the requested attachment. The fields of the object are listed in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]]. <br />
<br />
=== Get an attachments filedata ===<br />
<br />
GET <code>/ajax/attachment/[filename]?action=document</code><br />
<br />
Parameters:<br />
<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>attached</code> – Object ID of the object to which the attachments are attached.<br />
* <code>module</code> – Module ID (as per [[#AttachmentObject | Attachment object]]) of the attached object.<br />
* <code>id</code> – Object ID of the requested attachment.<br />
* <code>content_type</code> (optional) – If set the responses Content-Type header is set to this value, not the attachements file mime type.<br />
<br />
Response body: The raw byte data of the document. The response type for the HTTP Request is set accordingly to the defined mimetype for this infoitem.<br />
Note: The Filename may be added to the customary infostore path to suggest a filename to a Save-As dialog.<br />
<br />
== Module "reminder" ==<br />
<br />
The reminder module provides the ability to fetch all active reminders for a user between two dates.<br />
<br />
=== Get reminder range ===<br />
<br />
GET <code>/ajax/reminder?action=range</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>end</code> – The End date of the reminder range<br />
<br />
Response: An Array with all reminders which are scheduled until the specified time. Each reminder is described in [[#ReminderResponse | Reminder response]].<br />
<br />
{| id="ReminderResponse" cellspacing="0" border="1"<br />
|+ align="bottom" | Reminder response<br />
! Field !! Type !! Description<br />
|-<br />
| id || Number || The ID of the reminder.<br />
|-<br />
| target_id || Number || The target_id where this reminder is attached to<br />
|-<br />
| alarm || Time || The time of the alarm<br />
|-<br />
| module || Number || The module of the reminder<br />
|-<br />
| servertime || Time || The time on the server<br />
|-<br />
| user_id || Number || The ID of the user.<br />
|-<br />
| last_modified || Time || The last modification timestamp of the reminder<br />
|-<br />
| recurrence_position || Number || The recurrence position for series appointments or 0 if no series<br />
|-<br />
| folder || Number || The ID of the folder through that the object can be read<br />
|-<br />
|}<br />
<br />
=== Delete a Reminder===<br />
<br />
PUT <code>/ajax/reminder?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An object with the field “id”.<br />
<br />
Response body: An JSON array with the id that was not deleted.<br />
<br />
=== Delete Reminders (since v6.22)===<br />
<br />
PUT <code>/ajax/reminder?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An array of objects with the field “id”.<br />
<br />
Response body: An JSON array with the ids that were not deleted.<br />
<br />
=== Remind again (since v6.18.1) ===<br />
<br />
PUT <code>/ajax/reminder?action=remindAgain</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the reminder whose date shall be changed.<br />
<br />
Request body: The JSON representation of the reminder; mainly containing the field “alarm” which provides the new reminder date.<br><br />
E.g. <code>{ "alarm": 1283418027381 }</code><br />
<br />
Response body: The JSON representation of the updated reminder.<br />
<br />
== Module "multiple" ==<br />
<br />
The multiple module allows to bundle multiple requests to most other modules in a single request. Not supported are:<br />
* modules login and multiple,<br />
* POST requests with a multipart encoding (uploads),<br />
* GET requests which do not use an object as described in [[#ResponseBody | Response body]] as response body (downloads).<br />
<br />
=== Multiple requests ===<br />
<br />
PUT <code>/ajax/multiple</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>continue</code> – Specifies whether processing of requests should stop when an error occurs, or whether all request should be processed regardless of errors.<br />
<br />
Request body: An array with request objects. Each request object contains all URI parameters of the "normal" request as fields. The module name of the "normal" request is included in the field module. The parameter session is not included. If the "normal" request has a request body, the object which is represented by that request body is includes as the value of the field data.<br />
<br />
Response: An array with reply objects as described in [[#ResponseBody | Response body]]. The order of reply objects corresponds to the order of requests in the request body. Unlike with all other modules, this response is itself not part of a response object as described in [[#ResponseBody | Response body]].<br />
<br />
== Module "quota" ==<br />
<br />
The filestore module allows accesssing information about the use and quota of the filestore.<br />
<br />
=== Get quota information (Since 7.6.1, Preliminary) ===<br />
<br />
GET <code>/ajax/quota?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>module</code> (optional) – The module identifier to get quota information for, required if <code>account</code> is set.<br />
* <code>account</code> (optional) – The account identifier within the module to get quota information for.<br />
<br />
Response: A JSON object containing the requested quota information. If no <code>module</code> was specified, all defined [[#ModuleQuota | module quotas]] are set in the JSON object, each one mapped to it's module identifier. If the quota from a <code>module</code> was requested, a JSON array containing all [[#AccountQuota | account quotas]] of this module are returned. If both a <code>module</code> and <code>account</code> were requested, a JSON object representing this specific [[#AccountQuota | account auota]] is returned. <br />
<br />
Note: In case there is no quota limitation defined for a module or account, no corresponding JSON object is included in the response. <br />
<br />
<br />
{| id="ModuleQuota" cellspacing="0" border="1"<br />
|+ align="bottom" | Module Quota<br />
! Field !! Type !! Description<br />
|-<br />
| display_name || String || The display name of the module<br />
|-<br />
| accounts|| Array || Each element identifies an account quota within the module, as described in [[#AccountQuota | Account Quota]]<br />
|-<br />
|}<br />
<br />
<br />
{| id="AccountQuota" cellspacing="0" border="1"<br />
|+ align="bottom" | Account Quota<br />
! Field !! Type !! Description<br />
|-<br />
| account_id || String || Identifier of the account<br />
|-<br />
| account_name || String || Name of the account<br />
|-<br />
| countquota || Number || The account's quota limit for the number of items, or not set if not defined<br />
|-<br />
| countuse || Number || The account's actual usage for the number of items, or not set if no count quota defined<br />
|-<br />
| quota || Number || The account's quota limit for the storage in bytes, or not set if not defined<br />
|-<br />
| use || Number || The account's actual usage for the storage in bytes, or not set if no storage quota defined<br />
|-<br />
|}<br />
<br />
<br />
=== Get the filestore usage data ===<br />
<br />
GET <code>/ajax/quota?action=filestore</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: A JSON Object containing the fields “use” and “quota”. “use” represents the uploaded files sizes sum and the field “quota” represents the maximum.<br />
<br />
=== Get the mail usage data ===<br />
<br />
GET <code>/ajax/quota?action=mail</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: A JSON Object containing the fields “use” and “quota”. “use” represents the use mail quota and the field “quota” represents the maximum. -1 represents an unlimited quota.<br />
<br />
== Module "import"==<br />
The module import allows to import specific module data (like Contacts, Tasks or Appointments) in several formats (iCal, vCard, CSV) into a folder. Please note: The callback for all actions of this bundle is callback_import, not callback_$actionname for legacy purposes.<br />
<br />
=== Import CSV ===<br />
POST <code>/ajax/import?action=CSV</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder into which data should be imported. This must be a Contact folder.<br />
<br />
Request body: A "multipart/form-data" encoded .CSV file. The field name for the file is "file". The column titles of the table are those used within the OX, see column ''Displayed Name'' in [[#DetailedContactData]].<br />
<br />
Response: An array of JSON-Objects, one for each entry in the list, containing: The Object ID of the entry, the Object ID of the folder the data was written into, a timestamp of the modification (in case of error, of modification attempt) and an error in case the data could not be entered.<br />
<br />
=== Import Outlook CSV ===<br />
POST <code>/ajax/import?action=OUTLOOK_CSV</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder into which data should be imported. This must be a Contact folder.<br />
<br />
Request body: An .CSV file with Windows' default encoding Windows-1252. The column titles of the table may be those used by the English, French or German version of Outlook.<br />
<br />
Response: An array of JSON-Objects, one for each entry in the list, containing: The Object ID of the entry, the Object ID of the folder the data was written into, a timestamp of the modification (in case of error, of modification attempt) and an error in case the data could not be entered.<br />
<br />
=== Import iCAL ===<br />
POST <code>/ajax/import?action=ICAL</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder into which data should be imported. This may be an Appointment or a Task folder. May even be a list containing both.<br />
* <code>suppressNotification</code> – This optional parameter can be used to disable the notifications for new appointments that are imported through the given iCal file. This help keeping the Inbox clean if a lot of appointments need to be imported. The value of this parameter does not matter because only for the existence of the parameter is checked.<br />
* <code>ignoreUIDs</code> – Optional. When set to "true", UIDs are partially ignored during import of tasks and appointments from iCal. Internally, each UID is replaced statically by a random one to preserve possibly existing relations between recurring appointments in the same iCal file, but at the same time to avoid collisions with already existing tasks and appointments.<br />
<br />
Request body: An iCalendar file.<br />
<br />
Response: An array of JSON-Objects, one for each entry in the list, containing: The Object ID of the entry, the Object ID of the folder the data was written into, a timestamp of the modification (in case of error, of modification attempt) and an error in case the data could not be entered, and warnings (under the key "warnings") containing an Array of objects with the warning data, containing all customary error fields.<br />
<br />
=== Import vCard ===<br />
POST <code>/ajax/import?action=VCARD</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder into which data should be imported. This must be a Contact folder.<br />
<br />
Request body: An vCard file, maybe of the formats: vCard 2.1, vCard 3.0 or vCalendar 1.0<br />
<br />
Response: An array of JSON-Objects, one for each entry in the list, containing: The Object ID of the entry, the Object ID of the folder the data was written into, a timestamp of the modification (in case of error, of modification attempt) and an error in case the data could not be entered.<br />
<br />
== Module "export" ==<br />
The module export allows to export specific module data (like Contacts, Tasks or Appointments) from a folder in several formats (iCal, vCard, CSV).<br />
<br />
=== Exporting CSV ===<br />
GET <code>/ajax/export?action=CSV</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder whose contents are to be exported. This must be a Contact folder.<br />
* <code>columns</code> – (optional) Columns to be imported from the given file, given as an array of column numbers. See [[#DetailedContactData | Detailed contact data]] for numbers.<br />
* <code>export_dlists</code> – (optional) toggles whether distribution lists are exported, too. Default is false. Option exists since 7.4.1.<br />
Response: An InputStream containing the file of the MIME type <code>text/csv</code>.<br />
<br />
=== Exporting iCAL ===<br />
GET <code>/ajax/export?action=ICAL</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder whose contents are to be exported. This must be a Calendar folder.<br />
<br />
Response: An InputStream containing the file, of the MIME type <code>text/calendar</code>.<br />
<br />
=== Exporting vCard ===<br />
GET <code>/ajax/export?action=VCARD</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder whose contents are to be exported. This must be a Contact folder.<br />
<br />
Response: An InputStream containing the file, of the MIME type <code>text/x-vcard</code>.<br />
<br />
== Module "sync" ==<br />
The module sync delivers several core API extensions to support common operations used in a mobile synchronization environment.<br />
<br />
=== Clearing a folder's content ===<br />
PUT <code>/ajax/sync?action=refresh_server</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON array containing the folder ID(s) whose content should be cleared. '''NOTE:''' Although the requests offers to clear multiple folders at once it is recommended to clear only one folder per request since if any exception occurs<br />
(e.g. missing permissions) the complete request is going to be aborted.<br />
<br />
Response: A JSON array containing the IDs of folders that could not be cleared due to a concurrent modification. Meaning you receive an empty JSON array if everything worked well.<br />
<br />
== Module "token" (since 7.4.0) ==<br />
The module token delivers several core API extensions to support token based logins.<br />
<br />
=== Get a login token ===<br />
GET <code>/ajax/token?action=acquireToken</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response:<br />
A JSON object with the timestamp of the creation date and a token which can be used to create a new session.<br />
<br />
== Module "mailfilter" ==<br />
The module mailfilter describes how to add, update or delete mail filter rules or to check which actions are supported by the underlying system.<br />
<br />
A detailed description can be found here [[ HTTP_API_MailFilter | Mail Filter HTTP API]]<br />
<br />
== Module "ajax file upload" ==<br />
This module offers to store files in server's dedicated download directory for a configureable amount of time. The files are then accessible for further operations like inline images in (html) mails<br />
<br />
=== Uploading a file ===<br />
POST <code>/ajax/file?action=new</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>module</code> – The module for which the file is uploaded to determine proper upload quota constraints (e.g. "mail", "infostore", etc.).<br />
* <code>type</code> – The file type filter to define which file types are allowed during upload. Currently supported filters are: <code>file=all, text=text/*, media=image OR audio OR video, image=image/*, audio=audio/*, video=video/*, application=application/*</code><br />
<br />
Request body: A common POST request body of MIME type "multipart/*" which holds the file(s) to upload<br />
<br />
Response: A JSON array containing the IDs of the uploaded files. The files are accessible through the returned IDs for future use.<br />
<br />
=== Updating a file's last access timestamp (keep alive) ===<br />
By updating the last access timestamp it's prevented from being deleted from both session and disk storage.<br />
<br />
GET <code>/ajax/file?action=keepalive</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the uploaded file whose timestamp should be updated<br />
<br />
Response: The string "null" in response's data element<br />
<br />
=== Requesting a formerly uploaded file ===<br />
GET <code>/ajax/file?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the uploaded file<br />
<br />
Response: The content of the requested file is directly written into output stream<br />
<br />
== Module "image" ==<br />
This module allows to download images from Open-Xchange server without providing a session ID in request's URL parameters.<br />
<br />
=== Requesting an image ===<br />
GET <code>/ajax/image</code> <br />
<br />
Parameters:<br />
* <code>uid</code> – The unique ID referring to the desired image<br />
<br />
Response: The content of the requested image is directly written into output stream<br />
<br />
== Module "conversion" (preliminary) ==<br />
<br />
A generic module to request data from a data source and to process obtained/submitted data with a data handler. Thus data is converted from a data source by a data handler.<br />
<br />
=== Converting data ===<br />
PUT <code>/ajax/conversion?action=convert</code><br><br />
or<br><br />
POST <code>/ajax/conversion?action=convert</code> <br />
<br />
Parameters: &lt;no parameters required&gt;<br />
<br />
Request body: A [[#ConversionRequest | conversion request]] JSON object containing nested JSON objects for [[#DataSource | data source]] and [[#DataHandler | data handler]]<br />
<br />
<br />
{| id="ConversionRequest" cellspacing="0" border="1"<br />
|+ align="bottom" | Conversion request object<br />
! Field !! Type !! Description<br />
|-<br />
| datasource || JSON object || The data source object.<br />
|-<br />
| datahandler || JSON object || The data handler object.<br />
|-<br />
|}<br />
<br />
<br />
{| id="DataSource" cellspacing="0" border="1"<br />
|+ align="bottom" | Data source object<br />
! Field !! Type !! Description<br />
|-<br />
| identifier || String || The identifier of the data source.<br />
|-<br />
| args || JSON array or JSON object || The '''optional''' name-value-pairs as a single JSON object or a JSON object for each kept inside a JSON array for data source<br />
|-<br />
|}<br />
<br />
<br />
{| id="DataHandler" cellspacing="0" border="1"<br />
|+ align="bottom" | Data handler object<br />
! Field !! Type !! Description<br />
|-<br />
| identifier || String || The identifier of the data handler.<br />
|-<br />
| args || JSON array or JSON object || The '''optional''' name-value-pairs as a single JSON object or a JSON object for each kept inside a JSON array for data handler<br />
|-<br />
|}<br />
<br />
Response: The result of converted data ready as an appropriate JSON response<br />
<br />
==== Saving an ICal email attachment ====<br />
<br />
If an ICal file is attached to an email, its content can be saved as appointments and tasks into given calendar and task folder.<br />
If the fields "com.openexchange.groupware.calendar.confirmstatus" and "com.openexchange.groupware.calendar.confirmmessage" are set, the data handler inserts the appointment with the given status for the user, if the appointment does not exist. If it is already existing, the handler just updates the participant status.<br />
<br />
Data source's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.mail.ical&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.fullname&quot;:&quot;&lt;folder-fullname&gt;&quot;},<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.mailid&quot;:&quot;&lt;mail-id&gt;&quot;},<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.sequenceid&quot;:&quot;&lt;attachment-sequence-id&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Data handler's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.ical&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.groupware.calendar.folder&quot;:&quot;&lt;calendar-folder-id&gt;&quot;},<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.task.folder&quot;:&quot;&lt;task-folder-id&gt;&quot;},<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.calendar.confirmstatus&quot;:&quot;&lt;status&gt;&quot;},<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.calendar.confirmmessage&quot;:&quot;&lt;message&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Response: A JSON array of JSON objects each providing folder and object ID of added appointment/task; e.g. <code>[{&quot;folder_id&quot;:2567, &quot;id&quot;:7689}, ...]</code><br />
<br />
==== Converting an ICal email attachment into JSON objects ====<br />
<br />
If an ICal file is attached to an email, its content can converted to JSON appointments and tasks.<br />
<br />
Data source's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.mail.ical&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.fullname&quot;:&quot;&lt;folder-fullname&gt;&quot;}<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.mailid&quot;:&quot;&lt;mail-id&gt;&quot;}<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.sequenceid&quot;:&quot;&lt;attachment-sequence-id&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Data handler's JSON object.<br><br />
'''Note''' that all arguments are optional: Default is user time zone and zero recurrence position<br><br />
"com.openexchange.groupware.calendar.searchobject" triggers a search for the uid, and replaces the object_id and folder_id with the data of the corresponding ox-object id, if existing. The returned objects are still the ical objects and NOT the ox-objects.<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.ical.json&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.groupware.calendar.timezone&quot;:&quot;&lt;timezone-id&gt;&quot;}<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.calendar.recurrencePosition&quot;:&quot;&lt;recurrence-position&gt;&quot;}<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.calendar.searchobject&quot;:&quot;&lt;true|false&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Response: A JSON array of JSON objects for each appointment/task as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]]/[[##DetailedAppointmentData | Detailed appointment data]]<br />
<br />
==== Saving a VCard email attachment ====<br />
<br />
If a VCard file is attached to an email, its content can be saved as contacts into given contact folder.<br />
<br />
Data source's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.mail.vcard&quot;,<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.fullname&quot;:&quot;&lt;folder-fullname&gt;&quot;},<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.mailid&quot;:&quot;&lt;mail-id&gt;&quot;},<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.sequenceid&quot;:&quot;&lt;attachment-sequence-id&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Data handler's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.contact&quot;,<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.groupware.contact.folder&quot;:&quot;&lt;contact-folder-id&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Response: A JSON array of JSON objects each providing folder and object ID of added contact; e.g. <code>[{&quot;folder_id&quot;:2567, &quot;id&quot;:7689}, ...]</code><br />
<br />
==== Contact(s) attached to a new email as a VCard file ====<br />
<br />
Obtain VCard data from specified contact object(s).<br />
<br />
Data source's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.contact&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;folder&quot;:&quot;&lt;folder-id1&gt;&quot;,&quot;id&quot;:&quot;&lt;id1&gt;&quot;}<br><br />
&nbsp;&nbsp;&nbsp;...<br><br />
&nbsp;&nbsp;&nbsp;{&quot;folder&quot;:&quot;&lt;folder-idn&gt;&quot;,&quot;id&quot;:&quot;&lt;idn&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Get a new email's JSON object with specified VCard data source attached.<br />
<br />
Data handler's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.mail.vcard&quot;<br><br />
&nbsp;&quot;args&quot;:[]<br><br />
}<br><br />
</code><br />
<br />
Response: A [[#DetailedMailData | mail]] JSON object.<br />
<br />
== Module "search" (preliminary) ==<br />
<br />
The search module is an enhancement to each search request as an optional JSON object via PUT method to filter elements; e.g.<br />
<br />
<code><br />
PUT /ajax/contacts?action=all&...<br />
<br />
{"filter":{search-term-object}}<br />
</code><br />
<br />
This section describes the syntax of the optional JSON object representing the search term.<br><br />
In general the structure of a search term is in prefix notation; meaning the operator is written before its operands:<br />
<br />
<code>{"operation":"equals","operands":[...]}</code><br />
<br />
Moreover there are two different types of a search terms:<br />
* A single search term<br />
* A composite search term<br />
<br />
A single search term reflects an operation which cannot hold nested search terms as operands; e.g. "equals". In opposite to this a composite search term holds one or more nested search terms as operands; e.g. "not" or the logical junctors "and"/"or".<br />
<br />
By now the following operations are supported:<br />
* composite operations<br />
** "and" - The AND junctor<br />
** "or" - The OR junctor<br />
** "not" - Negation<br />
* single operations<br />
** "equals" - Equals comparison<br />
** "lt" - Less-than comparison<br />
** "gt" - Greater-than comparison<br />
<br />
Furthermore following operand types are supported for single search terms:<br />
* Column - Providing a name referring to a field/column<br />
* Constant - A constant<br />
<br />
Example of an EQUALS search term:<br><br />
<code><br />
{"operation":"equals","operands":[{"type":"column","value":"first_name"},"Jane"]}<br />
</code><br />
<br />
Example of an OR search term:<br><br />
<code><br />
{"operation":"or","operands":<br><br />
&nbsp;[<br><br />
&nbsp;&nbsp;{"operation":"equals","operands":[{"type":"column","value":"first_name"},"Jane"]},<br><br />
&nbsp;&nbsp;{"operation":"gt","operands":[{"type":"column","value":"birthday"},"1975-05-01"]}<br><br />
&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
<br />
Refer to object data tables introduced by different modules to know which field names are supported; e.g. for tasks it is [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]], and [[#DetailedTaskData | Detailed task data]].<br />
<br />
== Module "search" (alternative suggestion, still preliminary) ==<br />
<br />
The search module is an enhancement to each search request as an optional JSON object via PUT method to filter elements; e.g.<br />
<br />
<code><br />
PUT /ajax/contacts?action=all&...<br />
<br />
{"filter":<i>[search term]</i>}<br />
</code><br />
<br />
This section describes the syntax of the optional JSON object representing the search term.<br />
In general the structure of a search term is in prefix notation; meaning the operator is written before its operands:<br />
<br />
<code>[">", 5, 2]</code><br />
<br />
The available operators are:<br />
* Comparison operators ">", "<", "=", "<=", ">=", "<>"<br />
* logic operators "not", "and", "or"<br />
<br />
Comparison operators have exactly two operands. Each operand can be either a field name or a constant. A field name is an object with the member "field" specifying the field name, e.g. <code>{ field: "first_name" }</code>. The available field names depend on the searched module. Primitive JSON types are interpreted as constants. Arrays are not valid operands for comparison operators.<br />
<br />
The logic operator "not" has exactly one operand, the other logic operators can have any number of operands. Each operand must be an array representing a nested search expression.<br />
<br />
== Module "mail account" (available with v6.12) ==<br />
<br />
The mail account module is used to manage multiple mail accounts held by a user.<br />
<br />
=== Get All mail accounts ===<br />
<br />
GET <code>/ajax/account?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for mail account's are defined in [[#MailAccountData | mail account data]].<br />
<br />
Response: An array with attachment data. Each array element describes one mail account and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a mail account ===<br />
<br />
GET <code>/ajax/account?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the account to return.<br />
<br />
Response: A JSON object representing the desired mail account. See [[#MailAccountData | mail account data]].<br />
<br />
{| id="MailAccountData" cellspacing="0" border="1"<br />
|+ align="bottom" | Mail account data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 1001 || id || Number || Account ID<br />
|-<br />
| 1002 || login || String || The login.<br />
|-<br />
| 1003 || password || String || The (optional) password.<br />
|-<br />
| 1004 || mail_url || String || The mail server URL; e.g. "imap://imap.somewhere.com:143". '''URL is preferred over single fields''' (like mail_server, mail_port, etc.)<br />
|-<br />
| 1005 || transport_url || String || The transport server URL; e.g. "smtp://smtp.somewhere.com:25". '''URL is preferred over single fields''' (like transport_server, transport_port, etc.)<br />
|-<br />
| 1006 || name || String || Account's display name.<br />
|-<br />
| 1007 || primary_address || String || User's primary address in account; e.g. "someone@somewhere.com"<br />
|-<br />
| 1008 || spam_handler || String || The name of the spam handler used by account.<br />
|-<br />
| 1009 || trash || String || The name of the default trash folder.<br />
|-<br />
| 1010 || sent || String || The name of the default sent folder.<br />
|-<br />
| 1011 || drafts || String || The name of the default drafts folder.<br />
|-<br />
| 1012 || spam || String || The name of the default spam folder.<br />
|-<br />
| 1013 || confirmed_spam || String || The name of the default confirmed-spam folder.<br />
|-<br />
| 1014 || confirmed_ham || String || The name of the default confirmed-ham folder.<br />
|-<br />
| 1015 || mail_server || String || The mail server's hostname or IP address.<br />
|-<br />
| 1016 || mail_port || Number || The mail server's port.<br />
|-<br />
| 1017 || mail_protocol || String || The mail server's protocol. '''Always use basic protocol name.''' E.g. use "imap" instead of "imaps"<br />
|-<br />
| 1018 || mail_secure || Boolean || Whether to establish a secure connection to mail server (SSL, TLS).<br />
|-<br />
| 1019 || transport_server || String || The transport server's hostname or IP address.<br />
|-<br />
| 1020 || transport_port || Number || The transport server's port.<br />
|-<br />
| 1021 || transport_protocol || String || The transport server's protocol. '''Always use basic protocol name.''' E.g. use "smtp" instead of "smtps"<br />
|-<br />
| 1022 || transport_secure || Boolean || Whether to establish a secure connection to transport server (SSL, TLS).<br />
|-<br />
| 1023 || transport_login || String || The transport login. If empty "login" is taken as transport login as well.<br />
|-<br />
| 1024 || transport_password || String || The transport password. If empty "password" is taken as transport password as well.<br />
|-<br />
| 1025 || unified_inbox_enabled || Boolean || If enabled for Unified INBOX<br />
|-<br />
| 1026 || trash_fullname || String || Path to default trash folder. Preferred over "trash"<br />
|-<br />
| 1027 || sent_fullname || String || Path to default sent folder. Preferred over "sent"<br />
|-<br />
| 1028 || drafts_fullname || String || Path to default drafts folder. Preferred over "drafts"<br />
|-<br />
| 1029 || spam_fullname || String || Path to default spam folder. Preferred over "spam"<br />
|-<br />
| 1030 || confirmed_spam_fullname || String || Path to default confirmed-spam folder. Preferred over "confirmed_spam"<br />
|-<br />
| 1031 || confirmed_ham_fullname || String || Path to default confirmed-ham folder. Preferred over "confirmed_ham"<br />
|-<br />
| 1032 || pop3_refresh_rate || Number || The interval in minutes the POP3 account is refreshed<br />
|-<br />
| 1033 || pop3_expunge_on_quit || Boolean || Whether POP3 messages shall be deleted on actual POP3 account after retrieval or not<br />
|-<br />
| 1034 || pop3_delete_write_through || Boolean || If option "pop3_expunge_on_quit" is disabled, this property defines whether a delete in local INBOX also deletes affected message in actual POP3 account<br />
|-<br />
| 1035 || pop3_storage || String || The name of POP3 storage provider, default is "mailaccount"<br />
|-<br />
| 1036 || pop3_path || String || Path to POP3's virtual root folder in storage, default is name of the POP3 account beside default folders<br />
|-<br />
| 1037 || personal || String || The customizable personal part of email address<br />
|-<br />
| 1038 || reply_to || String || The customizable reply-to email address<br />
|-<br />
| 1039 || addresses || String || The comma-separated list of available E-Mail addresses including aliases. !! Only available for primary mail account !!<br />
|}<br />
<br />
=== Create a new mail account ===<br />
<br />
PUT <code>/ajax/account?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request: A JSON object describing the new account to create. See [[#MailAccountData | mail account data]].<br />
<br />
Response: A JSON object representing the inserted mail account. See [[#MailAccountData | mail account data]].<br />
<br />
=== Update a mail account ===<br />
<br />
PUT <code>/ajax/account?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request: A JSON object identifiying (field ID is present) and describing the account to update. See [[#MailAccountData | mail account data]].<br />
<br />
Response: A JSON object representing the updated mail account. See [[#MailAccountData | mail account data]].<br />
<br />
=== Delete a mail account ===<br />
<br />
PUT <code>/ajax/account?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An array with the ID of the mail account to delete.<br />
<br />
=== Validate a mail account (which shall be created) ===<br />
<br />
PUT <code>/ajax/account?action=validate</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>tree</code> - An optional boolean parameter which indicates whether on successful validation the folder tree shall be returned (NULL on failure) or if set to "false" or missing only a boolean is returned which indicates validation result<br />
<br />
Request: A JSON object describing the new account to validate. See [[#MailAccountData | mail account data]].<br />
<br />
Response: Dependent on optional "tree" parameter a JSON folder object or a boolean value indicating the validation result<br />
<br />
The JSON folder object corresponding to [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
Additionally a field "subfolder_array" is added which contains possible subfolders. This field is missing if a folder contains no subfolders.<br />
<br />
[[Category: OX6]]<br />
<br />
== Module Auto Configuration (since 6.22) ==<br />
<br />
=== Get Auto Configuration ===<br />
<br />
GET <code>/ajax/autoconfig?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>email</code> – Email Adress for which a mail configuration will be discovered.<br />
* <code>password</code> – Corresponding password for the mail account (optional)<br />
<br />
Response: A JSON Object containing the best available settings for an appropriate mail Server for the given email address. The fields are described in [[#MailAccountData | mail account data]]. The Data may be incomplete or even empty.<br />
<br />
== Module "user" (available with v6.14) ==<br />
<br />
The user module is used to access user information.<br />
<br />
=== Get all users ===<br />
<br />
GET <code>/ajax/user?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for users are defined in [[#CommonObjectData | Common object data]], [[#DetailedContactData | Detailed contact data]] and [[#DetailedUserData | Detailed user data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response with timestamp: An array with user data. Each array element describes one user and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedUserData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed user data<br />
! ID !! Displayed name !! Name !! Type !! Value<br />
|-<br />
| 610 || Aliases || aliases || Array || The user's aliases<br />
|-<br />
| 611 || Time zone || timezone || String || The time zone ID.<br />
|-<br />
| 612 || Locale || locale || String || The name of user's entire locale, with the language, country and variant separated by underbars. E.g. "en", "de_DE"<br />
|-<br />
| 613 || Groups || groups || Array || The IDs of user's groups<br />
|-<br />
| 614 || Contact ID || contact_id || Number || The contact ID of the user<br />
|-<br />
| 615 || Login info || login_info || String || The user's login information<br />
|}<br />
<br />
=== Get a list of users ===<br />
<br />
PUT <code>/ajax/user?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for users are defined in [[#CommonObjectData | Common object data]], [[#DetailedContactData | Detailed contact data]] and [[#DetailedUserData | Detailed user data]].<br />
<br />
Request body: An array of numbers. Each number is the ID of requested user. Since v6.18.1, a <code>null</code> value in the array is interpreted as the currently logged in user.<br />
<br />
Response with timestamp: An array with user data. Each array element describes one user and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a user ===<br />
<br />
GET <code>/ajax/user?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested user. Since v6.18.1, this parameter is optional: the default is the currently logged in user.<br />
<br />
Response with timestamp: An object containing all data of the requested user. The fields of the object are listed in [[#CommonObjectData | Common object data]], [[#DetailedContactData | Detailed contact data]] and [[#DetailedUserData | Detailed user data]].<br />
<br />
=== Update a user ===<br />
<br />
PUT <code>/ajax/user?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated user.<br />
* <code>timestamp</code> – Timestamp of the updated user. If the user was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: User object as described in [[#CommonObjectData | Common object data]], [[#DetailedContactData | Detailed contact data]] and [[#DetailedUserData | Detailed user data]]. Only modified fields are present.<br />
<br />
'''Note''': "timezone" and "locale" are the only fields from [[#DetailedUserData | Detailed user data]] which are allowed to be updated.<br />
<br />
Response with timestamp: An empty object.<br />
<br />
=== Search users ===<br />
<br />
PUT <code>/ajax/user?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified. In case of use of column 609 (use count depending order for collected users with global address book) the parameter "order" ist NOT necessary and will be ignored.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Request body: An Object as described in [[#SearchUsers | Search users]].<br />
<br />
{| id="SearchUsers" cellspacing="0" border="1"<br />
|+ align="bottom" | Search users<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find users. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|-<br />
| startletter || String || Search users with the given startletter. If this field is present, the pattern is matched against the user field which is specified by the property contact_first_letter_field on the server (default: last name). Otherwise, the pattern is matched against the display name.<br />
|}<br />
<br />
Alternative request body: An Object as described in [[#SearchUsersAlternative | Search users alternative]].<br />
<br />
{| id="SearchUsersAlternative" cellspacing="0" border="1"<br />
|+ align="bottom" | Search users alternative<br />
! Name !! Type !! Value<br />
|-<br />
| last_name || String || Searches users where the last name match with the given last name.<br />
|-<br />
| first_name || String || Searches users where the first name match with the given first name.<br />
|-<br />
| display_name || String || Searches users where the display name match with the given display name.<br />
|-<br />
| orSearch || Boolean || If set to true, the fields are connected through an OR search habit.<br />
|-<br />
| emailAutoComplete || Boolean || If set to true, results are guaranteed to contain at least one email adress and the search is performed by connecting the relevant fields through an OR search habit.<br />
|}<br />
<br />
Response: An array with user data. Each array element describes one user and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get user attribute (available with v6.20) ===<br />
<br />
GET <code>/ajax/user?action=getAttribute</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – ID of the user. <br />
* <code>name</code> – The attribute name. <br />
<br />
Response without timestamp: A JSON object providing name and value of the requested attribute<br />
<pre><br />
{ "name":"somename", "value":"somevalue"}<br />
</pre><br />
<br />
=== Set user attribute (available with v6.20) ===<br />
<br />
PUT <code>/ajax/user?action=setAttribute</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – ID of the user. <br />
* <code>setIfAbsent</code> - Set to "true" to put the value only if the specified name is not already associated with a value, otherwise "false" to put value in any case<br />
<br />
Request body: A JSON object providing name and value of the attribute. If the <code>"value"</code> field id missing or NULL, the attribute is removed.<br />
<pre><br />
{ "name":"somename", "value":"somevalue"}<br />
</pre><br />
<br />
Response: The boolean value "true" if PUT was successful; otherwise "false"<br />
<br />
== Module "OAuth" (available with v6.20) ==<br />
<br />
The OAuth module is used to manage multiple OAuth accounts for certian online services for a user. The OAuth mechanism allows the Open-Xchange application to act as behalf of this user using previously obtained access tokens granted by user.<br />
<br />
The OAuth interface is divided into two parts: Account access and service's meta data access.<br />
<br />
=== OAuth account access ===<br />
<br />
The OAuth service account access description.<br />
<br />
<br />
==== Get all OAuth accounts ====<br />
<br />
GET <code>/ajax/oauth/accounts?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – The <b>optional</b> service meta data identifier. If missing all accounts of all services are returned; otherwise all accounts of specified service are returned<br />
<br />
Response: An array with account data. Each array element is a JSON object describing an OAuth account as specified in [[#OAuthAccountData | OAuth account data]].<br />
<br />
==== Get an OAuth account ====<br />
<br />
GET <code>/ajax/oauth/accounts?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The account identifier.<br />
<br />
Response: A JSON object describing an OAuth account as specified in [[#OAuthAccountData | OAuth account data]].<br />
<br />
{| id="OAuthAccountData" cellspacing="0" border="1"<br />
|+ align="bottom" | OAuth account<br />
! Field !! Type !! Description<br />
|-<br />
| id || Number || The numeric identifier of the OAuth account.<br />
|-<br />
| displayName || String || The account display name<br />
|-<br />
| serviceId || String || The identifier of the associated service meta data; e.g. <code>"com.openexchange.oauth.twitter"</code><br />
|-<br />
| token || String || The token<br />
|-<br />
| secret || String || The token secret<br />
|-<br />
|}<br />
<br />
==== Delete an OAuth account ====<br />
<br />
PUT <code>/ajax/oauth/accounts?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The account identifier.<br />
<br />
Response: The boolean value "true" if successful<br />
<br />
==== Update an OAuth account ====<br />
<br />
PUT <code>/ajax/oauth/accounts?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The account identifier. May also be provided in request body's JSON OAuth account representation by <code>"id"</code> field.<br />
<br />
Request body: A JSON object providing the OAuth account fields to update. See [[#OauthAccountData | OAuth account data]]. Currently the only values which make sende being updated are <code>"displayName"</code> and the <code>"token"</code>-<code>"secret"</code>-pair.<br />
<br />
Response: The boolean value "true" if successful<br />
<br />
==== Initialize creation of an OAuth account ====<br />
<br />
GET <code>/ajax/oauth/accounts?action=init</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – The service meta data identifier; e.g. <code>"com.openexchange.oauth.twitter"</code><br />
<br />
Response: An JSON representation of the resulting interaction providing needed information to complete account creation. See [[#OauthInteractionData | OAuth interaction data]].<br />
<br />
{| id="OauthInteractionData" cellspacing="0" border="1"<br />
|+ align="bottom" | OAuth interaction<br />
! Field !! Type !! Description<br />
|-<br />
| authUrl || String || The numeric identifier of the OAuth account.<br />
|-<br />
| type || String || The interaction type name; <code>"outOfBand"</code> or <code>"callback"</code><br />
|-<br />
| token || String || The token<br />
|-<br />
| uuid || String || The UUID for this OAuth interaction<br />
|-<br />
|}<br />
<br />
==== Create an OAuth account ====<br />
<br />
Note: This action is typically called by provided call-back URL and is ony intended for manual invocation if "outOfBand" interaction is returned by preceeding <code>/ajax/oauth/account?action=init</code> step.<br />
<br />
PUT <code>/ajax/oauth/accounts?action=create</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module<br />
* <code>oauth_token</code> – The request token from preceeding OAuth interaction<br />
* <code>uuid</code> – The UUID of the preceeding OAuth interaction<br />
* <code>oauth_verfifier</code> – The verifier string which confirms that user granted access<br />
* <code>displayName</code> – The display name for the new account<br />
<br />
Response: A JSON object describing the newly created OAuth account as specified in [[#OAuthAccountData | OAuth account data]].<br />
<br />
=== OAuth service meta data access ===<br />
<br />
The OAuth service meta data access description.<br />
<br />
<br />
==== Get all OAuth services' meta data ====<br />
<br />
GET <code>/ajax/oauth/services?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: An array with service data. Each array element is a JSON object describing an OAuth service's meta data as specified in [[#OAuthServiceMetaData | OAuth service meta data]].<br />
<br />
==== Get an OAuth service's meta data ====<br />
<br />
GET <code>/ajax/oauth/services?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The service's identifier.<br />
<br />
Response: A JSON object describing an OAuth service's meta data as specified in [[#OAuthServiceMetaData | OAuth service meta data]].<br />
<br />
{| id="OAuthServiceMetaData" cellspacing="0" border="1"<br />
|+ align="bottom" | OAuth service meta data<br />
! Field !! Type !! Description<br />
|-<br />
| id || Number || The numeric identifier of the OAuth account.<br />
|-<br />
| displayName || String || The account display name<br />
|-<br />
|}<br />
<br />
== Module "JSlob" (available with v6.22) ==<br />
<br />
The JSlob module is used to store&retrieve arbitrary JSON-structured configuration for a single user.<br />
<br />
<br />
=== Get all JSLobs ===<br />
<br />
GET <code>/ajax/jslob?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
<br />
<br />
Response: An array with JSON configurations. Each array element is a JSON object representing a certain configuration consisting if a "id" and "jslob" field. See [[#JSlobData | JSlob data ]]<br />
<br />
{| id="JSlobData" cellspacing="0" border="1"<br />
|+ align="bottom" | JSlob data<br />
! Field !! Type !! Description<br />
|-<br />
| id || String or Number || The identifier of the JSlob.<br />
|-<br />
| jslob || JSON object || The JSON configuration.<br />
|-<br />
|}<br />
<br />
=== List denoted JSLobs ===<br />
<br />
PUT <code>/ajax/jslob?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
<br />
<br />
Request body: A JSON array of JSlob identifiers; e.g. <code>[ "1", "2", … ]</code><br />
<br />
Response: An array with JSON configurations. Each array element is a JSON object representing a certain configuration consisting if a "id" and "jslob" field. See [[#JSlobData | JSlob data ]]<br />
<br />
=== Delete a JSlob ===<br />
<br />
PUT <code>/ajax/jslob?action=set</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
* <code>id</code> – The JSlob identifier.<br />
<br />
<br />
Request body: An empty request body<br />
<br />
Response: Nothing<br />
<br />
=== Store a JSlob ===<br />
<br />
PUT <code>/ajax/jslob?action=set</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
* <code>id</code> – The identifier for the new JSlob to create<br />
<br />
<br />
Request body: A JSON object containing the "path" and "value" of the JSON configuration to store. If "path" is missing the current configuration<br />
is merged with given JSON object.<br />
<br />
Response: Nothing<br />
<br />
=== Update a single value inside a JSlob ===<br />
<br />
PUT <code>/ajax/jslob?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
* <code>id</code> – The identifier for the new JSlob to create<br />
<br />
<br />
Request body: The new value to store inside specified JSlob<br />
<br />
Response: A JSlob representation according to [[#JSlobData | JSlob data ]]<br />
<br />
=== REST-like access to JSlob module ===<br />
<br />
to be done...<br />
<br />
<br />
== Module "freebusy" (available with v6.22.1) ==<br />
<br />
Provides access to free/busy information.<br />
<br />
<br />
=== Get free/busy information ===<br />
<br />
GET <code>/ajax/freebusy?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>participant</code> – The participant to get the free/busy data for. May be either an internal user-, group- or resource-ID, or an e-mail address for external participants.<br />
* <code>from</code> – The lower (inclusive) limit of the requested time-range.<br />
* <code>until</code> – The upper (exclusive) limit of the requested time-range.<br />
* <code>merged</code> (optional) – True or False. Whether to pre-process the free/busy data on the server or not. This includes sorting as well as merging overlapping free/busy intervals.<br />
<br />
Response: An array of free/busy intervals as described in [[#FreeBusyInterval | Free/Busy interval]]<br />
<br />
{| id="FreeBusyInterval" cellspacing="0" border="1"<br />
|+ align="bottom" | Free/Busy interval<br />
! Name !! Type !! Value<br />
|-<br />
| start_date || Time || Start time of the interval.<br />
|-<br />
| end_date || Time || End time of the interval.<br />
|-<br />
| shown_as || Number || The busy status of this interval, one of:<br />
{| cellspacing="0" border="1"<br />
| 1 || unknown<br />
|-<br />
| 1 || reserved<br />
|-<br />
| 2 || temporary<br />
|-<br />
| 3 || absent<br />
|-<br />
| 4 || free<br />
|}<br />
|-<br />
| id || String || Object ID of the corresponding appointment if available.<br />
|-<br />
| folder_id || String || Folder ID of the corresponding appointment if available.<br />
|-<br />
| title || String || Title of the corresponding appointment if available.<br />
|-<br />
| location || String || Location of the corresponding appointment if available.<br />
|-<br />
| full_time || Boolean || True if the corresponding appointment is a whole day appointment, not present otherwise.<br />
|}<br />
<br />
<br />
=== Get a list of free/busy information ===<br />
<br />
PUT <code>/ajax/freebusy?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>from</code> – The lower (inclusive) limit of the requested time-range.<br />
* <code>until</code> – The upper (exclusive) limit of the requested time-range.<br />
* <code>merged</code> (optional) – True or False. Whether to pre-process the free/busy data on the server or not. This includes sorting as well as merging overlapping free/busy intervals.<br />
<br />
Request body: An array of participants to get the free/busy data for. Each participant may be either an internal user-, group- or resource-ID, or an e-mail address for external participants.<br />
<br />
Response: The free/busy data for all requested participants inside a JSON object with the participants as keys. Besides a combined data element for a requested group, all group members are resolved and listed seperately in the result. If the 'merged' view was requested, an additional data element named 'merged' representing a combined view for all requested participants is added to the results implicitly.<br />
<br />
<br />
== Messaging Services ==<br />
<br />
Messaging Services represent a messaging backend. The messaging services add a new folder module "messaging". <br />
<br />
A *Messaging Service* Object has the following structure:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Messaging Service<br />
! Field !! Type !! Description<br />
|-<br />
| id || String || Identifies a messagingService. Usually a String in reverse domain name notation. Example: "com.openexchange.messaging.twitter"<br />
|-<br />
| displayName || String || Human readable display name of the service. Example: "Twitter" <br />
|-<br />
| formDescription || Array || A description for dynamic form fields. Same as in PubSub <br />
|-<br />
| messagingActions || Array || An array of Strings a dynamic set of actions that are possible with messages of this service. Described in detail later on. <br />
|-<br />
|}<br />
<br />
The available JSON calls are:<br />
<br />
GET /ajax/messaging/service?action=all<br />
<br />
* session - A session ID previously obtained from the login module. <br />
<br />
Response: A standard response object containing an array of messaging service objects. <br />
<br />
<br />
GET /ajax/messaging/service?action=get<br />
<br />
* session - A session ID previously obtained from the login module. <br />
* id - The ID of the messaging service to load<br />
<br />
Response: A standard response object containing a messaging service object.<br />
<br />
== Messaging Accounts ==<br />
<br />
A messaging account represents the concrete configuration of an account of a given messaging service.<br />
A *messaging account* has the following structure:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Messaging Account<br />
! Field !! Type !! Description<br />
|-<br />
| id || Number || Identifies a given messaging account. This is not writeable and is generated by the server <br />
|-<br />
| messagingService || String || The messaging service id of the messaging service this account belongs to <br />
|-<br />
| displayName || String || User chosen String to identify a given account. Will also be translated into the folder name of the folder representing the accounts content <br />
|-<br />
| configuration || Object || Configuration data according to the formDescription of the relevant messagingService <br />
|-<br />
|}<br />
<br />
The available JSON calls are:<br />
<br />
PUT /ajax/messaging/account?action=new<br />
<br />
* session - A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON Object describing the account to be created.<br />
Response: A response object containing the new account id as its data.<br />
<br />
<br />
PUT /ajax/messaging/account?action=update<br />
<br />
* session - A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON Object describing the update to the account. Note that the "id" and "messagingService" must always be set.<br />
Response: A response object containing the number 1 as its data on success.<br />
<br />
GET /ajax/messaging/account?action=get<br />
<br />
* session - A session ID previously obtained from the login module.<br />
* messagingService - The messaging service id that the account belongs to<br />
* id - An account ID to load<br />
<br />
Response: A response object containing the JSON Object representing the loaded account as its data.<br />
<br />
GET /ajax/messaging/account?action=delete<br />
<br />
* session - A session ID previously obtained from the login module.<br />
* messagingService - The messaging service id that the account belongs to<br />
* id - An account ID to delete<br />
<br />
Response: A response object containing 1 as its data on success.<br />
<br />
GET /ajax/messaging/account?action=all<br />
<br />
* session - A session ID previously obtained from the login module<br />
* messagingService - (optional) list only those accounts that belong to the given messagingService.<br />
<br />
Response: A response object containing a JSON array of account objects in its data section.<br />
<br />
<br />
== Messaging Messages ==<br />
<br />
A Messaging Message represents a single message. It consists of some metadata, headers and a content. The content attribute varies by the content-type header. <br />
If the content type is text/* it is a string, if it is a multipart/* it is an array of objects, each representing a part of the multipart. If it is anything else<br />
it is considered binary and is a Base64 encoded string (ToDo : This is not smart enough yet. I suppose we'll have to include encoding options for binaries much like in our EAVJSONProposal).<br />
<br />
The folder id of a message follows a predefined format:<br />
<br />
<pre><br />
[messagingService]://[accountId]/[path]<br />
</pre><br />
<br />
for an imaginary example consider: "com.openexchange.messaging.twitter://535/defaultTimeline/directMessages"<br />
<br />
The structure of a Messaging Message is as follows:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Messaging Message<br />
! Field !! Type !! Description<br />
|-<br />
|id ||String || The id of this message. Only unique in the given folder. <br />
|-<br />
|folder ||String || The folder id. <br />
|-<br />
|threadLevel ||Number || The nesting level of this message according to the conversation it's belonged to. May not be set. <br />
|-<br />
|flags ||Number || Bitmask showing the state of this message. The same as in the module "mail". <br />
|-<br />
|receivedDate ||Time || The time this message was received. <br />
|-<br />
|colorLabel ||Number || An arbitrary number marking this message in a certain color. The same as the colorLabel common to all groupware objects (see HTTP API)<br />
|-<br />
|user ||Array || An array of strings. Represents user flags. <br />
|-<br />
|size ||Number || The binary size of this message in bytes. <br />
|-<br />
|picture || String || A string depicting the URL to a picture for this message <br />
|-<br />
|url || String || A string that contains a link to the messages origin. Currently used in RSS messages.<br />
|-<br />
|headers ||JSONObject || A JSON Object of header data. Usually the value is either a String or an Array (if the headers has more than one value). Certain headers are rendered as more complex structures, see the section "Complex Headers". <br />
|-<br />
|content ||String or Array || See introductory note for Messaging Messages. <br />
|-<br />
|}<br />
<br />
The structure of a Multipart Part (an element of the content array in a multipart/* message) is a s follows:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Multipart Element<br />
! Field !! Type !! Description<br />
|-<br />
|sectionId || String || The sectionId of this part.<br />
|-<br />
|headers || JSONObject || Same as above. <br />
|-<br />
|content || String or Array || Same as above. <br />
|-<br />
|}<br />
<br />
Some *Complex Headers* have a structure differing from simple key/value(s) pairs. These are:<br />
<br />
=== Content-Type ===<br />
<br />
The Content-Type header is represented as a JSON Object with the following structure:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Content Type Header<br />
! Field !! Type !! Description<br />
|-<br />
| type || String || The type string (eg. text/plain). This governs the rendering of the content of a message. <br />
|-<br />
| params || Object || An Object with the keys "charset", containing the charset of this message and "name" pointing to the filename this part or message should have. <br />
|-<br />
|}<br />
<br />
When setting the content-type header in a messaging messages generated on the client the header may also be sent in it's short form. The short form is the type followed by a semi-colon separated list of key=value pairs<br />
of the params. For example: "text/plain;charset=utf-8;name=something.txt".<br />
<br />
=== Address Headers ===<br />
<br />
Address headers ( From, To,Cc,Bcc,Reply-To,Resent-Reply-To,Disposition-Notification-To,Resent-To,Sender,Resent-Sender,Resent-To,Resent-Cc,Resent-Bcc ) are formatted as an array of objects, or in case of "From" as a single object, with the attributes *address* and *personal*:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Address Headers<br />
! Field !! Type !! Description<br />
|-<br />
| address || String || The technical part of the address<br />
|-<br />
| personal || String || A displayable description of the addressee. May be unset.<br />
|-<br />
|}<br />
<br />
When setting an address header the header may also be sent by clients in the short form <code>"personal &lt;address&gt;"</code>, for example <code>"Clark Kent &lt;clark.kent@dailyplanet.com&gt;"</code>. <br />
<br />
=== List renderings of Messaging Messages ===<br />
<br />
Actions returning lists of messages usually return only a selection of attributes of a message driven by a "columns" parameter. The columns that are addressable point either to attributes of the top-level message or its headers. <br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Header Equivalence<br />
! Column !! Refers To<br />
|-<br />
| *column* | *refers to* <br />
|-<br />
| id || The id attribute <br />
|-<br />
| folderId || The folder attribute <br />
|-<br />
| contentType || The "Content-Type" header <br />
|-<br />
| from || The "From" header <br />
|-<br />
| to || The "To" header <br />
|-<br />
| cc || The "Cc" header <br />
|-<br />
| bcc || The "Bcc" header <br />
|-<br />
| subject || The "Subject" header <br />
|-<br />
| size || The size attribute <br />
|-<br />
| sentDate || The "Date" header <br />
|-<br />
| receivedDate || The receivedDate attribute <br />
|-<br />
| flags || The flags attribute <br />
|-<br />
| threadLevel || The threadLevel attribute <br />
|-<br />
| dispositionNotificationTo || The "Disposition-Notification-To" header. <br />
|-<br />
| priority || The "X-Priority" header <br />
|-<br />
| colorLabel || The colorLabel attribute <br />
|-<br />
| url || The url attribute <br />
|-<br />
| body || The content attribute <br />
|-<br />
| headers || The headers attribute <br />
|-<br />
|}<br />
<br />
=== JSON calls ===<br />
<br />
GET /ajax/messaging/message?action=get<br />
<br />
* session - A session ID previously obtained from the login module<br />
* id - The ID of the message to load<br />
* peek - (optional) if set to "true" the read/unread state of the message will not change. Defaults to false.<br />
* folder - The folder id<br />
<br />
Response: An Object representing the loaded message.<br />
<br />
PUT /ajax/messaging/message?action=send<br />
<br />
* session - A session ID previously obtained from the login module<br />
* recipients - (optional) If set the message is sent to the given list of recipients, otherwise this defaults to the "To" header of the message.<br />
<br />
Request Body: The Request Body should contain the JSON Object representing the message to be sent.<br />
Response: "1" as the data of a regular response on success.<br />
<br />
GET or PUT /ajax/messaging/message?action=perform<br />
<br />
* session - A session ID previously obtained from the login module<br />
* action - The messaging action to invoke<br />
* id - The id of the message the action should be invoked on. Only used on actions of type "storage".<br />
* folder - The folder id.<br />
<br />
Request Body: On actions of type "message" the body should contain the JSON representation of the message the action should be applied to.<br />
Response: Either 1 if no further user interaction is needed or a messaging message that, after having the user modify it has to be supplied back to the follower action of this action.<br />
<br />
Thus, to invoke a messaging action of type "storage" the folder and id are needed. Messaging actions of type "message" need a folder and message in the body. <br />
Messaging actions of type "none" need a messaging message and account. <br />
<br />
==== List style requests ====<br />
<br />
GET /ajax/messaging/message?action=all<br />
<br />
* session - A session ID previously obtained from the login module<br />
* columns - A comma-separated list of column names.<br />
* sort - (optional) A column to sort by.<br />
* order - (optional) The order direction. "asc" for ascending or "desc" for descending. Defaults to "asc"<br />
* folder - The folder id.<br />
<br />
Response: An array of arrays with the sub arrays containing the values of the fields asked for by the the columns parameter.<br />
<br />
<br />
PUT /ajax/messaging/messages?action=list<br />
<br />
* session - A session ID previously obtained from the login module<br />
* columns - A comma-separated list of column names.<br />
<br />
Request Body: An array of arrays with the folder and id as elements each identifying a message. <br />
<br />
Response: An array of arrays with the sub arrays containing the values of the fields asked for by the columns parameter.<br />
<br />
== Snippet module (available with v7.0.0/v6.22.0) ==<br />
<br />
=== Gets a certain snippet by identifier ===<br />
<br />
GET /ajax/snippet?action=get<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
<br />
Response:<br />
The snippet's JSON representation; e.g.<br />
<br />
{<br />
"id": "1",<br />
"type": "signature",<br />
"props": {"x-custom": "any value"},<br />
"module": "mail",<br />
"displayname": "My signature",<br />
"misc": {"foo": "bar"},<br />
"createdby": 17,<br />
"content": "-- \\nMy name and position here",<br />
"accountid": 0,<br />
"shared": false,<br />
"files":<br />
[<br />
{<br />
"mimetype": "image/png; name=pic.png",<br />
"filename": "pic.png",<br />
"id": "46f49f8a-40d5-4f29-8bc9-728f3420864c",<br />
"size": 6074<br />
}<br />
]<br />
}<br />
<br />
=== Gets all snippets associated with the current user and context ===<br />
<br />
GET /ajax/snippet?action=all<br />
<br />
* session - The session identifier<br />
* type - Optional CSV of types to filter by; e.g. "signature"<br />
<br />
Response:<br />
A JSON array of snippets' JSON representations<br />
<br />
<br />
<br />
=== Gets certain snippets by identifiers ===<br />
<br />
GET /ajax/snippet?action=list<br />
<br />
* session - The session identifier<br />
<br />
Request body:<br />
A JSON array of snippet identifiers<br />
<br />
Response:<br />
A JSON array of snippets' JSON representations<br />
<br />
<br />
<br />
=== Gets a certain snippet's attachment by identifier ===<br />
<br />
GET /ajax/snippet?action=getattachment<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
* attachmentid - The attachment identifier<br />
<br />
Response:<br />
The attachment's raw data<br />
<br />
<br />
<br />
=== Creates a new snippet ===<br />
<br />
PUT /ajax/snippet?action=new<br />
<br />
* session - The session identifier<br />
<br />
Request body:<br />
A JSON representation of the snippet.<br />
Excluding its attachments (see attach/detach actions)<br />
<br />
Response:<br />
The created snippet's identifier<br />
<br />
<br />
<br />
=== Updates a certain snippet by identifier ===<br />
<br />
PUT /ajax/snippet?action=update<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
<br />
Request body:<br />
A JSON representation of the snippet providing the fields that should be changed.<br />
Excluding its attachments (see attach/detach actions)<br />
<br />
Response:<br />
The updated snippet's JSON representation<br />
<br />
<br />
<br />
=== Deletes a certain snippet by identifier ===<br />
<br />
PUT /ajax/snippet?action=delete<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier (otherwise provide one or more identifiers through request body's JSON array)<br />
<br />
Request body:<br />
A JSON array of identifiers denoting the snippets to delete<br />
<br />
Response:<br />
An empty/dummy result (don't care)<br />
<br />
<br />
<br />
=== Attaches one or more files to an existing snippet ===<br />
<br />
POST /ajax/snippet?action=attach<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
<br />
Request body:<br />
Multipart form data providing the upload files to attach to the snippet.<br />
<br />
Response:<br />
The updated snippet's identifier<br />
<br />
<br />
<br />
=== Detaches open or more files from an existing snippet ===<br />
<br />
PUT /ajax/snippet?action=detach<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
<br />
Request body:<br />
A JSON array providing the identifiers of the attachments to remove from snippet<br />
<br />
Response:<br />
The updated snippet's identifier<br />
<br />
== Picture Halo (since 7.4.1) ==<br />
<br />
GET /appsuite/api/halo/contact/picture<br />
* session - (optional) falls back to the public session cookie<br />
* internal_userid - (optional) The internal user id of a user whose picture you want to load<br />
* userid - (optional) an alias for internal_userid<br />
* user_id - (optional) an alias for internal_userid<br />
* id - (optional) a contact id<br />
* email - (optional) an email to search for. Will pick global address book matches before regular matches. After that picks the most recently changed contact<br />
* email1 - (optional) an alias for email<br />
* email2 - (optional) another email address to use to find matches<br />
* email3 - (optional) and yet another email address to use to find matches<br />
<br />
''At least one of the optional search parameters should be set. All parameters are connected by OR during the search. More specific parameters like user_id or id are prioritized in case of multiple matches.''<br />
<br />
Response:<br />
The picture with proper eTag and caching headers set, or an HTTP Status 404 response, if no picture could be found.<br />
<br />
<br />
== Module "capabilities" (available with v7.4.2) ==<br />
<br />
Provides access to capabilities, i.e. modules or features that are available on the backend and the user has access to.<br />
<br />
=== Get a capability ===<br />
<br />
GET <code>/ajax/capabilities?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The identifier of the capability<br />
<br />
Response: The requested capability as described in [[#Capability| Capability]], if available, otherwise an empty result<br />
<br />
{| id="Capability" cellspacing="0" border="1"<br />
|+ align="bottom" | Capability<br />
! Name !! Type !! Value<br />
|-<br />
| id || String || The identifier of the capability<br />
|-<br />
| attributes || Object || A JSON object holding optional properties of the capability <br />
|}<br />
<br />
=== Get all capabilities ===<br />
<br />
GET <code>/ajax/capabilities?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: An array of capability objects as described in [[#Capability| Capability]].<br />
<br />
<br />
== Module "jump" (available with v7.6.0) ==<br />
<br />
The jump module is used to pass an acquired identity token for an authenticated user from one system to another for a single sign-on.<br />
<br />
=== Acquire an identity token ===<br />
<br />
GET <code>/ajax/jump?action=identityToken</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>system</code> – The identifier for the external service/system<br />
<br />
Response: The acquired identity token wrapped by a simple JSON object as described in [[#Jump| Jump]]<br />
<br />
{| id="Jump" cellspacing="0" border="1"<br />
|+ align="bottom" | Jump<br />
! Name !! Type !! Value<br />
|-<br />
| token || String || The identifier of the token<br />
|}</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:Theming&diff=17886AppSuite:Theming2014-06-27T11:03:12Z<p>Viktor.Pracht: /* Favicons and mobile homescreen icons */</p>
<hr />
<div>{{Stability-experimental}}<br />
<br />
<div class="title">Theming</div><br />
<br />
'''Abstract.''' In this article, you can learn how to create customized themes and use them to change the look of you appsuite installation.<br />
__TOC__<br />
== LESS.JS ==<br />
Appsuite used LESS as dynamic stylesheet language. LESS extends CSS with dynamic behavior such as variables, mixins, operations and functions.<br />
<br />
Please read [http://lesscss.org/#docs LESS.JS] documentation first.<br />
<br />
=== Using less.js ===<br />
If your theme depends on less.js, you will need one more step to make it work. Why? To accelerate the login, compilation of LessCSS files was moved from the login process in the browser to the installation process on the backend. <br />
<br />
Backend packages for themes and any apps which ship .less files require the following changes:<br />
<br />
1. Add "skipLess=1" to the build command in *.spec and in debian/rules:<br />
sh /opt/open-xchange-appsuite-dev/bin/build-appsuite app skipLess=1<br />
2. Add %post and %postun sections to *.spec:<br />
%post<br />
if [ "$1" = 1 ]; then<br />
UPDATE=/opt/open-xchange/appsuite/share/update-themes.sh<br />
[ -x $UPDATE ] && $UPDATE<br />
fi<br />
%postun<br />
UPDATE=/opt/open-xchange/appsuite/share/update-themes.sh<br />
[ -x $UPDATE ] && $UPDATE<br />
<br />
For multiple binary packages, the %post and %postun sections should apply only to backend packages <br />
which contain .less files.<br />
<br />
3. Add debian/postinst and debian/postrm containing the same content:<br />
#!/bin/sh<br />
UPDATE=/opt/open-xchange/appsuite/share/update-themes.sh<br />
[ -x $UPDATE ] && $UPDATE<br />
<br />
For multiple binary packages, the postinst and postrm files should apply only to backend packages which contain .less files.<br />
<br />
Note: Since 7.2.1, LessCSS files must have the file extension .less to be usable with the 'less' RequireJS plugin (module dependencies of the form 'less!filename.less'). Previously we were more lenient and dealt with .css, too.<br />
<br />
== File structure ==<br />
A theme basically consists of two files located in <code>apps/themes/<var>THEME_ID</var>/</code>. These files are described in this and the following sections.<br />
<br />
<code><var>THEME_ID</var></code> is a unique identifier for your theme, which is not visible to users. By convention, it is best derived from a domain name you control, e.g. <code>com.example.prettytheme</code>.<br />
<br />
=== definitions.less ===<br />
This file can be used to override variables described in the "Variables" section of this article.<br />
<br />
=== style.less ===<br />
This file can be used to define any CSS you like. Before doing this, check, if there really is no variable that can be used to achieve the same thing.<br />
<br />
=== Referencing paths ===<br />
Since 7.2.1, all URLs are relative to the source .less file in which they are contained. This means that unless a theme changes an image it does not need to include that image anymore. <br />
<br />
Old themes must be updated if they change an image from the default theme: All styles from the default theme which refer to a changed image must be overwritten in the custom theme. This way the URLs resolve to the new image.<br />
<br />
== Variables ==<br />
<br />
Naming of the variables should be straight forward. Variables containing the word ''Background'' will always refer to the background color. Variables containing ''Color'' will refer to the foreground color of an element, like color of a font. ''Hover'' in most cases means "hovered" elements. ''Selected'' relates to the currently selected item. Elements that are supposed to catch the users eye can use the ''Highlight'' class and the variable contains this word.<br />
<br />
Variables are defined in variables.less from twitter-bootstrap and our default definitions.less. Variables that are defined in definitions.less always override variables from bootstrap's variables.less<br />
<br />
=== Most relevant variables ===<br />
<br />
{|<br />
! Variable (7.6.x) || Variable (7.4.x) || Default (7.6.x)<br />
|-<br />
| @topbar-background || @topbarBackground || #3774A8 (blue)<br />
|-<br />
| --- || @topbarBackgroundAlt || No longer used<br />
|-<br />
| @topbar-launcher-color || @topbarLauncherColor || rgba(255, 255, 255, 0.70)<br />
|-<br />
| @topbar-launcher-color-hover || @topbarLauncherColor-hover || #fff<br />
|-<br />
| @topbar-launcher-color-active || @topbarLauncherColorActive || #fff<br />
|-<br />
| @topbar-launcher-background-hover || @topbarLauncherBackgroundHover || rgba(0, 0, 0, 0.30)<br />
|-<br />
| @topbar-launcher-background-active || @topbarLauncherBackgroundActive || rgba(0, 0, 0, 0.20);<br />
|-<br />
| @topbar-icon-color || @topbarIconColor || #fff<br />
|-<br />
| @selected-background || @selectedBackground || #428BCA (blue)<br />
|-<br />
| @contact-picture-radius || @contactPictureRadius || 50%<br />
|-<br />
|}<br />
:<br />
<br />
<br />
The most significant visual change is achieved by changing the following variables:<br />
* '''@topbar-background''' (top navigation bar)<br />
* '''@selected-background''' (selection background color in list views and folder tree)<br />
* '''@link-color''' (almost all hyperlinks)<br />
<br />
=== Font ===<br />
<br />
{|<br />
! Variable (7.6.x) || Variable (7.4.x) || Default (7.6.x)<br />
|-<br />
| @font-family-sans-serif || @sansFontFamily || "Helvetica Neue", Helvetica, Arial, sans-serif<br />
|-<br />
| @font-family-serif || @serifFontFamily || Georgia, "Times New Roman", Times, serif<br />
|-<br />
| @font-family-monospace || @monoFontFamily || Monaco, Menlo, Consolas, "Courier New", monospace<br />
|-<br />
| @font-size-base || @baseFontSize || 14px<br />
|-<br />
| || @baseFontFamily ||<br />
|-<br />
| @line-height-base || @baseLineHeight || 1.428571429; // 20/14<br />
|-<br />
| || @altFontFamily ||<br />
|-<br />
| @font-size-touch || @touchFontSize || 15px<br />
|-<br />
| @headings-font-family || @headingsFontFamily || inherit<br />
|-<br />
| @headings-font-weight || @headingsFontWeight || 500<br />
|-<br />
| @font-size-large || @fontSizeLarge || ceil((@font-size-base * 1.25)); // ~18px<br />
|-<br />
| @font-size-small || @fontSizeSmall || ceil((@font-size-base * 0.85)); // ~12px<br />
|-<br />
| || @fontSizeMini ||<br />
|-<br />
| @vgrid-font-size || @vgridFontSize || 13px<br />
|}<br />
<br />
=== Colors ===<br />
<br />
{|<br />
! Variable (7.6.x) || Variable (7.4.x) || Default (7.6.x)<br />
|-<br />
| @background || @bodyBackground || #fff<br />
|-<br />
| @text-color || @textColor || @gray-dark<br />
|-<br />
| @link-color || @linkColor || @brand-primary<br />
|-<br />
| @link-hover-color || @linkColorHover || darken(@link-color, 15%)<br />
|-<br />
| @link-accent-color || @linkAccentColor || #ffad00<br />
|-<br />
| || @linkAccentColorHover ||<br />
|-<br />
| @badge-color || @badgeColor || @white<br />
|-<br />
| @badge-bg || @badgeBackground || #aaa<br />
|-<br />
| @headings-color || @headingsColor || inherit<br />
|-<br />
| @black || @black || #000<br />
|-<br />
| @gray-darker || @grayDarker || #222<br />
|-<br />
| @gray-dark || @grayDark || #333<br />
|-<br />
| @gray || @gray || #555<br />
|-<br />
| @gray-light || @grayLight || #999<br />
|-<br />
| @gray-lighter || @grayLighter || #eee<br />
|-<br />
| @white || @white || #fff<br />
|-<br />
| @blue || @blue || darken(#049cdb, 5%)<br />
|-<br />
| @blue-dark || @blueDark || #0064cd<br />
|-<br />
| @blue-light || @blueLight || lighten(#049cdb, 25%)<br />
|-<br />
| @green || @green || #1A8D1A<br />
|-<br />
| @green-light || @greenLight || #92D050<br />
|-<br />
| @red || @red || #cc0000<br />
|-<br />
| @yellow || @yellow || #F8E400<br />
|-<br />
| @orange || @orange || #f89406<br />
|-<br />
| @pink || @pink || #E01CD9<br />
|-<br />
| @purple || @purple || #7E16CF<br />
|-<br />
|}<br />
<br />
=== Space ===<br />
<br />
{|<br />
! Variable (7.6.x) || Variable (7.4.x) || Default (7.6.x)<br />
|-<br />
| || @paddingLarge ||<br />
|-<br />
| || @paddingSmall ||<br />
|-<br />
| || @paddingMini ||<br />
|-<br />
| @border-radius-base || @baseBorderRadius || 4px<br />
|-<br />
| @border-radius-large || @borderRadiusLarge || 6px<br />
|-<br />
| @border-radius-small || @borderRadiusSmall || 3px<br />
|}<br />
<br />
=== Pagination ===<br />
<br />
Used where pagination is done, for example in the Calendar weekview, each week is on one "page"; one can switch the week using a pagination widget styled with these variables.<br />
<br />
{|<br />
! Variable (7.6.x) || Variable (7.4.x) || Default (7.6.x)<br />
|-<br />
| @pagination-bg || @paginationBackground || #fff<br />
|-<br />
| @pagination-border || @paginationBorder || #ddd<br />
|-<br />
| @pagination-active-bg || @paginationActiveBackground || @brand-primary<br />
|}<br />
<br />
=== Buttons ===<br />
<br />
{|<br />
! Variable (7.6.x) || Variable (7.4.x) || Default (7.6.x)<br />
|-<br />
| || @btnBackground ||<br />
|-<br />
| || @btnBackgroundHighlight ||<br />
|-<br />
| || @btnBorder ||<br />
|-<br />
| @btn-primary-background || @btnPrimaryBackground || @link-color<br />
|-<br />
| @btn-primary-background-highlinght || @btnPrimaryBackgroundHighlight || darken(@btn-primary-background, 10%);<br />
|-<br />
| @btn-info-background || @btnInfoBackground || #5bc0de<br />
|-<br />
| @btn-info-background-highlight || @btnInfoBackgroundHighlight || #2f96b4<br />
|-<br />
| @btn-success-background || @btnSuccessBackground || #62c462<br />
|-<br />
| @btn-success-background-highlight || @btnSuccessBackgroundHighlight || #51a351<br />
|-<br />
| @btn-warning-background || @btnWarningBackground || lighten(@orange, 15%)<br />
|-<br />
| @btn-warning-background-highlight || @btnWarningBackgroundHighlight || @orange<br />
|-<br />
| @btn-danger-background || @btnDangerBackground || #ee5f5b<br />
|-<br />
| @btn-danger-background-danger-highlight || @btnDangerBackgroundHighlight || #bd362f<br />
|-<br />
| @btn-inverse-background || @btnInverseBackground || #444<br />
|-<br />
| @btn-inverse-background-highlight || @btnInverseBackgroundHighlight || @gray-darker<br />
|}<br />
<br />
=== Dropdowns ===<br />
<br />
{|<br />
! Variable (7.6.x) || Variable (7.4.x) || Default (7.6.x)<br />
|-<br />
| @dropdown-bg || @dropdownBackground || #fff<br />
|-<br />
| @dropdown-border || @dropdownBorder || rgba(0,0,0,.15)<br />
|-<br />
| @dropdown-divider-bg || @dropdownDividerTop || #e5e5e5<br />
|-<br />
| @dropdown-divider-bg || @dropdownDividerBottom || #e5e5e5<br />
|-<br />
| @dropdown-link-color || @dropdownLinkColor || @gray-dark<br />
|-<br />
| @dropdown-link-hover-color || @dropdownLinkColorHover || darken(@gray-dark, 5%)<br />
|-<br />
| @dropdown-link-active-color || @dropdownLinkColorActive || @component-active-color<br />
|-<br />
| @dropdown-link-active-bg || @dropdownLinkBackgroundActive || @component-active-bg<br />
|-<br />
| @dropdown-link-hover-bg || @dropdownLinkBackgroundHover || #f5f5f5<br />
|}<br />
<br />
=== Foldertree ===<br />
{|<br />
! Variable (7.6.x) || Variable (7.4.x) || Default (7.6.x) || Description<br />
|-<br />
| @foldertree-sidepane-background || @foldertreeSidepanelBackground || #f5f5f5 ||<br />
|-<br />
| @foldertee-section-title-color || @foldertreeSectionTitleColor || #888 || Color for sectiontitles in foldertree (like "Public" folders)<br />
|-<br />
| @foldertree-active-label-color || @foldertreeActiveLabelColor || #333 || ''Active'' means, user can perform an action on this item<br />
|-<br />
|@foldertree-passive-label-color || @foldertreePassiveLabelColor ||@hc-gray || ''Passive'' means, user can '''not''' perform any action with this item <br />
|-<br />
| @foldertree-hover-background || @foldertreeHoverBackground || rgba(0, 0, 0, 0.05) ||<br />
|-<br />
| @foldertree-selected-background || @foldertreeSelectedBackground || rgba(0, 0, 0, 0.10) ||<br />
|-<br />
| @foldertree-badge-background || @foldertreeBadgeBackground || @bagde-bg || see [[#Colors]] for definition of @badge-bg<br />
|-<br />
| @foldertree-badge-color || @foldertreeBadgeColor ||@badge-color || see [[#Colors]] for definition of @badge-color<br />
|}<br />
<br />
=== Calendar ===<br />
==== Appointment ====<br />
{|<br />
! Variable (7.6.x) || Variable (7.4.x) || Default (7.6.x) || Description<br />
|-<br />
| @appointment-reserved || @appointmentReserved || #08c /* blue */ || Appointment status color<br />
|-<br />
| @appointment-temporary || @appointmentTemporary || #ffbb00 /* yellow */ || Appointment status color<br />
|-<br />
| @appointment-absent || @appointmentAbsent || #913f3f /* red */ || Appointment status color<br />
|-<br />
| @appointment-free || @appointmentFree || #8eb360 /* green */ || Appointment status color<br />
|-<br />
| @appointment-private || @appointmentPrivate || #555 /* gray */ || Appointment status color<br />
|-<br />
| @appointment-declined-font || @appointmentDeclinedFont || #888 /* dark gray */|| Font color for declined Appointments<br />
|-<br />
| @appointment-unconfirmed-alpha || @appointmentUnconfirmedAlpha || 0.4 || Transparency value for unconfirmed Appointments<br />
|-<br />
| @appointment-declined-alpha || @appointmentDeclinedAlpha || 0.3 || Transparency value for declined Appointments<br />
|-<br />
| @appointment-hover-pct || @appointmentHoverPct || 15% || Percentage increase of the dark pigment content on hover effect<br />
|}<br />
<br />
==== Week View ====<br />
{|<br />
! Variable (7.6.x) || Variable (7.4.x) || Default (7.6.x) || Description<br />
|-<br />
| @weekview-appointment-lasso || @weekviewAppointmentLasso || #aeaeff || Lasso frame color<br />
|-<br />
| @weekview-day-in || @weekviewDayIn || #fff /* white */ || Default background color in week view<br />
|-<br />
| @weekview-day-out || @weekviewDayOut || #e0e0e0 /* grey */ || Background color outside of the mean working time<br />
|-<br />
| @weekview-timeline || @weekviewTimeline || rgba(243, 15, 170, 0.4) || Color of the Line indicating the current time<br />
|-<br />
| @weekview-time-width || @weekviewTimeWith || 58px || With of the time labels on the left side<br />
|-<br />
| @calendar-toolbar-height || @calendarToolbarHeight || 47px || Height of the control toolbar <br />
|}<br />
<br />
==== Month View ====<br />
{|<br />
! Variable (7.6.x) || Variable (7.4.x) || Default (7.6.x) || Description<br />
|-<br />
| @monthview-appointment-out || @monthviewAppointmentOut || #aaa /* light gray */ || Color of appointments, which are not in focus<br />
|-<br />
| @monthview-today || @monthviewToday || #daefff /* light blue */|| Background color of the current day<br />
|-<br />
| || @monthview@calendarToolbarHeight || ||<br />
|}<br />
<br />
== Area names ==<br />
<br />
The variables sometimes refer to common areas. To identify which area is located where, see the following annotated screenshots.<br />
<br />
[[File:Colors_mail.png|800px||Mail application]]<br />
<br />
[[File:Colors_launchpad.png|800px||Launchpad application]]<br />
<br />
== Replacing the logo ==<br />
<br />
One of the most common theme changes which requires editing <code>style.css</code> is changing the logo in the top right corner. The logo is displayed as the background image for an element with the ID <code>io-ox-top-logo-small</code>. A theme can therefore change the size and URL of the image:<br />
#io-ox-top-logo-small {<br />
width: 60px;<br />
height: 22px;<br />
margin: 8px 13px 0 13px;<br />
background-image: url(mylogo.png);<br />
}<br />
The file <code>mylogo.png</code> is expected to be in the same directory as <code>style.css</code>. If you want to place the image somewhere else, then use a relative path in <code>url()</code>.<br />
<br />
Remember that images in OX App Suite are served by the web server and not by the application server. This means that images need to be packaged separately (for dedicated web servers) and installed in <code>/var/www/appsuite/</code> (or similar, depending on the target platform) instead of <code>/opt/open-xchange/appsuite/</code>. Direct support for multiple packages is coming in version 7.4.1. Until then, use the build system from the <code>develop</code> branch to [[AppSuite:UI_build_system#init-packaging|initialize the packaging]] if your theme contains images.<br />
<br />
== Mixins ==<br />
In LESS, it is possible to include a bunch of properties from one ruleset into another ruleset. So say we have the following class:<br />
<br />
=== Sample ===<br />
<pre class="language-css"><br />
.border-radius(@radius: 0px) {<br />
-webkit-border-radius: @radius;<br />
-moz-border-radius: @radius;<br />
-ms-border-radius: @radius;<br />
border-radius: @radius;<br />
}<br />
<br />
#menu a {<br />
color: #111;<br />
.border-radius(5px);<br />
}<br />
</pre><br />
<br />
Read [http://www.lesscss.org/#-mixins LESS Mixins]<br />
<br />
=== global OX Mixins ===<br />
<br />
they can be found at [[#definitions.less | definitions.less]]<br />
<br />
{|<br />
! Mixin || Sample || Description <br />
|-<br />
| .box-sizing(@boxmodel) || .box-sizing(border-box) ||<br />
|-<br />
| .user-select(@select) || .user-select(none) ||<br />
|-<br />
| .border-radius(@radius) || .border-radius(3px) ||<br />
|-<br />
| .box-shadow(@shadow) || .box-shadow(3px) ||<br />
|-<br />
| .vertical-gradient(@startColor, @endColor) || .vertical-gradient(#888, #555) ||<br />
|-<br />
| .radial-gradient(@color1, @color2, @color3) || .radial-gradient(#111, #222, #333) ||<br />
|-<br />
| .transition(@transition) || .transition(background-color 0.2s linear) ||<br />
|-<br />
| .animation(@animation) || .animation(slidein 300ms) ||<br />
|-<br />
| .animation-name(@name) || .animation-name(slideright) ||<br />
|-<br />
| .ellipsis || .ellipsis ||<br />
|-<br />
| .overflow(@type) || .overflow(hidden) ||<br />
|-<br />
| .overflow-x(@type) || .overflow-x(hidden) ||<br />
|-<br />
| .overflow-y(@type) || .overflow-y(hidden) ||<br />
|-<br />
| .backface-visibility(@type) || .backface-visibility(hidden) ||<br />
|}<br />
<br />
== How to activate a theme during development ==<br />
<br />
When creating a new theme, you will want to test changes quickly without building packages reinstalling them. The trick is to use [[Appsuite:Appserver|appserver]].<br />
<br />
# First, you need to add the theme to the list of available themes on the backend. Simply create a new file in <code>/opt/open-xchange/etc/settings/</code> with the extension <code>.properties</code> and add a line for your theme to it: <pre&lt;noinclude&gt;&lt;/noinclude&gt;>io.ox/core/settingOptions//themes/<var>ID</var>=<var>Theme Name</var></pre&lt;noinclude&gt;&lt;/noinclude&gt;> Replace <var>ID</var> by the identifier (directory name) of your theme, and <var>Theme Name</var> by the human-readable name which should appear in the UI.<br />
# The server needs to be restarted to read the new settings.<br />
# Now, you can use <code>appserver</code> ([[AppSuite:appserver#Use_with_Apache|with a local web server]] if your theme includes images) to get your theme in combination with the UI which is already installed on the backend.<br />
# Finally, activate your theme the list in the <code>Settings -> Basic</code> view behind the option <code>Theme</code>.<br />
<br />
In case you also want to access the same backend without <code>appserver</code> while your theme is selected, that theme (or at least some empty <code>.less</code> files) should be also installed on the backend to avoid errors. To just use an empty theme, run the following as root:<br />
touch /opt/open-xchange/appsuite/apps/themes/<var>ID</var>/definitions.less<br />
touch /opt/open-xchange/appsuite/apps/themes/<var>ID</var>/style.less<br />
/opt/open-xchange/appsuite/share/update-themes.sh<br />
The value of <var>ID</var> here must be the same as in your <code>.properties</code> file.<br />
<br />
== Favicons and mobile homescreen icons ==<br />
'''Note''': This chapter is not about changing AppSuite icons which are used in the application like the brand on the upper right.<br />
<br />
'''This documentation applies for AppSuite v.7.4.2'''<br />
<br />
AppSuite ships with a standard set of icons containing a<br />
# favicon<br />
# set of touch icons which are mainly used by mobile Safari on iOS<br />
<br />
These icons are used as default for all devices and browsers as long as you don't deliver your own icons with your theme. To provide your own icons, put them into your theme's directory, e.g. <tt>apps/themes/<var>theme-name</var>/favicon.ico</tt>.<br />
<br />
=== Favicon ===<br />
All major browsers support the use of a favicon. The favicon is a pixel image with the size of 16x16 (32x32) and the "ico" file ending. (see [http://en.wikipedia.org/wiki/Favicon Wikipedia Favicon] for details).<br />
<br />
You should provide your custom favicon within your custom theme. If you do not add a custom favicon to your theme the global OX default will be used. The default icon is located under <tt>apps/themes/icons/default</tt> on the web server.<br />
<br />
'''Attention:''' Safari and Internet Explorer do not support dynamic changes to the favicon for a webpage. This means, the default icon will be shown even if a custom favicon is provided within a custom theme. To enable the right favicon for a theme on Safari and IE, the overall standard <tt>favicon.ico</tt> located under <tt>apps/themes/icons/default</tt> on the web server must be replaced with a custom version.<br />
<br />
=== Apple touch icons ===<br />
iOS devices (iPhone/iPad/iPod) support so called "Webclips". Webclips are bookmarks to websites or webapps which provide a App Icon that is shown on the iOS homescreen. AppSuite offers full support for Webclips by providing all needed App icons, splashscreens and full screen support. If a user uses the "Add to homescreen" button on his iOS device, a Webclip is created, taking the right icon for his current device. Most devices need custom resolutions of the Webclip icon in the '''png''' format.<br />
<br />
* iPhone 3: 57 x 57 px<br />
* iPhone 4 retina: 114x114 px<br />
* iPhone iPhone 5 retina: 120 x 120 px<br />
* iPad: 72 x 72 px<br />
* iPad (iOS 7): 76 x 76px<br />
* iPad retina: 144 x 144 px <br />
* iPad retina (iOS 7): 152 x 152 px <br />
<br />
Furthermore a fullscreen Webclip App will show a splashscreen, a jpg file that is displayed on startup during app load. There are currently three different resolutions as jpg files available. '''Note''': Splashscreens must be JPG files<br />
<br />
* iPhone: 320 x 460 px<br />
* iPhone 4: 640 x 920 px<br />
* iPhone 5: 640 x 1096 px<br />
<br />
'''Note''': We do not provide splashscreens for iPad<br />
<br />
This list may change with Apple's iOS updates. We recommend providing all of this resolutions when customizing the Webclip icons and splashscreens, even if some iOS devices use the next best resolution for an icon if a certain file is missing.<br />
<br />
=== Providing custom icons ===<br />
To provide custom Webclip icons locate the following path in the AppSuite installation on your web server:<br />
pathToAppSuite/apps/themes/icons/default<br />
<br />
This folder contains all OX default icons for Webclips icons and splashscreens. Use these as samples for your own versions.<br />
<br />
A clean installation will have all our default icons in the "default" directory. To customize the icons we recommend using our default icons as samples and save your customized version in your theme. '''Note''': The filename has to be the same as in the default folder. Otherwise the fallback will be applied and the default icons will be used. If more advanced rewriting is needed one should edit the contents of the <tt>.htaccess</tt> file located under <tt>apps/themes</tt><br />
<br />
== Theming the login page ==<br />
<br />
The login page is a little bit special. If you don’t use the [[Open-Xchange_servlet_for_external_login_masks|form login]] and provide your own login page, you might want to theme the login page, too. [[AppSuite:Theming the login page|Learn how to do this here]].<br />
<br />
=== Providing domain based login themes ===<br />
<br />
If you have a multibrand installation and you want to deliver not only custom themes but also custom login-themes this can be done via Apache mod_rewrite. You can do so by a domain-based rewrite rule to deliver custom themes to a user based on the URI he's using. The needed config file <tt>.htaccess</tt> is located under <tt>apps/themes</tt><br />
<br />
<pre><br />
# Sample config for domain based login theme<br />
RewriteCond %{HTTP_HOST} ^www\.domain\.com$<br />
RewriteCond %{REQUEST_FILENAME} -f<br />
RewriteRule ^login/(.*)$ domain_com_logintheme/$1 [L]<br />
</pre><br />
<br />
== Best practice ==<br />
<br />
To be really safe, it’s best to only define your own values for the variables shown above. If this really breaks anything, we consider this a bug, please report it [https://bugs.open-xchange.com/] in our bugzilla.<br />
<br />
Of course, using CSS in <code>style.less</code> file to define your own styles is also possible. Make sure to test your style in such cases more carefully. It is most likely safe to change minor things using this file, but if you plan to change any positions of larger elements, this might break the complete design. So please be careful when overwriting the default CSS rules.<br />
<br />
== Links ==<br />
[http://bradfrost.github.io/this-is-responsive/resources.html Responsive design]<br />
<br />
[http://lesscss.org/ LESS]<br />
<br />
== Caveats ==<br />
<br />
It is '''not''' recommended to change the size of elements or their position. If you really want to do so, please check on all devices and in all browsers and make sure you didn’t break anything. You even have to be careful when changing the font, because this might have effects on positioning, too.<br />
<br />
As mentioned before, changing colors should be safe.<br />
<br />
[[Category:AppSuite]]<br />
[[Category:UI]]</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=ConfigCascade&diff=17773ConfigCascade2014-06-06T10:39:56Z<p>Viktor.Pracht: /* UI Properties */ Syntax for UI values</p>
<hr />
<div>= Introduction to the config cascade =<br />
<br />
The config cascade is a configuration system that allows administrators to selectively override configuration parameters on context and user level. This means a configuration option can vary between groups of contexts, specific contexts or users.<br />
<br />
== Who should read this document? ==<br />
<br />
If you are tasked with designing and maintaining the configuration of an OX server or cluster, information contained in this document will acquaint you with options in OX configuration design. <br />
<br />
== Core Concepts - Configuration Scope ==<br />
<br />
The config cascade differentiates between 4 scopes of configuration: '''Server''', '''ContextSet''', '''Context''' and '''User''', with the latter always overriding the configuration of the one before it. To determine the active value of a certain parameter, the config cascade looks whether the parameter is defined in a certain scope before falling back to the next scope to the left to determine if a value is defined there. This means, that a value in the '''User''' scope can override the more general value from the '''Context''' scope, which in turn overrides the value of a context set configuration, which itself overrides a server wide configuration.<br />
<br />
== Core Concepts - Context Taxonomy ==<br />
<br />
When deciding on configuration options it usually makes sense to group contexts according to a certain criterion. Typical uses would be to group contexts by offering ('''webmail''', '''groupware_standard''', '''groupware_plus'''), or country ('''de''', '''fr''', '''es''') or brand ('''coolhosting''', '''supremehosting''') or if they are part of a "friendly users" group you sometimes give access to features to deem whether they are appropriate for rollout ('''beta'''). You can then specify configuration options that only take effect if a context is part of one of these groups. For example, the default hostname varies by both country and brand, with the french coolhosting domain name being "coolhosting.fr", while the spanish one is "coolhosting.es", or, for the second brand "supremehosting.fr" or "supremehosting.es" respectively. How can you go about classifying a context?<br />
<br />
Using the command line tools you can specifiy the taxonomy/types parameter:<br />
<br />
'''createcontext ... -i 12 --taxonomy/types=webmail,coolhosting,de'''<br />
<br />
which would tag context 12 with the types webmail, coolhosting and de. This is also available in "'''changecontext'''". In RMI the equivalent is to call '''Context#setUserAttribute("taxonomy", "types", "webmail,coolhosting,de")'''. We will later see how configuration options can be specified for these types of contexts. <br />
<br />
== Specifying Configuration - Server Scope ==<br />
<br />
The most general scope is the '''Server''' scope. Every value that can be overridden along the config cascade should also be defined with a default value in the Server scope. This is done using the usual configuration methods of the server: .properties files in the config directory (usually /opt/openexchange/etc, or /opt/openexchange/etc/groupware in versions up to 6.20.7). Let's consider the properties "'''com.openexchange.messaging.facebook'''", which governs whether facebook messaging should be available in a given installation. Since we consider this to be a premium feature, we'll disable this on the server level:<br />
<br />
'''facebookmessaging.properties:'''<br />
com.openexchange.messaging.facebook=false<br />
<br />
Later we will see how to enable it for certain groups of contexts.<br />
<br />
== Specifying Configuration - Context Set Scope ==<br />
<br />
As we saw, you can classify contexts into groups. These groups will now be used to specify certain configuration options. Let's consider this setup:<br />
<br />
<br />
Context 12: webmail,de,beta<br />
Context 13: groupware_plus,es<br />
Context 14: groupware_plus,fr,beta<br />
<br />
<br />
Let's say, we want to roll out the facebook functionality to those contexts, that have the groupware_plus product and are part of our "friendly users". For this, you can specify a configuration that overrides the server setting like this:<br />
<br />
Create a file called '''/opt/openexchange/etc/contextSets/messaging.yml''' and add the following block:<br />
<br />
experimental_gw_plus:<br />
withTags: groupware_plus & beta<br />
com.openexchange.messaging.facebook: true<br />
<br />
Let's go through this line by line. The first line introduces a configuration block that will be used for certain contexts. The name doesn't matter, only insofar as that it may only be used once per file. Choose a good mnemonic here, so a future you or someone else can guess at what is going on in this configuration block. <br />
<br />
The second line specifies the criterion to use to find out whether a context belongs in this group of contexts. In this case, a context having both the groupware_plus and beta tags will be considered to be a part of this group. In the withTags expression you can use boolean logic (with & for and, | for or and brackets to group the expressions). It's best to not go overboard with this, though. If the boolean expressions here become too complex it's usually an indication that you could use another classification for the contexts. Which tags does a context have? Firstly, and most obviously, those specified as its taxonomy/types list. But that is not the whole story. The /users/ module access permissions are also transformed into tags and applied to the context (at runtime). So if a user has access to the tasks module and the infostore module, the context will be considered to be tagged with ucTask and ucInfostore as well. This is sometimes enough to determine if a context is part of a certain offering, but more explicit tagging of contexts according to the offering keeps things readable. Lastly the configuration parameter "com.openexchange.config.cascade.types" (which is itself config cascade enabled) adds its value to the tag list, so, for example:<br />
<br />
friendly_users:<br />
withTags: groupware_plus & beta<br />
com.openexchange.config.cascade.types: friendly_and_paying<br />
<br />
Would add the friendly_and_paying tag to all contexts already classified as groupware_plus and beta. Also since this value can also be specified on user level, you could classify users irrespective of their contexts, should the need arise. <br />
<br />
The third line then specifies the setting to override. You can specify all properties to override in this block, so if we wanted to enable both facebook and twitter messaging for these contexts, we'd use the following configuration:<br />
<br />
experimental_gw_plus:<br />
withTags: groupware_plus & beta<br />
com.openexchange.messaging.facebook: true<br />
com.openexchange.messaging.twitter: true<br />
<br />
Most configuration use cases can probably be handled with the context sets system. Only if a configuration is truly unique for just one context or user should the other options be pursued.<br />
<br />
== Specifying Configuration - Context Scope and User Scope ==<br />
<br />
Configuration options can be overridden on user and context level, using a dynamic property. For example:<br />
<br />
$ createcontext [...] --config/com.openexchange.messaging.facebook=true<br />
$ changecontext [...] --config/com.openexchange.messaging.facebook=true<br />
<br />
$ createuser [...] --config/com.openexchange.messaging.facebook=true<br />
$ changeuser [...] --config/com.openexchange.messaging.facebook=true<br />
<br />
Depending on the number of users and contexts in your system, this could pose a problem further down the road when you need to update this value for a large number of users.<br />
<br />
To remove such a setting again the following syntax can be used:<br />
<br />
$ changecontext [...] --remove-config/com.openexchange.messaging.facebook<br />
$ changeuser [...] --remove-config/com.openexchange.messaging.facebook<br />
<br />
== UI Properties ==<br />
<br />
A common use case for the OX configuration system is to allow fine-tuning of the UI by providing configuration data on the backend. All properties defined in properties files below <tt>/opt/open-xchange/etc/groupware/settings</tt> are transported to the UI and are config cascade enabled. So every customization you can specify for the UI using these settings, can also be selectively overridden with the config cascade.<br />
<br />
Since the config cascade only overrides existing settings, whether a property is a UI property or a server property is automatically determined by the directory in which the corresponding <tt>.properties</tt> file is found. For example if <tt>/opt/open-xchange/etc/settings/appsuite.properties</tt> contains the setting<br />
<br />
io.ox/core//theme=default<br />
<br />
Then you can overwrite it for any context (or user, context set, etc.):<br />
<br />
$ changecontext [...] --config/io.ox/core//theme=org.example.theme<br />
<br />
The values are first parsed using [http://json.org/ JSON] syntax. If that fails, they are interpreted as plain strings.<br />
<br />
== Further Reading ==<br />
<br />
[[ConfigCascadeCookbook]] - Collects typical configuration scenarios and how to handle them using the config cascade.</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:Writing_a_portal_plugin&diff=17490AppSuite:Writing a portal plugin2014-04-30T14:47:35Z<p>Viktor.Pracht: /* The simplest portal plugin: An advertisement */ added missing extension</p>
<hr />
<div>{{Stability-stable}}<br />
<br />
<div class="title">Writing a portal plugin</div><br />
<br />
'''Abstract:''' This articles covers how to write a plugin that shows on the portal page. A portal plugin always gives a short overview on a piece of information (the so-called 'tile'). It can link a longer view that is opened when the tile is clicked, this we call the side pop-up. The side pop-up is optional.<br />
<br />
== Where and how to start ==<br />
Plugins are collected in the folder ui/apps/plugins. Start your new plugin there: Create a folder and in this folder, create two files: <tt>register.js</tt> (where everything happens) and <tt>manifest.json</tt><br />
<br />
== The simplest portal plugin: An advertisement ==<br />
The simplest portal plugin comes without a side pop-up and shows static content on its tile. Two uses for this would be presenting an advertisement (or your daily creed, an often used check list....) or showing a link list (for example to other parts of an company's intranet that are not integrated into the AppSuite (yet)). We will now build an advertisement, which is just a slogan.<br />
<br />
The beauty of this is that we do not have any dependencies (for example needing another module like the file store), so the content of our manifest.json is rather simple:<br />
<br />
<pre class="language-javascript"> <br />
{<br />
"namespace": "portal"<br />
}<br />
</pre><br />
<br />
Nothing to see here. We say we belong in the portal namespace and that's it. We do not need to define any dependencies on other modules.<br />
<br />
Our register.js is only slightly longer:<br />
<br />
<pre class="language-javascript"> <br />
define('plugins/portal/myAd/register', ['io.ox/core/extensions'], function (ext) {<br />
<br />
'use strict';<br />
<br />
ext.point('io.ox/portal/widget').extend({<br />
id: 'myAd'<br />
});<br />
<br />
ext.point('io.ox/portal/widget/myAd').extend({<br />
preview: function () {<br />
var content = $('<div class="content">')<br />
.text('Buy stuff. It's like solid happiness.');<br />
this.append(content);<br />
}<br />
});<br />
<br />
ext.point('io.ox/portal/widget/myAd/settings').extend({<br />
title: 'My advertisement',<br />
type: 'myAd'<br />
});<br />
});<br />
</pre><br />
<br />
Please keep in mind, that the first parameter of define()-method refers to your app's path. According to the code above <tt>plugins/portal/myAd/</tt> should contain the upper displayed <tt>register.js</tt>.<br />
<br />
So what do we have here? We have two extension points:<br />
<br />
The first one is for the ad itself, ''io.ox/portal/widget/myAd''. This one contains a single method that we implement, ''preview''. ''Preview'' is responsible for the tile you see whenever you look at your portal. Technically, ''this'' contains the container to which you can attach your content. If you are brave, you can do changes on the container, too. But that is not needed for now.<br />
<br />
The second is less obvious: It creates an option in the settings area for the portal (the one you reach by "customize this page"). There you will have to enable your setting (yes, this is a very polite advertisement). The ''title'' is what is shown as the name of your plugin (so chose a readable one), the type references the one you used in the definition. '''Attention:''' the ''type'' attribute has to be identical to the module name in the extension point. In this case "io.ox/portal/widget/myAd/settings" has the module name ''myAd'' and the referenced ''type'' is identical: ''myAd''. Also make sure, the type doesn’t contain any "/" or "-" characters. You are save if you limit the characters used to numbers, alphabetical characters and "_".<br />
<br />
== A more typical portal plugin ==<br />
A typical portal plugin uses the tile to display a short summary or teaser of its contents and uses a side-popup to show the whole content.<br />
<br />
The manifest.json can stay the same, but the register.js needs to do a little more now:<br />
<pre class="language-javascript"> <br />
define("plugins/portal/myAd/register", ['io.ox/core/extensions'], function (ext) {<br />
<br />
"use strict";<br />
<br />
ext.point('io.ox/portal/widget').extend({<br />
id: 'myAd'<br />
});<br />
<br />
ext.point('io.ox/portal/widget/myAd').extend({<br />
title: "My Advertisement",<br />
<br />
load: function (baton) {<br />
var def = $.Deferred();<br />
def.resolve("It's like solid happiness.").done(function (data) {<br />
baton.data = {<br />
teaser: 'Buy stuff',<br />
fullText: 'Buy stuff. It is like solid happiness.'<br />
};<br />
});<br />
return def;<br />
},<br />
<br />
preview: function (baton) {<br />
var content = $('<div class="content pointer">')<br />
.text(baton.data.teaser);<br />
this.append(content);<br />
},<br />
<br />
draw: function (baton) {<br />
var content = $('<div class="myAdd">')<br />
.text(baton.data.fullText);<br />
this.append(content);<br />
}<br />
});<br />
<br />
ext.point('io.ox/portal/widget/myAd/settings').extend({<br />
title: 'My advertisement',<br />
type: 'myAd'<br />
});<br />
});<br />
</pre><br />
<br />
What happened here? We have gained two new methods and all three methods seems to be passing something called ''baton'' around. The baton is actually just that - something to pass around. The baton carries data between different methods.<br />
<br />
=== Order of execution ===<br />
How do the three functions interact? When a plugin is supposed to be rendered, the first method to be called is "load". Load usually does some (asynchronous) loading of data, be it from the file store or some external source. Meanwhile, the empty tile (well, if you give it a title, that is already rendered, so it is not completely naked) is rendered on the portal page. <br />
<br />
When the loading is done, it is consensus that the loaded data is stored as baton.data. Then ''preview'' is called and usually does something with the data in the baton. It then renders its content, which is appended to the tile.<br />
<br />
When the tile is clicked on, a side popup is drawn (which, again, is nearly naked). Meanwhile, the function ''draw'' is called. As with ''preview'', ''draw'' usually uses the data from the baton.<br />
<br />
The given example is a stereotypical use case: First, ''load'' gets the data. Then ''preview'' renders a short version of the data on the tile. When clicked, ''draw'' renders a longer, more detailed view of that data on a side popup.<br />
<br />
=== Notes ===<br />
If you look closely, you will find that the class of the container on the tile has changed to "content pointer". This is relevant, as this makes the whole tile clickable (there is a delegate for '.item .content.pointer' that does that). This is just a comfortable way to do so, you don't have to use it. If you want to have different sections of your tile to execute different actions, you will have to implement handlers yourself.<br />
<br />
This covers the most common uses of portal widgets. But if you are looking for more, we got more:<br />
<br />
== Advanced plugins ==<br />
<br />
=== Initialize ===<br />
Sometimes you want to do things even before loading. Maybe pre-populate the baton. For this we have the method ''initialize'':<br />
<pre class="language-javascript"> <br />
ext.point('io.ox/portal/widget/myAd').extend({<br />
...<br />
initialize: function (baton) {<br />
baton.default = "Defaultiness";<br />
}<br />
});<br />
</pre><br />
<br />
=== Things that require a setup ===<br />
There are some external sources that need some kind of set up before they can be used. Services that need an OAuth authorization, for example. For this, you need to implement two more functions, named ''requiresSetup'' and ''performSetup''. The former determines whether it is necessary to run a setup, the latter starts the setup process if the former returns ''true''.<br />
<br />
<pre class="language-javascript"> <br />
ext.point('io.ox/portal/widget/myAd').extend({<br />
...<br />
requiresSetup: function () {<br />
return isMissingAnAccount();<br />
},<br />
performSetup: function () {<br />
createANewAccount();<br />
}<br />
});<br />
</pre><br />
<br />
=== Unique ===<br />
Talking about things with OAuth... a lot of data sources are unique - people only have one Facebook account. To make sure the widget can only be created once, set it to ''unique'':<br />
<br />
<pre class="language-javascript"> <br />
ext.point('io.ox/portal/widget/myAd/settings').extend({<br />
title: 'My advertisement',<br />
type: 'myAd',<br />
unique: true<br />
});<br />
</pre><br />
<br />
=== Error handling ===<br />
Occasionally, it might happen that there is an error when loading an external source. Should this occur and ''load'' (which, as you know, uses a $.Deferred) call ''fail'' instead of ''done'', the function ''error'' is called. This allows you to handle this case differently. <br />
<br />
<pre class="language-javascript"> <br />
ext.point('io.ox/portal/widget/myAd').extend({<br />
...<br />
error: function (error) {<br />
$(this).empty().append(<br />
$('<div>').text('An error occurred.');<br />
);<br />
}<br />
});<br />
</pre><br />
This is not a catch-all solution, though: If you do not use ''load'' to load that data, but do it in either ''preview'' or ''draw'', this will not work. It will also not work if the service that is called wraps the error nicely in a valid response.<br />
<br />
=== Configurable settings ===<br />
Sometimes you want to fine-tune your widget. The place to do so is in the settings. If you mark your settings ''editable'', your settings gets a little 'edit' link and you get to define a function that is called. This function is given both the model and the view so you can build your own settings pane:<br />
<br />
<pre class="language-javascript"> <br />
ext.point('io.ox/portal/widget/myAd/settings').extend({<br />
editable: true,<br />
edit: function (model, view) {<br />
...<br />
}<br />
});<br />
</pre><br />
<br />
== Stuck somewhere? ==<br />
You got stuck with a problem while developing? OXpedia might help you out with the article about [[AppSuite:Debugging_the_UI | debugging the UI]].<br />
<br />
=== Checklist: Paths, names and Types ===<br />
Remember:<br />
* The path of the extension point must be <tt>io.ox/portal/widget/$name</tt><br />
* You have to have settings!<br />
* The path of the settings extension point must be <tt>io.ox/portal/widget/$name/settings</tt><br />
* The <tt>type</tt> of the settings extension point must match the <tt>$name</tt> of the portal plugin!<br />
* go all lowercase with your widget name, versions <7.6 sometimes had issues with that<br />
<br />
=== My shiny new widget does not show up in the widget selection ===<br />
Yes. That is surprising, isn't it? There is a small peculiarity about manifests: They may be in the frontend, but the backend needs to know about them. Luckily, that is done automatically on system startup. You probably did not restart your server, didn't you?<br />
<br />
If you cannot simply restart your server, but you want to test (good!), you can hack your widget into the list of loaded widgets. Open the <tt>io.ox/portal/widgets.js</tt> and look for the variable DEV_PLUGINS. Add the name of your plugin in there and re-build the UI.<br />
<br />
== Finishing touches ==<br />
Now that you have learned all there is about portal plugins, it is time to clean up. Check whether your plugin only [[AppSuite:UI manifests explained | works when a certain module is active]]. Also, maybe we can interest you in [[AppSuite:i18n | preparing the text for readers from other countries]]? There is also an article on [[AppSuite:Configuring_portal_plugins|plugins only showing under certain circumstances]].<br />
<br />
[[Category:AppSuite]]<br />
[[Category:UI]]<br />
[[Category:Developer]]</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:Writing_a_portal_plugin&diff=17489AppSuite:Writing a portal plugin2014-04-30T14:47:10Z<p>Viktor.Pracht: /* A more typical portal plugin */ added missing extension</p>
<hr />
<div>{{Stability-stable}}<br />
<br />
<div class="title">Writing a portal plugin</div><br />
<br />
'''Abstract:''' This articles covers how to write a plugin that shows on the portal page. A portal plugin always gives a short overview on a piece of information (the so-called 'tile'). It can link a longer view that is opened when the tile is clicked, this we call the side pop-up. The side pop-up is optional.<br />
<br />
== Where and how to start ==<br />
Plugins are collected in the folder ui/apps/plugins. Start your new plugin there: Create a folder and in this folder, create two files: <tt>register.js</tt> (where everything happens) and <tt>manifest.json</tt><br />
<br />
== The simplest portal plugin: An advertisement ==<br />
The simplest portal plugin comes without a side pop-up and shows static content on its tile. Two uses for this would be presenting an advertisement (or your daily creed, an often used check list....) or showing a link list (for example to other parts of an company's intranet that are not integrated into the AppSuite (yet)). We will now build an advertisement, which is just a slogan.<br />
<br />
The beauty of this is that we do not have any dependencies (for example needing another module like the file store), so the content of our manifest.json is rather simple:<br />
<br />
<pre class="language-javascript"> <br />
{<br />
"namespace": "portal"<br />
}<br />
</pre><br />
<br />
Nothing to see here. We say we belong in the portal namespace and that's it. We do not need to define any dependencies on other modules.<br />
<br />
Our register.js is only slightly longer:<br />
<br />
<pre class="language-javascript"> <br />
define('plugins/portal/myAd/register', ['io.ox/core/extensions'], function (ext) {<br />
<br />
'use strict';<br />
<br />
ext.point('io.ox/portal/widget/myAd').extend({<br />
preview: function () {<br />
var content = $('<div class="content">')<br />
.text('Buy stuff. It's like solid happiness.');<br />
this.append(content);<br />
}<br />
});<br />
<br />
ext.point('io.ox/portal/widget/myAd/settings').extend({<br />
title: 'My advertisement',<br />
type: 'myAd'<br />
});<br />
});<br />
</pre><br />
<br />
Please keep in mind, that the first parameter of define()-method refers to your app's path. According to the code above <tt>plugins/portal/myAd/</tt> should contain the upper displayed <tt>register.js</tt>.<br />
<br />
So what do we have here? We have two extension points:<br />
<br />
The first one is for the ad itself, ''io.ox/portal/widget/myAd''. This one contains a single method that we implement, ''preview''. ''Preview'' is responsible for the tile you see whenever you look at your portal. Technically, ''this'' contains the container to which you can attach your content. If you are brave, you can do changes on the container, too. But that is not needed for now.<br />
<br />
The second is less obvious: It creates an option in the settings area for the portal (the one you reach by "customize this page"). There you will have to enable your setting (yes, this is a very polite advertisement). The ''title'' is what is shown as the name of your plugin (so chose a readable one), the type references the one you used in the definition. '''Attention:''' the ''type'' attribute has to be identical to the module name in the extension point. In this case "io.ox/portal/widget/myAd/settings" has the module name ''myAd'' and the referenced ''type'' is identical: ''myAd''. Also make sure, the type doesn’t contain any "/" or "-" characters. You are save if you limit the characters used to numbers, alphabetical characters and "_".<br />
<br />
== A more typical portal plugin ==<br />
A typical portal plugin uses the tile to display a short summary or teaser of its contents and uses a side-popup to show the whole content.<br />
<br />
The manifest.json can stay the same, but the register.js needs to do a little more now:<br />
<pre class="language-javascript"> <br />
define("plugins/portal/myAd/register", ['io.ox/core/extensions'], function (ext) {<br />
<br />
"use strict";<br />
<br />
ext.point('io.ox/portal/widget').extend({<br />
id: 'myAd'<br />
});<br />
<br />
ext.point('io.ox/portal/widget/myAd').extend({<br />
title: "My Advertisement",<br />
<br />
load: function (baton) {<br />
var def = $.Deferred();<br />
def.resolve("It's like solid happiness.").done(function (data) {<br />
baton.data = {<br />
teaser: 'Buy stuff',<br />
fullText: 'Buy stuff. It is like solid happiness.'<br />
};<br />
});<br />
return def;<br />
},<br />
<br />
preview: function (baton) {<br />
var content = $('<div class="content pointer">')<br />
.text(baton.data.teaser);<br />
this.append(content);<br />
},<br />
<br />
draw: function (baton) {<br />
var content = $('<div class="myAdd">')<br />
.text(baton.data.fullText);<br />
this.append(content);<br />
}<br />
});<br />
<br />
ext.point('io.ox/portal/widget/myAd/settings').extend({<br />
title: 'My advertisement',<br />
type: 'myAd'<br />
});<br />
});<br />
</pre><br />
<br />
What happened here? We have gained two new methods and all three methods seems to be passing something called ''baton'' around. The baton is actually just that - something to pass around. The baton carries data between different methods.<br />
<br />
=== Order of execution ===<br />
How do the three functions interact? When a plugin is supposed to be rendered, the first method to be called is "load". Load usually does some (asynchronous) loading of data, be it from the file store or some external source. Meanwhile, the empty tile (well, if you give it a title, that is already rendered, so it is not completely naked) is rendered on the portal page. <br />
<br />
When the loading is done, it is consensus that the loaded data is stored as baton.data. Then ''preview'' is called and usually does something with the data in the baton. It then renders its content, which is appended to the tile.<br />
<br />
When the tile is clicked on, a side popup is drawn (which, again, is nearly naked). Meanwhile, the function ''draw'' is called. As with ''preview'', ''draw'' usually uses the data from the baton.<br />
<br />
The given example is a stereotypical use case: First, ''load'' gets the data. Then ''preview'' renders a short version of the data on the tile. When clicked, ''draw'' renders a longer, more detailed view of that data on a side popup.<br />
<br />
=== Notes ===<br />
If you look closely, you will find that the class of the container on the tile has changed to "content pointer". This is relevant, as this makes the whole tile clickable (there is a delegate for '.item .content.pointer' that does that). This is just a comfortable way to do so, you don't have to use it. If you want to have different sections of your tile to execute different actions, you will have to implement handlers yourself.<br />
<br />
This covers the most common uses of portal widgets. But if you are looking for more, we got more:<br />
<br />
== Advanced plugins ==<br />
<br />
=== Initialize ===<br />
Sometimes you want to do things even before loading. Maybe pre-populate the baton. For this we have the method ''initialize'':<br />
<pre class="language-javascript"> <br />
ext.point('io.ox/portal/widget/myAd').extend({<br />
...<br />
initialize: function (baton) {<br />
baton.default = "Defaultiness";<br />
}<br />
});<br />
</pre><br />
<br />
=== Things that require a setup ===<br />
There are some external sources that need some kind of set up before they can be used. Services that need an OAuth authorization, for example. For this, you need to implement two more functions, named ''requiresSetup'' and ''performSetup''. The former determines whether it is necessary to run a setup, the latter starts the setup process if the former returns ''true''.<br />
<br />
<pre class="language-javascript"> <br />
ext.point('io.ox/portal/widget/myAd').extend({<br />
...<br />
requiresSetup: function () {<br />
return isMissingAnAccount();<br />
},<br />
performSetup: function () {<br />
createANewAccount();<br />
}<br />
});<br />
</pre><br />
<br />
=== Unique ===<br />
Talking about things with OAuth... a lot of data sources are unique - people only have one Facebook account. To make sure the widget can only be created once, set it to ''unique'':<br />
<br />
<pre class="language-javascript"> <br />
ext.point('io.ox/portal/widget/myAd/settings').extend({<br />
title: 'My advertisement',<br />
type: 'myAd',<br />
unique: true<br />
});<br />
</pre><br />
<br />
=== Error handling ===<br />
Occasionally, it might happen that there is an error when loading an external source. Should this occur and ''load'' (which, as you know, uses a $.Deferred) call ''fail'' instead of ''done'', the function ''error'' is called. This allows you to handle this case differently. <br />
<br />
<pre class="language-javascript"> <br />
ext.point('io.ox/portal/widget/myAd').extend({<br />
...<br />
error: function (error) {<br />
$(this).empty().append(<br />
$('<div>').text('An error occurred.');<br />
);<br />
}<br />
});<br />
</pre><br />
This is not a catch-all solution, though: If you do not use ''load'' to load that data, but do it in either ''preview'' or ''draw'', this will not work. It will also not work if the service that is called wraps the error nicely in a valid response.<br />
<br />
=== Configurable settings ===<br />
Sometimes you want to fine-tune your widget. The place to do so is in the settings. If you mark your settings ''editable'', your settings gets a little 'edit' link and you get to define a function that is called. This function is given both the model and the view so you can build your own settings pane:<br />
<br />
<pre class="language-javascript"> <br />
ext.point('io.ox/portal/widget/myAd/settings').extend({<br />
editable: true,<br />
edit: function (model, view) {<br />
...<br />
}<br />
});<br />
</pre><br />
<br />
== Stuck somewhere? ==<br />
You got stuck with a problem while developing? OXpedia might help you out with the article about [[AppSuite:Debugging_the_UI | debugging the UI]].<br />
<br />
=== Checklist: Paths, names and Types ===<br />
Remember:<br />
* The path of the extension point must be <tt>io.ox/portal/widget/$name</tt><br />
* You have to have settings!<br />
* The path of the settings extension point must be <tt>io.ox/portal/widget/$name/settings</tt><br />
* The <tt>type</tt> of the settings extension point must match the <tt>$name</tt> of the portal plugin!<br />
* go all lowercase with your widget name, versions <7.6 sometimes had issues with that<br />
<br />
=== My shiny new widget does not show up in the widget selection ===<br />
Yes. That is surprising, isn't it? There is a small peculiarity about manifests: They may be in the frontend, but the backend needs to know about them. Luckily, that is done automatically on system startup. You probably did not restart your server, didn't you?<br />
<br />
If you cannot simply restart your server, but you want to test (good!), you can hack your widget into the list of loaded widgets. Open the <tt>io.ox/portal/widgets.js</tt> and look for the variable DEV_PLUGINS. Add the name of your plugin in there and re-build the UI.<br />
<br />
== Finishing touches ==<br />
Now that you have learned all there is about portal plugins, it is time to clean up. Check whether your plugin only [[AppSuite:UI manifests explained | works when a certain module is active]]. Also, maybe we can interest you in [[AppSuite:i18n | preparing the text for readers from other countries]]? There is also an article on [[AppSuite:Configuring_portal_plugins|plugins only showing under certain circumstances]].<br />
<br />
[[Category:AppSuite]]<br />
[[Category:UI]]<br />
[[Category:Developer]]</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:Changes&diff=17273AppSuite:Changes2014-03-13T14:19:28Z<p>Viktor.Pracht: /* Themes */</p>
<hr />
<div><div class="title">Changes</div><br />
<br />
== 7.6.0 ==<br />
<br />
=== grunt ===<br />
grunt has superseded jake as a build system. In this section all changes will be described.<br />
<br />
Instead of a shell wrapper around jake (the `build-appsuite` script), grunt should now be invoked<br />
directly. The recommended workflow will be described in the next subsections, where all tasks relevant<br />
for development will be explained in detail.<br />
<br />
Grunt is a well documented task-runner (see http://gruntjs.com) and there is a large community writing plugins.<br />
Unless stated otherwise, we implemented standard grunt behaviour and rely on best-practice introduced by the<br />
grunt community.<br />
<br />
==== local configuration ====<br />
All local configuration is now done in `grunt/local.conf.json` using the JSON format. This replaces<br />
the `local.conf` file, that was sourced into build-appsuite shell script. This new way is more platform<br />
independent.<br />
<br />
==== building the UI ====<br />
<br />
Details on this would be out of scope on this article. To get further information please see our [[AppSuite:GettingStartedWithGrunt | Getting Started with grunt]] guide.<br />
<br />
=== appserver ===<br />
The functionality of the appserver is now provided by the grunt-contrib-connect plugin. The `connect` task<br />
should be run in conjunction with the `watch` task like this:<br />
<br />
<pre><br />
grunt connect watch<br />
</pre><br />
<br />
This will start the appserver middleware and start watching for changed files. In case you don't want this<br />
behaviour, you have to start the `connect` task with the keepalive option (as documented in the [https://github.com/gruntjs/grunt-contrib-connect#keepalive grunt-contrib-connect documentation]):<br />
<br />
<pre><br />
grunt connect:server:keepalive<br />
</pre><br />
<br />
=== Bower ===<br />
Most of our third party front-end libraries are now managed via bower. The location for these libraries has changed from lib/ to bower_components/. These files will be handled when building by the new grunt build system and copied or concatenated accordingly.<br />
<br />
'''Warning: Manual editing/patching/hacking files in "bower_components/" is deprecated.'''<br />
<br />
''However if you are positive that there is a bug in one of these libraries a possible course of action would be to fork the package on github and commit your patch there and create an upstream pull request, in any case this should be handled by the frontend team.''<br />
<br />
An up-to-date list of packages maintained by bower can be reviewed in the bower.json file in the ui root.<br />
<br />
* jquery<br />
* underscore<br />
* mediaelement<br />
* bootstrap<br />
* bootstrap-datepicker<br />
* bootstrap-typeahead<br />
* font-awesome<br />
* open-sans-fontface<br />
* backbone<br />
* backbone-validation<br />
* Chart.js<br />
* bigscreen<br />
* jquery-placeholder<br />
* jquery-imageloader<br />
* textarea-helper<br />
* requirejs<br />
* bootstrap-accessibility-plugin<br />
<br />
Read more about bower [http://bower.io here].<br />
<br />
=== Require.js ===<br />
Require.js updated from 2.1.8 to 2.1.11<br />
<br />
We also changed the way style files are included in the require.js define() method.<br />
less and css files are now defined in the same way as javascript files, WITHOUT its extension.<br />
<br />
* less!io.ox/calendar/style.less => less!io.ox/calendar/style<br />
* css!io.ox/calendar/style.css => css!io.ox/calendar/style<br />
<br />
=== jQuery ===<br />
jQuery was updated from 2.0.3 to 2.1.0<br />
<br />
If you experience any issues please check [http://blog.jquery.com/2014/01/24/jquery-1-11-and-2-1-released/ this blogpost] for changes.<br />
<br />
=== Underscore.js ===<br />
<br />
Underscore was updated from Version 1.4.4 to Version 1.6<br />
<br />
Please read the [http://underscorejs.org/#changelog changelog].<br />
<br />
'''Hint:''' Look for "Removed the ability to call _.bindAll with no method name arguments", this was pretty much the only issue we had whilst updating.<br />
<br />
=== Backbone.js ===<br />
<br />
Backbone.js was updated from 0.9.x to Version 1.0.0<br />
<br />
Please read the [http://backbonejs.org/#changelog changelog].<br />
<br />
'''Note:''' We currently cannot update to 1.1.2, which is the current version of backbone, but will do so in the near future, when we resolve our issues.<br />
<br />
=== Bootstrap ===<br />
<br />
Bootstrap was updated from 2.2.2 to 3.1.1<br />
<br />
Please read the [http://getbootstrap.com/migration/ Bootstrap 2 to Bootstrap 3 migration guide], as there are many significant changes, to markup and styles.<br />
<br />
All bootstrap plugins and our core components have been updated accordingly.<br />
<br />
'''Note:''' In Bootstrap 3 the typeahead plugin was dropped in favor of Twitters typeahead.js. This change would break our current autocomplete functions, so we added the Bootstrap 3 Typeahead (https://github.com/bassjobsen/Bootstrap-3-Typeahead) for backwards-compatibility.<br />
<br />
See also changes for themes below.<br />
<br />
=== Themes ===<br />
<br />
We cleaned up definitions.less and removed duplicate and obsolete definitions. If you want to override specific bootstrap default values you can do so by overriding variables from "/bower_components/bootstrap/less/variables.less" in your themes definitions.less file.<br />
<br />
Mixins were also removed from definitions and reside now in a separate file "/apps/themes/mixins.less".<br />
<br />
=== Font Awesome ===<br />
<br />
Font Awesome was updated to it's latest version (4.0.3).<br />
You can read about the changes [http://fortawesome.github.io/Font-Awesome/whats-new/ here].<br />
<br />
These classes have been replaced in our core components:<br />
<br />
* icon-align-justify => fa fa-align-justify<br />
* icon-align-left => fa fa-align-left<br />
* icon-angle-left => fa fa-angle-left<br />
* icon-angle-right => fa fa-angle-right<br />
* icon-archive => fa fa-archive<br />
* icon-arrow-down => fa fa-arrow-down<br />
* icon-arrow-up => fa fa-arrow-up<br />
* icon-book => fa fa-book<br />
* icon-bookmark => fa fa-bookmark<br />
* icon-bookmark-empty => fa fa-bookmark-o<br />
* icon-caret-down => fa fa-caret-down<br />
* icon-caret-right => fa fa-caret-right<br />
* icon-chevron-left => fa fa-chevron-left<br />
* icon-chevron-right => fa fa-chevron-right<br />
* icon-circle => fa fa-circle<br />
* icon-circle-arrow-right => fa fa-circle-arrow-right<br />
* icon-cloud-download => fa fa-cloud-download<br />
* icon-cog => fa fa-cog<br />
* icon-collapse-alt => fa fa-minus-square-o<br />
* icon-comment-alt => fa fa-comment-o<br />
* icon-download-alt => fa fa-download<br />
* icon-edit => fa fa-edit<br />
* icon-envelope => fa fa-envelope<br />
* icon-envelope-alt => fa fa-envelope-o<br />
* icon-exclamation => fa fa-exclamation<br />
* icon-expand-alt => fa fa-plus-square-o<br />
* icon-external-link => fa fa-external-link<br />
* icon-external-link-sign => fa fa-external-link-square<br />
* icon-eye-open => fa fa-eye<br />
* icon-file => fa fa-file<br />
* icon-film => fa fa-film<br />
* icon-folder-close => fa fa-folder<br />
* icon-folder-open => fa fa-folder-open<br />
* icon-gear => fa fa-cog<br />
* icon-group => fa fa-group<br />
* icon-list-alt => fa fa-list-alt<br />
* icon-lock => fa fa-lock<br />
* icon-magic => fa fa-magic<br />
* icon-mail-forward => fa fa-mail-forward<br />
* icon-minus-sign => fa fa-minus-circle<br />
* icon-music => fa fa-music<br />
* icon-ok => fa fa-check<br />
* icon-paper-clip => fa fa-paperclip<br />
* icon-pencil => fa fa-pencil<br />
* icon-picture => fa fa-picture-o<br />
* icon-play => fa fa-play<br />
* icon-plus-sign => fa fa-plus-circle<br />
* icon-print => fa fa-print<br />
* icon-qrcode => fa fa-qrcode<br />
* icon-question-sign => fa fa-question-circle<br />
* icon-refresh => fa fa-refresh<br />
* icon-remove => fa fa-times<br />
* icon-remove-circle => fa fa-times-circle<br />
* icon-reorder => fa fa-bars<br />
* icon-reply => fa fa-reply<br />
* icon-resize-full => fa fa-expand<br />
* icon-retweet => fa fa-retweet<br />
* icon-rss => fa fa-rss<br />
* icon-search => fa fa-search<br />
* icon-shopping-cart => fa fa-shopping-cart<br />
* icon-signin => fa fa-sign-in<br />
* icon-spin => fa fa-spin<br />
* icon-star => fa fa-star<br />
* icon-table => fa fa-table<br />
* icon-tag => fa fa-tag<br />
* icon-th => fa fa-th<br />
* icon-th-large => fa fa-th-large<br />
* icon-th-list => fa fa-th-list<br />
* icon-tint => fa fa-tint<br />
* icon-trash => fa fa-trash-o<br />
* icon-unlock => fa fa-unlock<br />
* icon-user => fa fa-user<br />
<br />
=== TinyMCE ===<br />
<br />
TinyMCE was updated from 3.4.7 to 3.5.10.</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:Changes&diff=17272AppSuite:Changes2014-03-13T14:19:04Z<p>Viktor.Pracht: /* Bower */</p>
<hr />
<div><div class="title">Changes</div><br />
<br />
== 7.6.0 ==<br />
<br />
=== grunt ===<br />
grunt has superseded jake as a build system. In this section all changes will be described.<br />
<br />
Instead of a shell wrapper around jake (the `build-appsuite` script), grunt should now be invoked<br />
directly. The recommended workflow will be described in the next subsections, where all tasks relevant<br />
for development will be explained in detail.<br />
<br />
Grunt is a well documented task-runner (see http://gruntjs.com) and there is a large community writing plugins.<br />
Unless stated otherwise, we implemented standard grunt behaviour and rely on best-practice introduced by the<br />
grunt community.<br />
<br />
==== local configuration ====<br />
All local configuration is now done in `grunt/local.conf.json` using the JSON format. This replaces<br />
the `local.conf` file, that was sourced into build-appsuite shell script. This new way is more platform<br />
independent.<br />
<br />
==== building the UI ====<br />
<br />
Details on this would be out of scope on this article. To get further information please see our [[AppSuite:GettingStartedWithGrunt | Getting Started with grunt]] guide.<br />
<br />
=== appserver ===<br />
The functionality of the appserver is now provided by the grunt-contrib-connect plugin. The `connect` task<br />
should be run in conjunction with the `watch` task like this:<br />
<br />
<pre><br />
grunt connect watch<br />
</pre><br />
<br />
This will start the appserver middleware and start watching for changed files. In case you don't want this<br />
behaviour, you have to start the `connect` task with the keepalive option (as documented in the [https://github.com/gruntjs/grunt-contrib-connect#keepalive grunt-contrib-connect documentation]):<br />
<br />
<pre><br />
grunt connect:server:keepalive<br />
</pre><br />
<br />
=== Bower ===<br />
Most of our third party front-end libraries are now managed via bower. The location for these libraries has changed from lib/ to bower_components/. These files will be handled when building by the new grunt build system and copied or concatenated accordingly.<br />
<br />
'''Warning: Manual editing/patching/hacking files in "bower_components/" is deprecated.'''<br />
<br />
''However if you are positive that there is a bug in one of these libraries a possible course of action would be to fork the package on github and commit your patch there and create an upstream pull request, in any case this should be handled by the frontend team.''<br />
<br />
An up-to-date list of packages maintained by bower can be reviewed in the bower.json file in the ui root.<br />
<br />
* jquery<br />
* underscore<br />
* mediaelement<br />
* bootstrap<br />
* bootstrap-datepicker<br />
* bootstrap-typeahead<br />
* font-awesome<br />
* open-sans-fontface<br />
* backbone<br />
* backbone-validation<br />
* Chart.js<br />
* bigscreen<br />
* jquery-placeholder<br />
* jquery-imageloader<br />
* textarea-helper<br />
* requirejs<br />
* bootstrap-accessibility-plugin<br />
<br />
Read more about bower [http://bower.io here].<br />
<br />
=== Require.js ===<br />
Require.js updated from 2.1.8 to 2.1.11<br />
<br />
We also changed the way style files are included in the require.js define() method.<br />
less and css files are now defined in the same way as javascript files, WITHOUT its extension.<br />
<br />
* less!io.ox/calendar/style.less => less!io.ox/calendar/style<br />
* css!io.ox/calendar/style.css => css!io.ox/calendar/style<br />
<br />
=== jQuery ===<br />
jQuery was updated from 2.0.3 to 2.1.0<br />
<br />
If you experience any issues please check [http://blog.jquery.com/2014/01/24/jquery-1-11-and-2-1-released/ this blogpost] for changes.<br />
<br />
=== Underscore.js ===<br />
<br />
Underscore was updated from Version 1.4.4 to Version 1.6<br />
<br />
Please read the [http://underscorejs.org/#changelog changelog].<br />
<br />
'''Hint:''' Look for "Removed the ability to call _.bindAll with no method name arguments", this was pretty much the only issue we had whilst updating.<br />
<br />
=== Backbone.js ===<br />
<br />
Backbone.js was updated from 0.9.x to Version 1.0.0<br />
<br />
Please read the [http://backbonejs.org/#changelog changelog].<br />
<br />
'''Note:''' We currently cannot update to 1.1.2, which is the current version of backbone, but will do so in the near future, when we resolve our issues.<br />
<br />
=== Bootstrap ===<br />
<br />
Bootstrap was updated from 2.2.2 to 3.1.1<br />
<br />
Please read the [http://getbootstrap.com/migration/ Bootstrap 2 to Bootstrap 3 migration guide], as there are many significant changes, to markup and styles.<br />
<br />
All bootstrap plugins and our core components have been updated accordingly.<br />
<br />
'''Note:''' In Bootstrap 3 the typeahead plugin was dropped in favor of Twitters typeahead.js. This change would break our current autocomplete functions, so we added the Bootstrap 3 Typeahead (https://github.com/bassjobsen/Bootstrap-3-Typeahead) for backwards-compatibility.<br />
<br />
See also changes for themes below.<br />
<br />
=== Themes ===<br />
<br />
We cleaned up definitions.less and removed duplicate and obsolete definitions. If you want to override specific bootstrap default values you can do so by overriding variables from "/bower_components/bootstrap/less/variables.less" in your themes definitions.less file.<br />
<br />
Mixins were also removed from definitions and reside now in a seperate file "/apps/themes/mixins.less".<br />
<br />
=== Font Awesome ===<br />
<br />
Font Awesome was updated to it's latest version (4.0.3).<br />
You can read about the changes [http://fortawesome.github.io/Font-Awesome/whats-new/ here].<br />
<br />
These classes have been replaced in our core components:<br />
<br />
* icon-align-justify => fa fa-align-justify<br />
* icon-align-left => fa fa-align-left<br />
* icon-angle-left => fa fa-angle-left<br />
* icon-angle-right => fa fa-angle-right<br />
* icon-archive => fa fa-archive<br />
* icon-arrow-down => fa fa-arrow-down<br />
* icon-arrow-up => fa fa-arrow-up<br />
* icon-book => fa fa-book<br />
* icon-bookmark => fa fa-bookmark<br />
* icon-bookmark-empty => fa fa-bookmark-o<br />
* icon-caret-down => fa fa-caret-down<br />
* icon-caret-right => fa fa-caret-right<br />
* icon-chevron-left => fa fa-chevron-left<br />
* icon-chevron-right => fa fa-chevron-right<br />
* icon-circle => fa fa-circle<br />
* icon-circle-arrow-right => fa fa-circle-arrow-right<br />
* icon-cloud-download => fa fa-cloud-download<br />
* icon-cog => fa fa-cog<br />
* icon-collapse-alt => fa fa-minus-square-o<br />
* icon-comment-alt => fa fa-comment-o<br />
* icon-download-alt => fa fa-download<br />
* icon-edit => fa fa-edit<br />
* icon-envelope => fa fa-envelope<br />
* icon-envelope-alt => fa fa-envelope-o<br />
* icon-exclamation => fa fa-exclamation<br />
* icon-expand-alt => fa fa-plus-square-o<br />
* icon-external-link => fa fa-external-link<br />
* icon-external-link-sign => fa fa-external-link-square<br />
* icon-eye-open => fa fa-eye<br />
* icon-file => fa fa-file<br />
* icon-film => fa fa-film<br />
* icon-folder-close => fa fa-folder<br />
* icon-folder-open => fa fa-folder-open<br />
* icon-gear => fa fa-cog<br />
* icon-group => fa fa-group<br />
* icon-list-alt => fa fa-list-alt<br />
* icon-lock => fa fa-lock<br />
* icon-magic => fa fa-magic<br />
* icon-mail-forward => fa fa-mail-forward<br />
* icon-minus-sign => fa fa-minus-circle<br />
* icon-music => fa fa-music<br />
* icon-ok => fa fa-check<br />
* icon-paper-clip => fa fa-paperclip<br />
* icon-pencil => fa fa-pencil<br />
* icon-picture => fa fa-picture-o<br />
* icon-play => fa fa-play<br />
* icon-plus-sign => fa fa-plus-circle<br />
* icon-print => fa fa-print<br />
* icon-qrcode => fa fa-qrcode<br />
* icon-question-sign => fa fa-question-circle<br />
* icon-refresh => fa fa-refresh<br />
* icon-remove => fa fa-times<br />
* icon-remove-circle => fa fa-times-circle<br />
* icon-reorder => fa fa-bars<br />
* icon-reply => fa fa-reply<br />
* icon-resize-full => fa fa-expand<br />
* icon-retweet => fa fa-retweet<br />
* icon-rss => fa fa-rss<br />
* icon-search => fa fa-search<br />
* icon-shopping-cart => fa fa-shopping-cart<br />
* icon-signin => fa fa-sign-in<br />
* icon-spin => fa fa-spin<br />
* icon-star => fa fa-star<br />
* icon-table => fa fa-table<br />
* icon-tag => fa fa-tag<br />
* icon-th => fa fa-th<br />
* icon-th-large => fa fa-th-large<br />
* icon-th-list => fa fa-th-list<br />
* icon-tint => fa fa-tint<br />
* icon-trash => fa fa-trash-o<br />
* icon-unlock => fa fa-unlock<br />
* icon-user => fa fa-user<br />
<br />
=== TinyMCE ===<br />
<br />
TinyMCE was updated from 3.4.7 to 3.5.10.</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:Changes&diff=17271AppSuite:Changes2014-03-13T14:15:19Z<p>Viktor.Pracht: /* appserver */</p>
<hr />
<div><div class="title">Changes</div><br />
<br />
== 7.6.0 ==<br />
<br />
=== grunt ===<br />
grunt has superseded jake as a build system. In this section all changes will be described.<br />
<br />
Instead of a shell wrapper around jake (the `build-appsuite` script), grunt should now be invoked<br />
directly. The recommended workflow will be described in the next subsections, where all tasks relevant<br />
for development will be explained in detail.<br />
<br />
Grunt is a well documented task-runner (see http://gruntjs.com) and there is a large community writing plugins.<br />
Unless stated otherwise, we implemented standard grunt behaviour and rely on best-practice introduced by the<br />
grunt community.<br />
<br />
==== local configuration ====<br />
All local configuration is now done in `grunt/local.conf.json` using the JSON format. This replaces<br />
the `local.conf` file, that was sourced into build-appsuite shell script. This new way is more platform<br />
independent.<br />
<br />
==== building the UI ====<br />
<br />
Details on this would be out of scope on this article. To get further information please see our [[AppSuite:GettingStartedWithGrunt | Getting Started with grunt]] guide.<br />
<br />
=== appserver ===<br />
The functionality of the appserver is now provided by the grunt-contrib-connect plugin. The `connect` task<br />
should be run in conjunction with the `watch` task like this:<br />
<br />
<pre><br />
grunt connect watch<br />
</pre><br />
<br />
This will start the appserver middleware and start watching for changed files. In case you don't want this<br />
behaviour, you have to start the `connect` task with the keepalive option (as documented in the [https://github.com/gruntjs/grunt-contrib-connect#keepalive grunt-contrib-connect documentation]):<br />
<br />
<pre><br />
grunt connect:server:keepalive<br />
</pre><br />
<br />
=== Bower ===<br />
Most of our third party front-end libraries are now managed via bower. The location for these libraries has changed from lib/ to bower_components/. These files will be handled when building by the new grunt build system and copied or concatinated accordingly.<br />
<br />
'''Warning: Manual editing/patching/hacking files in "bower_components/" is deprecated.'''<br />
<br />
''However if you are positive that there is a bug in one of these libraries a possible course of action would be to fork the package on github and commit your patch there and create an upstream pull request, in any case this should be handled by the frontend team.''<br />
<br />
An up-to-date list of packages maintained by bower can be reviewed in the bower.json file in the ui root.<br />
<br />
* jquery<br />
* underscore<br />
* mediaelement<br />
* bootstrap<br />
* bootstrap-datepicker<br />
* bootstrap-typeahead<br />
* font-awesome<br />
* open-sans-fontface<br />
* backbone<br />
* backbone-validation<br />
* Chart.js<br />
* bigscreen<br />
* jquery-placeholder<br />
* jquery-imageloader<br />
* textarea-helper<br />
* requirejs<br />
* bootstrap-accessibility-plugin<br />
<br />
Read more about bower [http://bower.io here].<br />
<br />
=== Require.js ===<br />
Require.js updated from 2.1.8 to 2.1.11<br />
<br />
We also changed the way style files are included in the require.js define() method.<br />
less and css files are now defined in the same way as javascript files, WITHOUT its extension.<br />
<br />
* less!io.ox/calendar/style.less => less!io.ox/calendar/style<br />
* css!io.ox/calendar/style.css => css!io.ox/calendar/style<br />
<br />
=== jQuery ===<br />
jQuery was updated from 2.0.3 to 2.1.0<br />
<br />
If you experience any issues please check [http://blog.jquery.com/2014/01/24/jquery-1-11-and-2-1-released/ this blogpost] for changes.<br />
<br />
=== Underscore.js ===<br />
<br />
Underscore was updated from Version 1.4.4 to Version 1.6<br />
<br />
Please read the [http://underscorejs.org/#changelog changelog].<br />
<br />
'''Hint:''' Look for "Removed the ability to call _.bindAll with no method name arguments", this was pretty much the only issue we had whilst updating.<br />
<br />
=== Backbone.js ===<br />
<br />
Backbone.js was updated from 0.9.x to Version 1.0.0<br />
<br />
Please read the [http://backbonejs.org/#changelog changelog].<br />
<br />
'''Note:''' We currently cannot update to 1.1.2, which is the current version of backbone, but will do so in the near future, when we resolve our issues.<br />
<br />
=== Bootstrap ===<br />
<br />
Bootstrap was updated from 2.2.2 to 3.1.1<br />
<br />
Please read the [http://getbootstrap.com/migration/ Bootstrap 2 to Bootstrap 3 migration guide], as there are many significant changes, to markup and styles.<br />
<br />
All bootstrap plugins and our core components have been updated accordingly.<br />
<br />
'''Note:''' In Bootstrap 3 the typeahead plugin was dropped in favor of Twitters typeahead.js. This change would break our current autocomplete functions, so we added the Bootstrap 3 Typeahead (https://github.com/bassjobsen/Bootstrap-3-Typeahead) for backwards-compatibility.<br />
<br />
See also changes for themes below.<br />
<br />
=== Themes ===<br />
<br />
We cleaned up definitions.less and removed duplicate and obsolete definitions. If you want to override specific bootstrap default values you can do so by overriding variables from "/bower_components/bootstrap/less/variables.less" in your themes definitions.less file.<br />
<br />
Mixins were also removed from definitions and reside now in a seperate file "/apps/themes/mixins.less".<br />
<br />
=== Font Awesome ===<br />
<br />
Font Awesome was updated to it's latest version (4.0.3).<br />
You can read about the changes [http://fortawesome.github.io/Font-Awesome/whats-new/ here].<br />
<br />
These classes have been replaced in our core components:<br />
<br />
* icon-align-justify => fa fa-align-justify<br />
* icon-align-left => fa fa-align-left<br />
* icon-angle-left => fa fa-angle-left<br />
* icon-angle-right => fa fa-angle-right<br />
* icon-archive => fa fa-archive<br />
* icon-arrow-down => fa fa-arrow-down<br />
* icon-arrow-up => fa fa-arrow-up<br />
* icon-book => fa fa-book<br />
* icon-bookmark => fa fa-bookmark<br />
* icon-bookmark-empty => fa fa-bookmark-o<br />
* icon-caret-down => fa fa-caret-down<br />
* icon-caret-right => fa fa-caret-right<br />
* icon-chevron-left => fa fa-chevron-left<br />
* icon-chevron-right => fa fa-chevron-right<br />
* icon-circle => fa fa-circle<br />
* icon-circle-arrow-right => fa fa-circle-arrow-right<br />
* icon-cloud-download => fa fa-cloud-download<br />
* icon-cog => fa fa-cog<br />
* icon-collapse-alt => fa fa-minus-square-o<br />
* icon-comment-alt => fa fa-comment-o<br />
* icon-download-alt => fa fa-download<br />
* icon-edit => fa fa-edit<br />
* icon-envelope => fa fa-envelope<br />
* icon-envelope-alt => fa fa-envelope-o<br />
* icon-exclamation => fa fa-exclamation<br />
* icon-expand-alt => fa fa-plus-square-o<br />
* icon-external-link => fa fa-external-link<br />
* icon-external-link-sign => fa fa-external-link-square<br />
* icon-eye-open => fa fa-eye<br />
* icon-file => fa fa-file<br />
* icon-film => fa fa-film<br />
* icon-folder-close => fa fa-folder<br />
* icon-folder-open => fa fa-folder-open<br />
* icon-gear => fa fa-cog<br />
* icon-group => fa fa-group<br />
* icon-list-alt => fa fa-list-alt<br />
* icon-lock => fa fa-lock<br />
* icon-magic => fa fa-magic<br />
* icon-mail-forward => fa fa-mail-forward<br />
* icon-minus-sign => fa fa-minus-circle<br />
* icon-music => fa fa-music<br />
* icon-ok => fa fa-check<br />
* icon-paper-clip => fa fa-paperclip<br />
* icon-pencil => fa fa-pencil<br />
* icon-picture => fa fa-picture-o<br />
* icon-play => fa fa-play<br />
* icon-plus-sign => fa fa-plus-circle<br />
* icon-print => fa fa-print<br />
* icon-qrcode => fa fa-qrcode<br />
* icon-question-sign => fa fa-question-circle<br />
* icon-refresh => fa fa-refresh<br />
* icon-remove => fa fa-times<br />
* icon-remove-circle => fa fa-times-circle<br />
* icon-reorder => fa fa-bars<br />
* icon-reply => fa fa-reply<br />
* icon-resize-full => fa fa-expand<br />
* icon-retweet => fa fa-retweet<br />
* icon-rss => fa fa-rss<br />
* icon-search => fa fa-search<br />
* icon-shopping-cart => fa fa-shopping-cart<br />
* icon-signin => fa fa-sign-in<br />
* icon-spin => fa fa-spin<br />
* icon-star => fa fa-star<br />
* icon-table => fa fa-table<br />
* icon-tag => fa fa-tag<br />
* icon-th => fa fa-th<br />
* icon-th-large => fa fa-th-large<br />
* icon-th-list => fa fa-th-list<br />
* icon-tint => fa fa-tint<br />
* icon-trash => fa fa-trash-o<br />
* icon-unlock => fa fa-unlock<br />
* icon-user => fa fa-user<br />
<br />
=== TinyMCE ===<br />
<br />
TinyMCE was updated from 3.4.7 to 3.5.10.</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:GettingStartedWithGrunt&diff=17270AppSuite:GettingStartedWithGrunt2014-03-13T14:03:11Z<p>Viktor.Pracht: /* Linux */</p>
<hr />
<div><div class="title">Getting started with grunt</div><br />
__TOC__<br />
== Node ==<br />
<br />
=== Linux ===<br />
<br />
Install the default nodejs of your distribution via your favourite package/ports manager and you are good to go.<br />
<br />
If you are having problems or your package manager does not provide at least nodejs in version 0.10.x please have a look at https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager<br />
<br />
=== Windows ===<br />
<br />
Head to the node.js [http://nodejs.org/ site] and download and install the latest version.<br />
It is recommended to restart after the installation, as paths may not be up-to-date.<br />
<br />
Please also make sure git is installed and in your PATH.<br />
<br />
''This is sometimes a problem on windows, make sure to activate the option to put git into your path during msys-git installation.''<br />
<br />
=== Mac OS X ===<br />
<br />
We strongly encourage you to use [http://brew.sh/ homebrew]. Actually, we won't support you if you don't. It's that bad.<br />
<br />
Make sure you have an up-to-date homebrew installation.<br />
<br />
<pre><br />
brew update<br />
brew upgrade<br />
</pre><br />
<br />
Check your homebrew installation with <tt>brew doctor</tt> and resolve any issues and repeat this step until homebrews output says "Your system is ready to brew.".<br />
<br />
<pre><br />
brew doctor<br />
</pre><br />
<br />
Install node via <tt>brew install node</tt> if is not yet installed.<br />
<br />
<pre><br />
brew install node<br />
</pre><br />
<br />
Make sure you '''never <tt>sudo</tt> anything related to node or its package manager npm'''. If you think you have to, you are doing something wrong and are probably dealing with a broken homebrew/macports installation! If this is the case, the easiest way of resolving this is completely deleting the homebrew (and if present macports) directories and (re)installing homebrew.<br />
<br />
The default system's max opened file limit in mac os x is very low (256), in order to use grunt watch, it needs to be increased.<br />
<br />
You can either set this in your shell via <tt>ulimit -n 8192</tt> to a sensible value.<br />
<br />
<pre><br />
ulimit -n 8192<br />
</pre><br />
<br />
or you can set<br />
it permanently by adding <tt>limit maxfiles 8192 20480</tt> to <tt>/etc/launchd.conf</tt><br />
<br />
<pre><br />
echo "limit maxfiles 8192 20480" | sudo tee -a /etc/launchd.conf<br />
</pre><br />
<br />
''Note that you will have to restart your system for the setting to be active.''<br />
<br />
== Grunt & Bower ==<br />
<br />
With <tt>npm install -g bower grunt-cli</tt> you can install the global npm dependencies needed for grunt and bower.<br />
<br />
'''Mac OS X / Windows:'''<br />
<pre><br />
npm install -g bower grunt-cli<br />
</pre><br />
<br />
'''Linux ''only'':'''<br />
You may need root privileges to install global npm modules.<br />
<pre><br />
sudo npm install -g bower grunt-cli<br />
</pre><br />
<br />
== Cleaning development environment ==<br />
<br />
Sometimes it is needed to completely wipe all old and ignored (by git) files. You can also do this using git by running <tt>git clean -ndx</tt> this will print a lot of files, but _not_ delete any. Check the list if you really want to remove these files. Then run <tt>git clean -fdx</tt> to really do the cleanup.<br />
<br />
== Installing node dependencies for OX Appsuite Frontend development ==<br />
<br />
Change to the ui directory of your git workdirectory and run <tt>npm install</tt>.<br />
Make sure, you have got the git binary in your path. (This is sometimes a problem on windows,<br />
make sure to activate the option to put git into your path during msys-git installation. TODO: more detail)<br />
<br />
<pre><br />
npm install<br />
</pre><br />
<br />
== Building the UI ==<br />
<br />
Just run the default grunt task <tt>grunt</tt><br />
<br />
<pre><br />
grunt<br />
</pre><br />
<br />
== Local configuration ==<br />
<br />
You can override some options on your local build environment by creating the file <tt>grunt/local.conf.json</tt>. See <tt>grunt/local.conf.default.json</tt> as a template.<br />
<br />
Hint: copy the default file to <tt>grunt/local.conf.json</tt> to get started.<br />
<br />
<pre><br />
cp grunt/local.conf.default.json grunt/local.conf.json<br />
vi grunt/local.conf.json<br />
</pre><br />
<br />
If you want to use the proxy function of the appserver, at least the server-variable needs to be configured.<br />
<br />
<pre><br />
{<br />
"appserver": {<br />
"server": "http://url.to.your.ser/appsuite/",<br />
"verbose": ["local:error"]<br />
}<br />
}<br />
</pre><br />
<br />
<br />
== Accessing the UI ==<br />
<br />
You can run the appserver with the connect grunt task:<br />
<br />
<pre><br />
grunt connect:server:keepalive<br />
</pre><br />
<br />
or in combination with the watch task:<br />
<br />
<pre><br />
grunt connect watch<br />
</pre><br />
<br />
You can now access the ui via <tt>http://localhost:8337/appsuite/</tt>.</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:I18n&diff=17183AppSuite:I18n2014-03-03T11:47:26Z<p>Viktor.Pracht: /* Custom Translations */</p>
<hr />
<div>{{Stability-experimental}}<br />
<br />
<div class="title">Internationalization (i18n)</div><br />
<br />
__TOC__<br />
<br />
Providing software for users in the whole world means providing it in multiple languages. This consists of two steps:<br />
<br />
* ''Internationalization (i18n)'' - Making the software international, i. e. preparing it to be adapted to different languages and locations.<br />
* ''Localization (L10n)'' - Adapting the software to a particular language and/or location.<br />
The Open-Xchange platform offers several facilities to simplify both parts. The L10n part is mostly a concern for translators. Open-Xchange facilities for that consist mainly of using a well-established format for translations: [http://www.gnu.org/s/gettext/ GNU Gettext] Portable Object (PO) files. This allows translators to use existing dedicated translation tools or a simple UTF-8-capable text editor.<br />
<br />
The i18n part is what software developers will be mostly dealing with and is what the rest of this document describes.<br />
<br />
==Translation==<br />
<br />
The main part of i18n is the translation of various text strings which are presented to the user. For this purpose, the Open-Xchange platform provides the RequireJS plugin <tt>'gettext'</tt>. Individual translation files are specified as a module dependency of the form <tt>'gettext!module_name'</tt>. The resulting module API is a function which can be called to translate a string using the specified translation files:<br />
<br />
<pre class="language-javascript"><br />
define('com.example/example', ['gettext!com.example/example'],<br />
function (gt) {<br />
'use strict';<br />
alert(gt('Hello, world!'));<br />
});<br />
</pre><br />
<br />
After building the module, the file ox.pot in the project's root directory will contain an entry for every call to one of <tt>gettext</tt> functions:<br />
<br />
<pre class="language-gettext"><br />
#: apps/com.example/example.js:4<br />
msgid "Hello, world!"<br />
msgstr ""<br />
</pre><br />
<br />
After translation, the PO files in the directory <tt>i18n</tt> shoud contain the translated entry:<br />
<br />
<pre class="language-gettext"><br />
#: apps/com.example/example.js:4<br />
msgid "Hello, world!"<br />
msgstr "Hallo, Welt!"<br />
</pre><br />
<br />
During the next build, the entries are copied from the central PO files into individual translation files. In our example, this would be <tt>apps/com.example/example.de_DE.js</tt>. Because of the added language ID, translation files can usually have the same name as the corresponding main module. Multiple related modules should use the same translation file to avoid the overhead of too many small translation files.<br />
<br />
Most modules will require more complex translations than can be provided by a simple string lookup. To handle some of these cases, the <tt>gettext</tt> module provides traditional methods in addition to being a callable function. Other cases are handled by the build system.<br />
<br />
==Composite Phrases==<br />
<br />
In most cases, the translated texts will not be static, but contain dynamic values as parts of a sentence. The straight-forward approach of translating parts of the sentence individually and then using string concatenation to compose the final text is a BAD idea. Different languages have different sentence structures, and if there are multiple dynamic values, their order might need to be reversed in some languages, and not reversed in others.<br />
<br />
The solution is to translate entire sentences and then to use the <tt>gettext</tt> function to insert dynamic values:<br />
<br />
<pre class="language-javascript"><br />
alert(<br />
//#. %1$s is the given name<br />
//#. %2$s is the family name<br />
//#, c-format<br />
gt('Welcome, %1$s %2$s!', firstName, lastName));<br />
</pre><br />
<br />
Results in:<br />
<br />
<pre class="language-gettext"><br />
#. %1$s is the given name<br />
#. %2$s is the family name<br />
#, c-format<br />
msgid "Welcome, %1$s, %2$s"<br />
msgstr ""<br />
</pre><br />
<br />
As shown in the example, it is possible to add comments for translators by starting a comment with <tt>"#."</tt>. Such comments must be placed immediately before the name of the variable which refers to the <tt>gettext</tt> module (in this case <tt>gt</tt>). They can be separated by arbitrary whitespace and newlines, but not other tokens. All such <tt>gettext</tt> calls should have comments explaining every format specifier.<br />
<br />
Comments starting with <tt>"#,"</tt> are meant for <tt>gettext</tt> tools, which in the case of <tt>"#, c-format"</tt>, can ensure that the translator did not leave out or mistype any of the format specifiers.<br />
<br />
For the cases when the format string must be translated by one of the functions described below, there is a dedicated format function <tt>gettext.format</tt> which, except for debugging, is an alias for <tt>_.printf</tt>.<br />
<br />
==Debugging==<br />
<br />
One of the most common i18n errors is forgetting to use a <tt>gettext</tt> function. To catch this kind of error, the UI can be started with the hash parameter <tt>"#debug-i18n=1"</tt>. (Reloading of the browser tab is usually required for the setting to take effect.)<br />
<br />
In this mode, every translated string is marked with invisible Unicode characters, and any DOM text without those characters gets reported on the console. The <tt>gettext.format</tt> function then also checks that every parameter is translated. This is the reason why <tt>_.printf</tt> should not be used for user-visible strings directly.<br />
<br />
Unfortunately, this method will also report any string which does not actually require translation. Examples of such strings include user data, numbers, strings already translated by the server, etc. To avoid filling the console with such false positives, every such string must be marked by passing it through the function <tt>gettext.noI18n</tt>:<br />
<br />
<pre class="language-javascript"><br />
alert(<br />
//#. %1$s is the given name<br />
//#. %2$s is the family name<br />
//#, c-format<br />
gt('Welcome, %1$s %2$s!', gt.noI18n(firstName), gt.noI18n(lastName)));<br />
</pre><br />
<br />
This results in the strings being marked as 'translated' without actually changing their visible contents. When not debugging, <tt>gettext.noI18n</tt> simply returns its first parameter.<br />
<br />
==Advanced gettext Functions==<br />
<br />
Besides <tt>gettext.format</tt> and <tt>gettext.noI18n</tt> there are several other functions which are required to cover all typical translation scenarios.<br />
<br />
===Contexts===<br />
<br />
Sometimes, the same English word or phrase has multiple meanings and must be translated differently depending on context. To be able to tell the individual translations apart, the method <tt>gettext.pgettext</tt> ('p' stands for 'particular') should be used instead of calling <tt>gettext</tt> directly. It takes the context as the first parameter and the text to translate as the second parameter:<br />
<br />
<pre class="language-javascript"><br />
alert(gt.pgettext('description', 'Title'));<br />
alert(gt.pgettext('salutation', 'Title'));<br />
</pre><br />
<br />
Results in:<br />
<br />
<pre class="language-gettext"><br />
msctxt "description"<br />
msgid "Title"<br />
msgstr "Beschreibung"<br />
<br />
msctxt "salutation"<br />
msgid "Title"<br />
msgstr "Anrede"<br />
</pre><br />
<br />
===Plural forms===<br />
<br />
In the case of numbers, the rules to select the proper plural form can be very complex. With the exception of languages with no separate plural forms, English is the second simplest language in this respect, having only two plural forms: singular and plural. Other languages can have up to four forms, and theoretically even more. The functions <tt>gettext.ngettext</tt> and <tt>gettext.npgettext</tt> (for a combination of plural forms with contexts) can select the proper plural form by using a piece of executable code embedded in the header of a PO file:<br />
<br />
<pre class="language-javascript"><br />
alert(gt.format(<br />
//#. %1$d is the number of mails<br />
//#, c-format<br />
gt.ngettext('You have %1$d mail', 'You have %1$d mails', n),<br />
gt.noI18n(n)));<br />
</pre><br />
<br />
The function <tt>gettext.ngettext</tt> accepts three parameters: the English singular and plural forms and the number which determines the chosen plural form. The function <tt>gettext.npgettext</tt> adds a context parameter before the others, similar to <tt>gettext.pgettext</tt>. They are usually used in combination with <tt>gettext.format</tt> to insert the actual number into the translated string.<br />
<br />
The above example results in the following entry:<br />
<br />
<pre class="language-gettext"><br />
#. %1$d is the number of mails<br />
#, c-format<br />
msgid "You have %1$d mail"<br />
msgid_plural "You have %1$d mails"<br />
msgstr[0] ""<br />
msgstr[1] ""<br />
</pre><br />
<br />
The number of <tt>msgstr[N]</tt> lines is determined by the number of plural forms in each language. This number is specified in the header of each PO file, together with the code to compute the index of the correct plural form the supplied number.<br />
<br />
==Custom Translations==<br />
App Suite has support for custom translations. ''gettext'' provides a function ''addTranslation(dictionary, key, value)'' that allows adding custom translation to a global dictionary ("*") as well as replacing translations in existing dictionaries. In order to use this, you have to create a plugin for the "core" namespace.<br />
<br />
<pre class="language-javascript"> <br />
var gt = require('io.ox/core/gettext');<br />
gt.addTranslation('*', 'Existing translation', 'My custom translation');<br />
</pre><br />
<br />
To keep it simple you can use the internal escaping to build counterparts for ngettext, pgettext, as well as npgettext. A context is escaped by \x00. Singular and plural are separated by \x01:<br />
<br />
<pre class="language-javascript"> <br />
// load gettext<br />
var gt = require('io.ox/core/gettext');<br />
<br />
// replace translation in dictionary 'io.ox/core'. Apps use context "app".<br />
gt.addTranslation('io.ox/core', 'app\x00Address Book', 'My Contacts');<br />
<br />
// replace translation - counterpart to ngettext<br />
gt.addTranslation('io.ox/mail', 'Copy\x01Copies', { 0: 'Kopie', 1: 'Kopien' });<br />
<br />
// replace translation - counterpart to npgettext<br />
gt.addTranslation('io.ox/mail', 'test\x00One\x01Two', { 0: 'Eins', 1: 'Zwei' });<br />
<br />
// some checks<br />
require(['gettext!io.ox/mail'], function (gt) {<br />
<br />
console.log('Sigular:', gt.ngettext('Copy', 'Copies', 1));<br />
console.log('Plural:', gt.ngettext('Copy', 'Copies', 2));<br />
<br />
console.log('Without context', gt.gettext('Files')); // should be 'My File Box'<br />
console.log('With context', gt.pgettext('test', 'Files')); // should be 'Files'<br />
<br />
console.log('Plural with context', gt.npgettext('test', 'One', 'Two', 2)); // should be 'Two'<br />
});<br />
<br />
</pre><br />
<br />
''addTranslation()'' always works for current language. If you want to benefit from automatic POT file generation, use the following approach:<br />
<br />
<pre class="language-javascript"> <br />
define('plugins/example/register', ['io.ox/core/gettext', 'gettext!custom'], function (gettext, gt) {<br />
<br />
'use strict';<br />
<br />
/* Just list all custom translations in your plugin by standalone gt() calls.<br />
The build system recognizes these strings and collects them in a POT file, <br />
so that they can be subject to translation processes. At runtime, gt('...')<br />
returns translations for current language.<br />
*/<br />
if (false) {<br />
gt('Tree');<br />
gt('House');<br />
gt('Dog');<br />
}<br />
<br />
// get internal dictionary (for current language of course)<br />
var dictionary = gt.getDictionary();<br />
<br />
// add all translations to global dictionary. Done!<br />
gettext.addTranslation('*', dictionary);<br />
});<br />
</pre><br />
<br />
<br />
[[Category:AppSuite]]<br />
[[Category:UI]]<br />
[[Category:Developer]]</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=HTTP_API&diff=17131HTTP API2014-02-20T16:02:21Z<p>Viktor.Pracht: /* Module "emig" */</p>
<hr />
<div>== Introduction ==<br />
<br />
This document defines the Open-Xchange HTTP API which is used by the new AJAX GUI. The first chapter describes general definitions and conventions which apply to all server modules. All other chapters describe individual server modules.<br />
<br />
=== Low level protocol ===<br />
<br />
The client accesses the server through HTTP GET, POST and PUT requests. HTTP cookies are used for authentication and must therefore be processed and sent back by the client as specified by [http://tools.ietf.org/html/rfc6265 RFC 6265]. The HTTP API is accessible at URIs starting with <code>/ajax</code>. Each server module has a unique name and its own sub-namespace with that name below <code>/ajax</code>, e. g. all access to the module "tasks" is via URIs starting with <code>/ajax/tasks</code>.<br />
<br />
Text encoding is always UTF-8. Data is sent from the server to the client as <code>text/javascript</code> and interpreted by the client to obtain an ECMAScript object. The HTTP API uses only a small subset of the ECMAScript syntax. This subset is roughly described by the following BNF:<br />
<br />
Value ::= "null" | Boolean | Number | String | Array | Object<br />
Boolean ::= "true" | "false"<br />
Number ::= see NumericLiteral in ECMA 262 3rd edition<br />
String ::= \"([^"\n\\]|\\["\n\\])*\"<br />
Array ::= "[]" | "[" Value ("," Value)* "]"<br />
Object ::= "{}" | "{" Name ":" Value ("," Name ":" Value)* "}"<br />
Name ::= [A-Fa-f][0-9A-Fa-f_]*<br />
<br />
Numbers are the standard signed integer and floating point numbers. Strings can contain any character, except double quotes, newlines and backslashes, which must be escaped by a backslash. Control characters in strings (other than newline) are not supported. Whitespace is allowed between any two tokens. See [http://json.org JSON] and [http://www.ecma-international.org/publications/standards/Ecma-262.htm ECMA 262, 3<sup>rd</sup> edition] for the formal definition.<br />
<br />
The response body consists of an object, which contains up to four fields as described in [[#ResponseBody | Response body]]. The field <code>data</code> contains the actual payload which is described in following chapters. The fields <code>timestamp</code>, <code>error</code> and <code>error_params</code> are present when data objects are returned, if an error occurred and if the error message contains conversion specifiers, respectively. Following sections describe the contents of these fields in more detail.<br />
<br />
{| id="ResponseBody" cellspacing="0" border="1"<br />
|+ align="bottom" | Response body<br />
! Name !! Type !! Value<br />
|-<br />
| data || Value || Payload of the response.<br />
|-<br />
| timestamp || Timestamp || The latest timestamp of the returned data (see [[HTTP_API#Updates|Updates]]).<br />
|-<br />
| error || String || The translated error message. Present in case of errors.<br />
|-<br />
| error_params || Array || As o 7.4.2: Empty JSON array. Before that: Parameters for the error message that would need to be replaced in the error string (in a printf-format style).<br />
|-<br />
| error_id || String || Unique error identifier to help finding this error instance in the server logs.<br />
|-<br />
| error_desc || String || The technical error message (always English) useful for debugging the problem. Might be the same as error message if there is no more information available<br />
|-<br />
| code || String || Error code consisting of an upper-case module identifier and a four-digit message number, separated by a dash; e.g. "MSG-0012"<br />
|-<br />
| error_stack || Array || If configured (see "com.openexchange.ajax.response.includeStackTraceOnError" in 'server.properties') this field provides the stack trace of associated Java exception represented as a JSON array<br />
|-<br />
| categories || String OR Array || Either a single (String) or list (Array) of upper-case category identifiers to which the error belongs. E.g.<br />
{| cellspacing="0" border="1"<br />
| "USER_INPUT" || An error resulting from wrong or missing input from front-end (e.g. mandatory field missing).<br />
|-<br />
| "CONFIGURATION" || An error related to user/system configuration which denies requested operation.<br />
|-<br />
| "PERMISSION_DENIED" || An error related to insufficient permission settings.<br />
|-<br />
| "TRY_AGAIN" || A requested operation could not be accomplished because a needed resource is temporary down or missing (e.g. imap server rejects connection because of too many established connections).<br />
|-<br />
| "SERVICE_DOWN" || A subsystem or third party service is down and therefore does not respond (e.g. database is down).<br />
|-<br />
| "CONNECTIVITY" || The underlying socket connection is corrupt, empty or closed. Only a temporary error that does not affect the whole system.<br />
|-<br />
| "ERROR" || A programming error which was caused by incorrect program code.<br />
|-<br />
| "CONFLICT" || A concurrent modification.<br />
|-<br />
| "CAPACITY" || The requested operation could not be performed cause an underlying resource is full or busy (e.g. IMAP folder exceeds quota).<br />
|-<br />
| "TRUNCATED" || The given data could not be stored into the database because an attribute contains a too long value.<br />
|-<br />
| "WARNING" || Action was at least partially successful, but a condition occurred that merited a warning<br />
|}<br />
|-<br />
| category || Number || Maintained for legacy reasons: The numeric representation of the first category:<br />
{| cellspacing="0" border="1"<br />
| 1 || An error resulting from wrong or missing input from front-end (e.g. mandatory field missing).<br />
|-<br />
| 2 || An error strictly related to user configuration which denies requested operation.<br />
|-<br />
| 3 || An error related to insufficient permission settings.<br />
|-<br />
| 4 || A requested operation could not be accomplished because a needed resource is temporary down or missing (e.g. imap server rejects connection because of too many established connections).<br />
|-<br />
| 5 || A subsystem or third party service is down and therefore does not respond (e.g. database is down).<br />
|-<br />
| 6 || The underlying socket connection is corrupt, empty or closed. Only a temporary error that does not affect the whole system.<br />
|-<br />
| 8 || A programming error which was caused by incorrect programm code.<br />
|-<br />
| 9 || A concurrent modification.<br />
|-<br />
| 11 || The requested operation could not be performed cause an underlying resource is full or busy (e.g. IMAP folder exceeds quota).<br />
|-<br />
| 12 || The given data could not be stored into the database because an attribute contains a too long value.<br />
|-<br />
| 13 || Action was at least partially successful, but a condition occurred that merited a warning<br />
|}<br />
|}<br />
<br />
Data from the client to the server can be sent in several formats. Small amounts of data are sent as <code>application/x-www-urlencoded</code> in query parameters in the request URI. For POST requests, some or all parameters may be sent in the request body instead of in the URI using any valid encoding for POST requests. Alternatively, some requests specify that data is sent as <code>text/javascript</code> in the body of a PUT request. The format of the request body for PUT requests is the same as for sending data from the server to the client, except that the payload is sent directly, without being wrapped in another object.<br />
<br />
When updating existing data, the client sends only fields that were modified. To explicitly delete a field, the field is sent with the value <code>null</code>. For fields of type <code>String</code>, the empty string <code>""</code> is equivalent to <code>null</code>.<br />
<br />
=== Error handling ===<br />
<br />
If the session of the user times out, if the client doesn't send a session ID or if the session for the specified session ID can not be found then the server returns the above described response object, that contains an error code and an error message. If the request URI or the request body is malformed or incomplete then the server returns the reponse object with an error message, too. In case of internal server errors, especially Java exceptions, or if the server is down, it returns the HTTP status code 503, Service Unavailable. Other severe errors may return other HTTP status values.<br />
<br />
Application errors, which can be caused by a user and are therefore expected during the operation of the groupware, are reported by setting the field error in the returned object, as described in [[#ResponseBody | Response body]]. Since the error messages are translated by the client, they can not be composed of multiple variable parts. Instead, the error message can contain simplified printf()-style conversion specifications, which are replaced by elements from the array in the field error_params. If error_params is not present, no replacement occurs, even if parts of the error message match the syntax of a conversion specification.<br />
<br />
A simplified conversion specification, as used for error messages, is either of the form %s or %''n''$s, where ''n'' is a 1-based decimal parameter index. The conversion specifications are replaced from left to right by elements from error_params, starting at the first element. %s is replaced by the current element and the current index is incremented. %''n''$s is replaced by the ''n''th element and the current index is set to the (''n'' + 1)th element.<br />
<br />
Some error message contain data sizes which must be expressed in Bytes or Kilobytes etc., depending on the actual value. Since the unit must be translated, this conversion is performed by the client. Unfortunately, standard printf()-style formatting does not have a specifier for this kind of translation. Therefore, the conversion specification for sizes is the same as for normal strings, and the client has to determine which parameters to translate based on the error code. The current error codes and the corresponding size parameters are listed in [[#DataSizeParameters | Data size parameters]]<br />
<br />
{| id="DataSizeParameters" cellspacing="0" border="1"<br />
|+ align="bottom" | Data size parameters<br />
! Error code !! Parameter indices<br />
|-<br />
| AJP-0006 || 1<br />
|-<br />
| AJP-0020 || 1, 2<br />
|-<br />
| CON-0101 || 2, 3<br />
|-<br />
| FLS-0003 || 1, 2, 3<br />
|-<br />
| MSG-0065 || 1, 3<br />
|-<br />
| MSG-0066 || 1<br />
|-<br />
| NON-0005 || 1, 2<br />
|-<br />
|}<br />
<br />
<br />
=== Date and time ===<br />
<br />
Dates without time are transmitted as the number of milliseconds between 00:00 UTC on that date and 1970-01-01 00:00 UTC. Leap seconds are ignored, therefore this number is always an integer multiple of 8.64e7.<br />
<br />
Because ECMAScript Date objects have no way to explicitly specify a timezone for calculations, timezone correction must be performed on the server. Dates with time are transmitted as the number of milliseconds since 1970-01-01 00:00 UTC (again, ignoring leap seconds) plus the offset between the ''user's'' timezone and UTC at the time in question. (See the Java method java.util.TimeZone.getOffset(long)). Unless optional URL parameter <code>'''timezone'''</code> is present. Then dates with time are transmitted as the number of milliseconds since 1970-01-01 00:00 UTC (again, ignoring leap seconds) plus the offset between the ''specified'' timezone and UTC at the time in question.<br />
<br />
For some date and time values, especially timestamps, monotonicity is more important than the actual value. Such values are transmitted as the number of milliseconds since 1970-01-01 00:00 UTC, ignoring leap seconds and without timezone correction. If possible, a unique strictly monotonic increasing value should be used instead, as it avoids some race conditions described below.<br />
<br />
This specification refers to these three interpretations of the type Number as separate data types. The types are described in [[#DateAndTimeTypes | Date and time types]].<br />
<br />
{| id="DateAndTimeTypes" cellspacing="0" border="1"<br />
|+ align="bottom" | Date and time types<br />
! Type !! Time !! Timezone !! Comment<br />
|-<br />
| Date || No || UTC || Date without time.<br />
|-<br />
| Time || Yes || User || Date and time.<br />
|-<br />
| Timestamp || Yes || UTC || Timestamp or unique sequence number.<br />
|-<br />
|}<br />
<br />
=== Updates ===<br />
<br />
To allow efficient synchronization of a client with changes made by other clients and to detect conflicts, the server stores a timestamp of the last modification for each object. Whenever the server transmits data objects to the client, the response object described in [[#ResponseBody | Response body]] includes the field timestamp. This field contains a timestamp value which is computed as the maximum of the timestamps of all transmitted objects.<br />
<br />
When requesting updates to a previously retrieved set of objects, the client sends the last timestamp which belongs to that set of objects. The response contains all updates with timestamps greater than the one specified by the client. The field timestamp of the response contains the new maximum timestamp value.<br />
<br />
If multiple different objects may have the same timestamp values, then a race condition exists when an update is processed between two such objects being modified. The first, already modified object will be included in the update response and its timestamp will be the maximum timestamp value sent in the timestamp field of the response. If the second object is modified later but gets the same timestamp, the client will never see the update to that object because the next update request from the client supplies the same timestamp value, but only modifications with greater timestamp values are returned.<br />
<br />
If unique sequence numbers can't be used as timestamps, then the risk of the race condition can be at least minimized by storing timestamps in the most precise format and/or limiting update results to changes with timestamp values which are measurably smaller than the current timestamp value.<br />
<br />
=== Editing ===<br />
<br />
Editing objects is performed one object at a time. There may be multiple objects being edited by the same client simulataneously, but this is achieved by repeating the steps required for editing a single object. There is no batch edit or upload command.<br />
<br />
To edit an object, a client first requests the entire object from the server. The server response contains the timestamp field described in the previous section. For in-place editing inside a view of multiple objects, where only already retrieved fields can be changed, retrieving the entire object is not necessary, and the last timestamp of the view is used as the timestamp of each object in it.<br />
<br />
When sending the modified object back to the server, only modified fields need to be included in the sent object. The request also includes the timestamp of the edited object. The timestamp is used by the server to ensure that the object was not edited by another client in the meantime. If the current timestamp of the object is greater than the timestamp supplied by the client, then a conflict is detected and the field error is set in the response. Otherwise, the object gets a new timestamp and the response to the client is empty.<br />
<br />
If the client displays the edited object in a view together with other objects, then the client will need to perform an update of that view immediately after successfully uploading an edited object.<br />
<br />
=== File uploads ===<br />
<br />
File uploads are made by sending a POST request that submits both the file and the needed fields as parts of a request of content-type “multipart/form-data” or “multipart/mixed”. The file metadata are stored in a form field “file” (much like an <input type=”file” name=”file” /> would do). In general a call that allows file uploads via POST will have a corresponding call using PUT to send object data. The JSON-encoded object-data that is send as the body of a corresponding PUT call is, when performed as a POST with file uploads, put into the request parameter “json”.<br />
<br />
Since the upload is performed directly by the browser and is not an Ajax call, the normal callback mechanism for asynchronous Javascript calls cannot be used to obtain the result. For this reason the server responds to these POST calls with a complete HTML page that performs the callback and should not be displayed to the user. The HTML response is functionally equivalent to:<br />
<br />
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><br />
<html><br />
<head><br />
<META http-equiv="Content-Type" content=\"text/html; charset=UTF-8\"><br />
<script type="text/javascript"><br />
(parent["callback_<b>action</b>"] || window.opener && window.opener["callback_<b>action</b>"])<br />
(<b>{json}</b>)<br />
</script><br />
</head><br />
</html><br />
<br />
The placeholders <code>{json}</code> is replaced by the response with the timestamp that would be expected from the corresponding PUT method. The placeholder <code>action</code> is replaced by the value of the parameter <code>action</code> of the request (except for the import bundle, which is named "import" instead of the action name for legacy purposes). The content-type of the answer is <code>text/html</code>.<br />
<br />
Non-browser clients don't need to interpret HTML or JavaScript. The JSON data can be recognized by the outermost <code>({</code> and <code>})</code>, where the inner braces are part of the JSON value. For example, the regular expression <code>\((\{.*\})\)</code> captures the entire JSON value in its first capturing group.<br />
<br />
=== Documentation conventions ===<br />
<br />
The rest of this document describes all available requests for each module. A module usually supports several different requests, which are differentiated by the used HTTP method, URI path and supplied URI parameters. The description of each method generally contains the following elements:<br />
* the HTTP method followed by the request URI, inclusing the URI parameter action, which is used to differentiate methods,<br />
* a list of URI parameters which can or must be supplied by the client,<br />
* for PUT requests, content of the request body,<br />
* "Response with timestamp:"if the timestamp field is required in the response body or simply "Response:" if not,<br />
* content of the response payload, unless it is supposed to be empty.<br />
<br />
=== Common object data ===<br />
<br />
This table contains common fields which apply for any module's data type and is referenced throughout this document whenever a module's data type is described.<br />
<br />
{| id="CommonObjectData" cellspacing="0" border="1"<br />
|+ align="bottom" | Common object data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 1 || id || String || Object ID<br />
|-<br />
| 2 || created_by || String || User ID of the user who created this object.<br />
|-<br />
| 3 || modified_by || String || User ID of the user who last modified this object.<br />
|-<br />
| 4 || creation_date || Time || Date and time of creation.<br />
|-<br />
| 5 || last_modified || Time || Date and time of the last modification.<br />
|-<br />
| 20 || folder_id || String || Object ID of the parent folder.<br />
|-<br />
| 100 || categories || String || String containing comma separated the categories. Order is preserved. Changing the order counts as modification of the object. Not present in folder objects.<br />
|-<br />
| 101 || private_flag || Boolean || Overrides folder permissions in shared private folders: When true, this object is not visible to anyone except the owner. Not present in folder objects.<br />
|-<br />
| 102 || color_label || Number || Color number used by Outlook to label the object. The assignment of colors to numbers is arbitrary and specified by the client. The numbers are integer numbers between 1 and 10 (inclusive). Not present in folder objects.<br />
|-<br />
| 103 || number_of_links || Number || Number of links. '''deprecated'''<br />
|-<br />
| 104 || number_of_attachments || Number || Number of attachments <br />
|-<br />
| 105 || lastModifiedOfNewestAttachmentUTC || Time || Date and time of the newest attachment written with UTC time zone.<br />
|}<br />
<br />
== Module "login" ==<br />
<br />
The login module is used to obtain a session from the user's login credentials. To understand the details of the different login methods, see the article titled "[[Login variations]]".<br />
<br />
=== Login ===<br />
<br />
POST <code>/ajax/login?action=login</code><br />
<br />
Parameters:<br />
* <code>name</code> – The login name.<br />
* <code>password</code> – The password.<br />
* <code>authId</code> (optional) – Identifier for tracing every single login request passed between different systems in a cluster. The value should be some token that is unique for every login request. This parameter must be given as URL parameter and not inside the body of the POST request.<br />
* <code>client</code> (optional) – Identifier of the client using the HTTP/JSON interface. This is for statistic evaluations what clients are used with Open-Xchange.<br />
* <code>version</code> (optional) – Used version of the HTTP/JSON interface client.<br />
* <code>clientIP</code> (optional) – IP address of the client host for that the session is created. If this parameter is not specified the IP address of the HTTP client doing this request is used.<br />
* <code>clientUserAgent</code> (optional) – Value of the User-Agent header of the client host for that the session is created. If this parameter is not specified the User-Agent of the current HTTP client doing this request is used.<br />
<br />
Response: A JSON object containing the session ID used for all subsequent requests. Additionally a random token is contained to be used for the Easy Login method.<br />
<br />
=== Form Login (since 6.20) ===<br />
<br />
POST <code>/ajax/login?action=formlogin</code><br />
<br />
This request implements a possible login to the web frontend by only using a simple HTML form. An example for such a form can be found in the backend's documentation folder (<code>/usr/share/doc/open-xchange</code>) under <code>examples/login.html</code>.<br />
<br />
Parameters:<br />
* <code>login</code> – The login name.<br />
* <code>password</code> – The password.<br />
* <code>authId</code> – Identifier for tracing every single login request passed between different systems in a cluster. The value should be some token that is unique for every login request. This parameter must be given as URL parameter and not inside the body of the POST request.<br />
* <code>client</code> – Identifier of the client using the HTTP/JSON interface. This is for statistic evaluations what clients are used with Open-Xchange. If the autologin request should work the client must be the same as the client sent by the UI in the normal login request.<br />
* <code>version</code> – Used version of the HTTP/JSON interface client.<br />
* <code>autologin</code> – True or false. True tells the UI to issue a store request for the session cookie. This store request is necessary if you want the autologin request not to fail.<br />
* <code>uiWebPath</code> (optional) – Defines another path on the web server where the UI is located. If this parameter is not defined the configured default of the backend is used.<br />
* <code>clientIP</code> (optional) – IP address of the client host for that the session is created. If this parameter is not specified the IP address of the HTTP client doing this request is used.<br />
* <code>clientUserAgent</code> (optional) – Value of the User-Agent header of the client host for that the session is created. If this parameter is not specified the User-Agent of the current HTTP client doing this request is used.<br />
<br />
Response: A redirect to the web UI. The URL of the web UI is either taken from the given parameter or from the configured default of the backend.<br />
<br />
For a complete description of the FormLogin-Process please see [[FormLogin|this documentation]]<br />
<br />
=== Token Login (since 7.0.1) ===<br />
<br />
POST <code>/ajax/login?action=tokenLogin</code><br />
<br />
This request allows every possible client to create a very short living session. This session can then be transferred to any other client preferably a browser entering then the normal web interface. Then the sessions life time will be extended equally to every other session.<br />
<br />
Compared to the login mechanism using the random token, this request is more secure because two tokens are used. One of these tokens is only known to the client and one is generated by the server. Only the combination of both tokens allows to use the session. The combination of both tokens must be done by the client creating the session.<br />
<br />
Parameters:<br />
* <code>login</code> – The login information.<br />
* <code>password</code> – The password.<br />
* <code>clientToken</code> – Client side identifier for accessing the session later. The value should be some token that is unique for every login request.<br />
* <code>authId</code> – Identifier for tracing every single login request passed between different systems in a cluster. The value should be some token that is unique for every login request. This parameter must be given as URL parameter and not inside the body of the POST request.<br />
* <code>client</code> – Identifier of the client using the HTTP/JSON interface. This is for statistic evaluations what clients are used with Open-Xchange. If the autologin request should work the client should be the same as the client sent by the UI in the normal login request. For security considerations it can become necessary to define here the correct client that will use the session.<br />
* <code>version</code> – Version of the HTTP/JSON interface client. Only for statistic evaluations.<br />
* <code>autologin</code> – True or false. True tells the UI to issue a store request for the session cookie. This store request is necessary if you want the autologin request not to fail. This must be enabled on the server and a client can test with the autologin request if it is enabled or not.<br />
* <code>uiWebPath</code> (optional) – Defines another path on the web server where the UI is located. If this parameter is not defined the configured default of the backend is used.<br />
* <code>clientIP</code> (optional) – IP address of the client host for that the session is created. If this parameter is not specified the IP address of the HTTP client doing this request is used. Currently the IP address may change when using the session with both tokens. This can be disabled in future releases for security considerations.<br />
* <code>clientUserAgent</code> (optional) – Value of the User-Agent header of the client host for that the session is created. If this parameter is not specified the User-Agent of the current HTTP client doing this request is used. Currently the User-Agent may change when using the session. This can be disabled in future releases for security considerations.<br />
<br />
<br />
Response: A redirect to the web UI. The URL of the web UI is either taken from the given parameter or from the configured default of the backend. This redirect will only contain the server side token. The client side token sent in the request must be appended by the client creating the session. The final URL must have the form <code style="white-space: nowrap"><var>redirect_URL</var>&amp;clientToken=<var>token</var></code>. Both tokens are necessary to use the session and both tokens must match. Otherwise the session is terminated.<br />
<br />
=== Tokens (since 7.0.1) ===<br />
<br />
POST <code>/ajax/login?action=tokens</code><br />
<br />
This request allows clients to access a session created with the [[#Token_Login_.28since_7.0.1.29 | tokenLogin]] request. When accessing the session its life time is extended equally to every other session.<br />
<br />
Parameters:<br />
* <code>serverToken</code> – Server side identifier for accessing the session. This identifier was created by the server and is contained in the tokenLogin response.<br />
* <code>clientToken</code> – Client side identifier for accessing the session. This identifier was created by the client and passed within the POST data of the tokenLogin request.<br />
* <code>client</code> – Identifier of the client using the HTTP/JSON interface. Currently this request allows to change the client identifier for the session. This eases creating the session because the identifier of the client using the session must not be known. For security considerations it can become necessary to drop this parameter.<br />
<br />
<br />
Response: A JSON object conform to the normal [[#ResponseBody | response body]] contrary to the JSON object of the normal login request. This JSON object contains the session identifier, the login, the identifier and the locale of the user.<br />
<br />
=== Logout ===<br />
<br />
GET <code>/ajax/login?action=logout</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
=== Refresh secret cookie (since 6.18.2) ===<br />
<br />
GET <code>/ajax/login?action=refreshSecret</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
=== Refresh auto-login cookie ===<br />
<br />
GET <code>/ajax/login?action=store</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
=== Redirect ===<br />
<br />
GET <code>/ajax/login;jsessionid=1157370816112.OX1?action=redirect</code><br />
<br />
'''SECURITY WARNING!''' Utilizing this request is '''INSECURE'''! This request allows to access a session with a single one time token. This one time token may be delivered to the wrong client if the AJP protocol has an error or Apache or the load balancer make a mistake. This will cause a wrong user to be in a wrong session. '''IMMEDIATELY''' consider not to use this request anymore. You have been warned. Use instead the FormLogin that does not need to use the redirect request.<br />
<br />
Parameters:<br />
* <code>random</code> – A session random token to jump into the session. This random token is part of the login response. Only a very short configurable time after the login it is allowed to jump into the session with the random token.<br />
* <code>client</code> (optional) – The client can be defined here newly if it is not correct on the login request itself.<br />
* <code>store</code> (optional) – Tells the UI to do a store request after login to be able to use autologin request.<br />
* <code>uiWebPath</code> (optional) – The optional path on the webserver to the UI. If this parameter is not given the configured uiWebPath is used.<br />
<br />
=== Change IP ===<br />
<br />
The following request is especially for integration with systems located in the providers infrastructure. If those systems create a session with the following request the client host IP address in the session can be changed. The IP check for following requests will be done using this newly set client host IP address.<br />
<br />
POST <code>/ajax/login?action=changeip</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>clientIP</code> – New IP address of the client host for the current session.<br />
<br />
Response: A JSON object containing the string "1" as data attribute.<br />
<br />
=== Redeem Token (since 7.4.0)===<br />
<br />
POST <code>/ajax/login?action=redeemToken</code><br />
<br />
Parameters:<br />
* <code>token</code> – The token created with [[#Get_a_login_token | acquireToken]].<br />
* <code>authId</code> – Identifier for tracing every single login request passed between different systems in a cluster. The value should be some token that is unique for every login request. This parameter must be given as URL parameter and not inside the body of the POST request. <br />
* <code>client</code> – Identifier of the client using the HTTP/JSON interface. The client must identifier must be the same for each request after creating the login session. <br />
* <code>secret</code> – The value of the secret string for token logins. This is configured through the tokenlogin-secrets configuration file.<br />
<br />
Response: A JSON object containing the session ID used for all subsequent requests. Additionally a random token is contained to be used for the Easy Login method. If configured within tokenlogin-secrets configuration file even the user password will be returned.<br />
<br />
== Module "config" ==<br />
<br />
The config module is used to retrieve and set user-specific configuration. The configuration is stored in a tree. Each node of the tree has a name and a value. The values of leaf nodes are strings which store the actual configuration data. The values of inner nodes are defined recursively as objects with one field for each child node. The name and the value of each field is the name and the value of the corresponding child node, respectively.<br />
<br />
The namespace looks like the following:<br />
<br />
* <code>/ajax/config/</code><br />
** <code>gui</code> – A string containing GUI-specific settings (currently, it is a huge [[#Low_level_protocol | JSON]] object).<br />
** <code>fastgui</code> - A string containing GUI-specific settings. This is a JSON object that must be kept small for performance.<br />
** <code>context_id</code> - the unique identifier of the context (read-only, added 2008-01-28).<br />
** <code>cookielifetime</code> - the cookie life time in seconds or <code>-1</code> for session cookie (read-only, added 2010-11-16).<br />
** <code>identifier</code> – the unique identifier of the user (read-only).<br />
** <code>contact_id</code> – the unique identifier of the contact data of the user (read-only).<br />
** <code>language</code> – the configured language of the user.<br />
** <code>timezone</code> – the configured timezone of the user.<br />
** <code>availableTimeZones</code> – a JSON object containing all available time zones. The key is the time zone identifier and the value contains its name in users language. (read-only, added 2010-07-08/v6.18).<br />
** <code>calendarnotification</code> - send a mail notification for appointments (deprecated since 2008-12-11)<br />
** <code>tasknotification</code> - send a mail notification for tasks (deprecated since 2008-12-11)<br />
** <code>reloadTimes</code> - Selectable times for GUI reload<br />
** <code>serverVersion</code> - Version string of the server.<br />
** <code>currentTime</code> - User timezone specific long of the current server time.<br />
** <code>maxUploadIdleTimeout</code> - Timeout after that idle uploads are deleted.<br />
** <code>folder/</code> – the standard folder of the user<br />
*** <code>tasks</code> – the standard task folder (read-only)<br />
*** <code>calendar</code> – the standard calendar folder (read-only)<br />
*** <code>contacts</code> – the standard contacts folder (read-only)<br />
*** <code>infostore</code> – the private infostore folder (read-only, since v6.20.1)<br />
*** <code>eas</code> – whether EAS folder selection is enabled (read-only)<br />
** <code>mail/</code> – settings for the email module (deprecated 2008-04-29)<br />
*** <code>addresses</code> – all email addresses of the user including the primary address (read-only, deprecated 2008-04-29)<br />
*** <code>defaultaddress</code> – primary email address of the user (read-only, deprecated 2008-04-29)<br />
*** <code>sendaddress</code> – one email address out of the addresses list that are email sent with. (deprecated 2008-04-29)<br />
*** <code>folder/</code> – the standard email folders (read-only, deprecated 2008-04-29)<br />
**** <code>inbox</code> – identifier of the folder that gets all incoming mails (read-only, deprecated 2008-04-29)<br />
**** <code>drafts</code> – identifier of the folder with the mail drafts (read-only, deprecated 2008-04-29)<br />
**** <code>trash</code> – identifier of the folder with the deleted mails (read-only, deprecated 2008-04-29)<br />
**** <code>spam</code> – identifier of the folder with the spam mails (read-only, deprecated 2008-04-29)<br />
**** <code>sent</code> – identifier of the folder with the sent mails (read-only, deprecated 2008-04-29)<br />
*** <code>htmlinline</code> – activate inlining of HTML attachments. (deprecated 2008-04-29)<br />
*** <code>colorquote</code> – color quoted lines. (deprecated 2008-04-29)<br />
*** <code>emoticons</code> – display emoticons as graphics. (deprecated 2008-04-29)<br />
*** <code>harddelete</code> – delete emails at once. (deprecated 2008-04-29)<br />
*** <code>inlineforward</code> – forward messages as inline or attachment. (deprecated 2008-04-29)<br />
*** <code>vcard</code> – attach vcard when sending mails. (deprecated 2008-04-29)<br />
*** <code>notifyonreadack</code> – notify on read acknowledgement. (deprecated 2008-04-29)<br />
*** <code>msgpreview</code> – show a message preview. (deprecated 2008-04-29)<br />
*** <code>ignorereplytext</code> (deprecated 2008-04-29)<br />
*** <code>nocopytosent</code> – don't put a copy to the sent folder when sending mails. (deprecated 2008-04-29)<br />
*** <code>spambutton</code> - Spam Button should be displayed in GUI or not. (deprecated 2008-04-29)<br />
** <code>participants</code><br />
*** <code>autoSearch</code> - If a search for all users, groups and resources when participant selection dialog is opened. (read-only, added 2008-10-09/SP5)<br />
*** <code>maximumNumberParticipants</code> – Defines the maximum number of participants for appointments and tasks. (read-only, added 2008-10-20/SP5)<br />
*** <code>showWithoutEmail</code> - If external participants without email should be shown.<br />
*** <code>showDialog</code> – Enables participant selection dialog for appointments and tasks. (read-only, added 2008-04-30/SP4)<br />
** <code>availableModules</code> – Contains a JSON array listing all enabled modules for a user. GUI loads Plugins through this list. To get your plugin listed here, create a subtree below <code>modules/</code> without a <code>module</code> subelement or with a subelement containing <code>true</code> (read-only, added 2008-02-25)<br />
** <code>minimumSearchCharacters</code> – Minimum number of characters a search pattern must have to prevent large responses and slow queries. (read-only, added 2008-10-20/SP5)<br />
** <code>modules</code><br />
*** <code>portal</code><br />
**** <code>gui</code> GUI settings for portal module<br />
**** <code>module</code><br />
*** <code>mail</code><br />
**** <code>addresses</code> – all email addresses of the user including the primary address (read-only, added 2008-02-25)<br />
**** <code>appendmailtext</code> – (added 2008-02-25)<br />
**** <code>allowhtmlimages</code> – Alters default setting whether external images contained in HTML content are allowed or not (added 2008-05-27)<br />
**** <code>colorquoted</code> – color quoted lines (added 2008-02-25)<br />
**** <code>contactCollectFolder</code> – contact folder id to save mail addresses from sent mails (added 2008-10-16)<br />
**** <code>contactCollectEnabled</code> – switch contact collection on/off (added 2008-10-16)<br />
**** <code>contactCollectOnMailAccess</code> – enables/disables contact collection for incoming mails. Default is true. (added 2009-09-24)<br />
**** <code>contactCollectOnMailTransport</code> – enables/disables contact collection for outgoing mails. Default is true. (added 2009-09-24)<br />
**** <code>defaultaddress</code> – primary email address of the user (read-only, added 2008-02-25)<br />
**** <code>deletemail</code> – delete emails or move to trash (added 2008-02-25)<br />
**** <code>emoticons</code> – display emoticons as graphics (added 2008-02-25)<br />
**** <code>defaultFolder</code><br />
***** <code>drafts</code> – identifier of the folder with the mail drafts (read-only, added 2008-02-25)<br />
***** <code>inbox</code> – identifier of the folder that gets all incoming mails (read-only, added 2008-02-25)<br />
***** <code>sent</code> – identifier of the folder with the sent mails (read-only, added 2008-02-25)<br />
***** <code>spam</code> – identifier of the folder with the spam mails (read-only, added 2008-02-25)<br />
***** <code>trash</code> – identifier of the folder with the deleted mails (read-only, added 2008-02-25)<br />
**** <code>forwardmessage</code> – forward messages as inline or attachment (added 2008-02-25)<br />
**** <code>gui</code> GUI settings for mail module<br />
**** <code>inlineattachments</code> – activate inlining of HTML attachments (added 2008-02-25)<br />
**** <code>linewrap</code> – (added 2008-02-25)<br />
**** <code>module</code> – if mail module is enabled or not (added 2008-02-25)<br />
**** <code>phishingheaders</code> – header(s) identifying phishing headers (added 2008-05-27)<br />
**** <code>replyallcc</code> – put all recipients on reply all into CC (added 2008-12-16/SP5)<br />
**** <code>sendaddress</code> – one email address out of the addresses list that are email sent with (added 2008-02-25)<br />
**** <code>spambutton</code> – Spam Button should be displayed in GUI or not (added 2008-02-25)<br />
**** <code>vcard</code> – attach vcard when sending mails (added 2008-02-25)<br />
*** <code>calendar</code><br />
**** <code>calendar_conflict</code><br />
**** <code>calendar_freebusy</code><br />
**** <code>calendar_teamview</code><br />
**** <code>gui</code> GUI settings for the calendar module<br />
**** <code>module</code><br />
**** <code>notifyNewModifiedDeleted</code> receive mail notification for new, modified or deleted appointments (added 2008-12-11/SP5)<br />
**** <code>notifyAcceptedDeclinedAsCreator</code> receive mail notification for accepted or declined appointments created by the user (added 2008-12-11/SP5)<br />
**** <code>notifyAcceptedDeclinedAsParticipant</code> receive mail notification for accepted or declined appointments that the user participates (added 2008-12-11/SP5)<br />
**** <code>defaultStatusPrivate</code> Default status for new appointments in private folders, where the user is participant. This does not affect appointments created by this user, which always have the status "accepted". The status are described in [[#UserParticipantObject | User participant object]]. Default is 0:none (added 2009-07-20/6.12)<br />
**** <code>defaultStatusPublic</code> Default status for new appointments in public folders, where the user is participant. This does not affect appointments created by this user, which always have the status "accepted". The status are described in [[#UserParticipantObject | User participant object]]. Default is 0:none (added 2009-07-20/6.12)<br />
*** <code>contacts</code><br />
**** <code>gui</code> GUI settings for the contacts module<br />
**** <code>mailAddressAutoSearch</code> – Define if a search is triggered when the recipient selection dialog is opened or the folder is changed. (read-only, added 2008-10-20/SP5)<br />
**** <code>module</code> True if the contact module is enabled for the current user, false otherwise.<br />
**** <code>singleFolderSearch</code> – True if the current user is allowed to search for contacts only in a single folder. False if contact searches across all folders are allowed. (read-only, added 2009-02-04/SP5 U1)<br />
**** <code>characterSearch</code> – True if the side bar for searching for contacts by a start letter should be displayed. False if the side bar should be hidden. (read-only, added 2009-05-29/6.10)<br />
**** <code>allFoldersForAutoComplete</code> – true if an auto complete search may omit the folder identifier array and search for contacts in all readable folders. This is configured through the contact.properties configuration file. (read-only, added 2010-07-22/v6.18.0)<br />
*** <code>tasks</code><br />
**** <code>gui</code> GUI settings for the tasks module<br />
**** <code>module</code><br />
**** <code>delegate_tasks</code><br />
**** <code>notifyNewModifiedDeleted</code> receive mail notification for new, modified or deleted tasks (added 2008-12-11/SP5)<br />
**** <code>notifyAcceptedDeclinedAsCreator</code> receive mail notification for accepted or declined tasks created by the user (added 2008-12-11/SP5)<br />
**** <code>notifyAcceptedDeclinedAsParticipant</code> receive mail notification for accepted or declined taks that the user participates (added 2008-12-11/SP5)<br />
*** <code>infostore</code><br />
**** <code>gui</code> GUI settings for the infostore module<br />
**** <code>module</code><br />
*** <code>interfaces</code><br />
**** <code>ical</code><br />
**** <code>vcard</code><br />
**** <code>syncml</code><br />
*** <code>folder</code><br />
**** <code>gui</code> UI settings for the folder tree<br />
**** <code>public_folders</code><br />
**** <code>read_create_shared_folders</code><br />
**** <code>tree</code> – Selected folder tree, the user wants to use. Currents trees are 0 for the known OX folder tree and 1 for the new virtual folder tree. (added 2010-04-09/6.18)<br />
*** <code>com.openexchange.extras</code><br />
**** <code>module</code> – Extras link in the configuration (read only, added 2008-04-29)<br />
*** <code>com.openexchange.user.passwordchange</code><br />
**** <code>module</code> – Will load Plug-In which allows to change the Password within the users configuration (read only, added 2008-07-09)<br />
*** <code>com.openexchange.user.personaldata</code><br />
**** <code>module</code> – Will load Plug-In which allows to edit personal contact information within the users configuration (read only, added 2008-07-09)<br />
*** <code>com.openexchange.group</code><br />
**** <code>enabled</code> – Specifies whether the user is allowed to edit groups and loads the corresponding Plug-In. (read only, added 2008-08-08)<br />
*** <code>com.openexchange.resource</code><br />
**** <code>enabled</code> – Specifies whether the user is allowed to edit resources and loads the corresponding Plug-In. (read only, added 2008-08-08)<br />
*** <code>com.openexchange.publish</code><br />
**** <code>enabled</code> – Specifies whether the user is allowed to publish items. (read only, added 2009-05-27)<br />
*** <code>com.openexchange.subscribe</code><br />
**** <code>enabled</code> – Specifies whether the user is allowed to subscribe sources. (read only, added 2009-05-27)<br />
*** <code>olox20</code><br />
**** <code>active</code> – Tells the UI if the user is allowed to use the OXtender for Microsoft Outlook 2. (read only, added 2011-03-15/6.20)<br />
**** <code>module</code> – Is set to false to prevent the UI from trying to load a plugin. (read only, added 2011-03-15/6.20)<br />
***<code>com.openexchange.oxupdater</code><br />
****<code>module</code> – Is true if the OXUpdater package is installed and started. (read only, added 2011-06-01/6.20)<br />
****<code>active</code> – Is true if the user is allowed to download the OXUpdater. Otherwise it's false. (read only, added 2011-06-01/6.20)<br />
***<code>com.openexchange.passwordchange</code><br />
**** <code>showStrength</code> – Show a widget, which displays the current passwort Strength while entering. (default: false)<br />
**** <code>minLength</code> – The minimum length of an entered password. (default: 4)<br />
**** <code>maxLength</code> – The maximum length of an entered password. 0 for unlimited. (default: 0)<br />
**** <code>regexp</code> – Defines the class of allowed special characters as Regular Expression. (default: [^a-z0-9])<br />
**** <code>special</code> – Shows an example of allowed special characters to the user. Should be a subset of "regexp" in a human readable format. (default: $, _, or %) <br />
<br />
=== Get configuration data ===<br />
<br />
GET <code>/ajax/config/path</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: Value of the node specified by path.<br />
<br />
=== Set configuration data ===<br />
<br />
PUT <code>/ajax/config/path</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: The new value of the node specified by path.<br />
<br />
== Module "folders" ==<br />
<br />
The folders module is used to access the OX folder structure.<br />
<br />
=== Special System Folders ===<br />
<br />
Folders with some kind of special.<br />
<br />
{| cellspacing="0" border="1"<br />
! ID !! Type !! Description<br />
|-<br />
| 6 || contacts || System Users<br />
|}<br />
<br />
=== Get root folders ===<br />
<br />
GET <code>/ajax/folders?action=root</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Response: An array with data for all folders at the root level of the folder structure. Each array element describes one folder and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="CommonFolderData" cellspacing="0" border="1"<br />
|+ align="bottom" | Common folder data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 1 || id || String || Object ID<br />
|-<br />
| 2 || created_by || String || User ID of the user who created this object.<br />
|-<br />
| 3 || modified_by || String || User ID of the user who last modified this object.<br />
|-<br />
| 4 || creation_date || Time || Date and time of creation.<br />
|-<br />
| 5 || last_modified || Time || Date and time of the last modification.<br />
|-<br />
| 6 || last_modified_utc || Timestamp || Timestamp of the last modification. Note that the type is Timestamp, not Time. See [[#Date and time]] for details. (added 2008-10-17, with SP5, temporary workaround)<br />
|-<br />
| 20 || folder_id || String || Object ID of the parent folder.<br />
|}<br />
<br />
{| id="DetailedFolderData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed folder data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 300 || title || String || Name of this folder.<br />
|-<br />
| 301 || module || String || Name of the module which implements this folder; e.g. "tasks", "calendar", "contacts", "infostore", or "mail"<br />
|-<br />
| 302 || type || Number || Type of folder:<br />
{| cellspacing="0" border="1"<br />
| 1 || private<br />
|-<br />
| 2 || public<br />
|-<br />
| 3 || shared<br />
|-<br />
| 5 || system folder<br />
|}<br />
|-<br />
| 304 || subfolders || Boolean || true if this folder has subfolders.<br />
|-<br />
| 305 || own_rights || Number or String || Permissions which apply to the current user, as described either in [[#PermissionFlags | Permission flags]] or in RFC 2086.<br />
|-<br />
| 306 || permissions || Array || Each element is an object described in [[#PermissionObject | Permission object]].<br />
|-<br />
| 307 || summary || String || Information about contained objects.<br />
|-<br />
| 308 || standard_folder || Boolean || Indicates whether or not folder is marked as a default folder (only OX folder)<br />
|-<br />
| 309 || total || Number || The number of objects in this Folder.<br />
|-<br />
| 310 || new || Number || The number of new objects in this Folder.<br />
|-<br />
| 311 || unread || Number || The number of unread objects in this Folder.<br />
|-<br />
| 312 || deleted || Number || The number of deleted objects in this Folder.<br />
|-<br />
| 313 || capabilities || Number || Bit mask containing information about mail folder capabilites, as described in [[#Capabilities | capabilities]].<br />
|-<br />
| 314 || subscribed || Boolean || Indicates whether this folder should appear in folder tree or not.<br />
|-<br />
| 315 || subscr_subflds || Boolean || Indicates whether subfolders should appear in folder tree or not.<br />
|-<br />
| 316 || standard_folder_type || Number || Indicates the default folder type. Zero for non-default folder. See [[#DefaultTypes | Standard folder types]]<br />
|-<br />
| 317 || supported_capabilities || Array || Each element is a String identifying a supported folder capability as described in [[#SupportedCapabilities | supported capabilities]]. Only applicable for non-mail folders. Read Only, Since 7.4.0.<br />
|-<br />
| 3010 || com.openexchange.publish.publicationFlag || Boolean || Indicates whether this folder is published. Read Only, provided by the com.openexchange.publish plugin, since 6.14.<br />
|-<br />
| 3020 || com.openexchange.subscribe.subscriptionFlag || Boolean || Indicates whether this folder has subscriptions storing their content in this folder. Read Only, provided by the com.openexchange.subscribe plugin, since 6.14.<br />
|-<br />
| 3030 || com.openexchange.folderstorage.displayName || String || Provides the display of the folder's owner. Read Only, Since 6.20.<br />
|}<br />
<br />
<br />
<br />
<br />
{| id="PermissionFlags" cellspacing="0" border="1"<br />
|+ align="bottom" | Permission flags<br />
! Bits !! Value<br />
|-<br />
| 0-6 || Folder permissions:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || See the folder.<br />
|-<br />
| 2 || Create objects in the folder. '''Note''': '''Does not apply to folders of module ''system'''''.<br />
|-<br />
| 4 || Create subfolders.<br />
|-<br />
| 64 || All permissions. This is currently the same as "Create subfolders" but in the future additional permissions may be added that will be given to the user when using this value.<br />
|}<br />
The values are scalars and not bit sets. Any other than the described values should not be used. If they are used expect an exception from the backend. Every value automatically contains the access rights covered by lower values.<br>'''NOTE''': ''Create objects in the folder'' is not covered by ''Create subfolders'' if folder's module is ''system''.<br />
|-<br />
| 7-13 || Read permissions for objects in the folder:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || Read only own objects.<br />
|-<br />
| 2 || Read all objects.<br />
|-<br />
| 64 || All permissions. This is currently the same as "Read all objects" but in the future additional permissions may be added that will be given to the user when using this value.<br />
|}<br />
The values are scalars and not bit sets. Any other than the described values should not be used. If they are used expect an exception from the backend. Every value automatically contains the access rights covered by lower values.<br />
|-<br />
| 14-20 || Write permissions for objects in the folder:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || Modify only own objects.<br />
|-<br />
| 2 || Modify all objects.<br />
|-<br />
| 64 || All permissions. This is currently the same as "Modify all objects" but in the future additional permissions may be added that will be given to the user when using this value.<br />
|}<br />
The values are scalars and not bit sets. Any other than the described values should not be used. If they are used expect an exception from the backend. Every value automatically contains the access rights covered by lower values.<br />
|-<br />
| 21-27 || Delete permissions for objects in the folder:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || Delete only own objects.<br />
|-<br />
| 2 || Delete all objects.<br />
|-<br />
| 64 || All permissions. This is currently the same as "Delete all objects" but in the future additional permissions may be added that will be given to the user when using this value.<br />
|}<br />
The values are scalars and not bit sets. Any other than the described values should not be used. If they are used expect an exception from the backend. Every value automatically contains the access rights covered by lower values.<br />
|-<br />
| 28 || Admin flag:<br />
{| cellspacing="0" border="1"<br />
| 0 || No permissions.<br />
|-<br />
| 1 || Every operation modifying the folder in some way requires this permission. This are e.g. changing the folder name, modifying the permissions, deleting or moving the folder.<br />
|}<br />
|}<br />
<br />
{| id="PermissionObject" cellspacing="0" border="1"<br />
|+ align="bottom" | Permission object<br />
! Name !! Type !! Value<br />
|-<br />
| bits || Number || For non-mail folders, a number as described in [[#PermissionFlags | Permission flags]].<br />
|-<br />
| rights || String || For mail folders, the rights string as defined in RFC 2086.<br />
|-<br />
| entity || Number || User ID of the user or group to which this permission applies.<br />
|-<br />
| group || Boolean || true if entity refers to a group, false if it refers to a user.<br />
|}<br />
<br />
{| id="Capabilities" cellspacing="0" border="1"<br />
|+ align="bottom" | Capabilities<br />
! Bit !! Description<br />
|-<br />
| 0 || Mailing system supports permissions.<br />
|-<br />
| 1 || Mailing system supports ordering mails by their thread reference.<br />
|-<br />
| 2 || Mailing system supports quota restrictions.<br />
|-<br />
| 3 || Mailing system supports sorting.<br />
|-<br />
| 4 || Mailing system supports folder subscription.<br />
|}<br />
<br />
{| id="DefaultTypes" cellspacing="0" border="1"<br />
|+ align="bottom" | Standard Folder Types<br />
! Bit !! Description<br />
|-<br />
| 0 || No default folder.<br />
|-<br />
| 1 || Task.<br />
|-<br />
| 2 || Calendar.<br />
|-<br />
| 3 || Contact.<br />
|-<br />
| 7 || Inbox.<br />
|-<br />
| 8 || Infostore.<br />
|-<br />
| 9 || Drafts.<br />
|-<br />
| 10 || Sent.<br />
|-<br />
| 11 || Spam.<br />
|-<br />
| 12 || Trash.<br />
|}<br />
<br />
{| id="SupportedCapabilities" cellspacing="0" border="1"<br />
|+ align="bottom" | Supported Capabilities<br />
! Name !! Description<br />
|-<br />
| permissions || Folder storage supports permissions.<br />
|-<br />
| publication || Folder storage supports folder publication.<br />
|-<br />
| quota || Folder storage supports quota restrictions.<br />
|-<br />
| sort || Folder storage supports sorting.<br />
|-<br />
| subscription || Folder storage supports folder subscription.<br />
|}<br />
<br />
=== Get subfolders ===<br />
<br />
GET <code>/ajax/folders?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>parent</code> – Object ID of a folder, which is the parent folder of the requested folders.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
* <code>all</code> – Set to <code>1</code> to list even not subscribed folders.<br />
* <code>tree</code> – The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
* <code>errorOnDuplicateName</code> – An optional flag to enable or disable (default) check for duplicate folder names within returned folder response (since v6.20.1). If a duplicate folder name is detected, an appropriate error is returned as [[#ResponseBody | response]].<br />
<br />
Response with timestamp: An array with data for all folders, which have the folder with the requested object ID as parent. Each array element describes one folder and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get path ===<br />
<br />
GET <code>/ajax/folders?action=path</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of a folder.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Response with timestamp: An array with data for all parent nodes until root folder. Each array element describes one folder and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get updated folders ===<br />
<br />
GET <code>/ajax/folders?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>parent</code> – Object ID of a folder, which is the parent folder of the requested folders.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested folders.<br />
* <code>ignore</code> (optional) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Response with timestamp: An array with data for new, modified and deleted folders. New and modified folders are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted folders (should the <code>ignore</code> parameter be ever implemented) would be identified by their object IDs as plain strings, without being part of a nested array.<br />
<br />
=== Get a folder ===<br />
<br />
GET <code>/ajax/folders?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested folder.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Response with timestamp: An object containing all data of the requested folder. The fields of the object are listed in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]]. The field id is not present. Since OX access controls are folder-based, the folder object also defines the permissions for the objects it contains. The permissions for a given user or group are defined by the object described in [[#PermissionObject | Permission object]]. The format of the actual permissions depends on the type of the folder. The permissions of mail folders are transmitted as a rights string as defined in section 3 of RFC 2086. Permissions of all other folders are transmitted as a single nonnegative integer number. The permissions for any given action on the folder or on contained objects is defined by a group of bits in the binary representation of this number. Each group of bits is interpreted as a separate number. Zero always means "no permissions". Any other values add new permissions and always include the permissions of all lower values. The individual values are described in [[#PermissionFlags | Permission flags]].<br />
<br />
=== Update a folder ===<br />
<br />
PUT <code>/ajax/folders?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated folder.<br />
* <code>timestamp</code> – Timestamp of the updated folder. If the folder was modified after the specified timestamp, then the update must fail.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Request body: Folder object as described in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]]. Only modified fields are present.<br />
<br />
=== Create a folder ===<br />
<br />
PUT <code>/ajax/folders?action=new</code><br />
<br />
Parameters:<br />
* <code>folder_id</code> – The parent folder of the newly created folder<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Request body: Folder object as described in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]]. The field id should not be present.<br />
<br />
Provided that permission is granted to create a folder, its module is bound to the limitation, that the new folder's module must be equal to parent folder's module except that:<br />
* Parent folder is one of the system folders <code>private</code>, <code>public</code>, or <code>shared</code>. Below these folders task, calendar, and contact modules are permitted.<br />
* Parent folder's module is one of task, calendar, or contact. Below this kind of folders task, calendar, and contact modules are permitted.<br />
<br />
Response: Object ID of the newly created folder.<br />
<br />
=== Delete folders ===<br />
<br />
PUT <code>/ajax/folders?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted folders.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered. <br />
<br />
Request body: An array with object IDs of the folders that shall be deleted.<br />
<br />
Response: An array with object IDs of folders that were '''NOT''' deleted. There may be a lot of different causes for a not deleted folder: A folder has been modified in the mean time, the user does not have the permission to delete it or those permissions have just been removed, the folder does not exist, etc.<br />
<br />
=== Clearing a folder's content ===<br />
PUT <code>/ajax/folders?action=clear</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>tree</code> – (Preliminary) The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>allowed_modules</code> – (Preliminary) An array of modules (either numbers or strings; e.g. "tasks,calendar,contacts,mail") supported by requesting client. If missing, all available modules are considered.<br />
<br />
Request body: A JSON array containing the folder ID(s) whose content should be cleared. '''NOTE:''' Although the requests offers to clear multiple folders at once it is recommended to clear only one folder per request since if any exception occurs<br />
(e.g. missing permissions) the complete request is going to be aborted.<br />
<br />
Response: A JSON array containing the IDs of folders that could not be cleared due to a concurrent modification. Meaning you receive an empty JSON array if everything worked well.<br />
<br />
=== Get all visible folder of a certain module (since v6.18.2) ===<br />
PUT <code>/ajax/folders?action=allVisible</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>tree</code> – The identifier of the folder tree. If missing '0' (primary folder tree) is assumed.<br />
* <code>content_type</code> – The desired content type (either numbers or strings; e.g. "tasks", "calendar", "contacts", "mail")<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for folders are defined in [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
<br />
Request body: None<br />
<br />
Response with timestamp: A JSON object containing three fields: "private", "public, and "shared". Each field is a JSON array with data for all folders. Each folder is itself described by an array.<br />
<br />
== Module "tasks" ==<br />
<br />
The tasks module is used to access task information.<br />
<br />
=== Get all tasks ===<br />
<br />
GET <code>/ajax/tasks?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for tasks are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response with timestamp: An array with task data. Each array element describes one task and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedTaskAndAppointmentData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed task and appointment data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 200 || title || String || Short description.<br />
|-<br />
| 201 || start_date || Date or Time || Inclusive start of the event as Date for tasks and whole day appointments and Time for normal appointments. For sequencies, this date must be part of the sequence, i. e. sequencies always start at this date.<br />
|-<br />
| 202 || end_date || Date or Time || Exclusive end of the event as Date for tasks and whole day appointments and as Time for normal appointments.<br />
|-<br />
| 203 || note || String || Long description.<br />
|-<br />
| 204 || alarm || Number or Time || Specifies when to notify the participants as the number of minutes before the start of the appointment (-1 for "no alarm"). For tasks, the Time value specifies the absolute time when the user should be notified.<br />
|-<br />
| 209 || recurrence_type || Number || Specifies the type of the recurrence for a task sequence:<br />
{| cellspacing="0" border="1"<br />
| 0 || none (single event)<br />
|-<br />
| 1 || daily<br />
|-<br />
| 2 || weekly<br />
|-<br />
| 3 || monthly<br />
|-<br />
| 4 || yearly<br />
|}<br />
|-<br />
| 212 || days || Number || Specifies which days of the week are part of a sequence. The value is a bitfield with bit 0 indicating sunday, bit 1 indicating monday and so on. May be present if recurrence_type > 1. If allowed but not present, the value defaults to 127 (all 7 days).<br />
|-<br />
| 213 || day_in_month || Number || Specifies which day of a month is part of the sequence. Counting starts with 1. If the field "days" is also present, only days selected by that field are counted. If the number is bigger than the number of available days, the last available day is selected. Present if and only if recurrence_type > 2.<br />
|-<br />
| 214 || month || Number || Month of the year in yearly sequencies. 0 represents January, 1 represents February and so on. Present if and only if recurrence_type = 4.<br />
|-<br />
| 215 || interval || Number || Specifies an integer multiplier to the interval specified by recurrence_type. Present if and only if recurrence_type > 0. Must be 1 if recurrence_type = 4.<br />
|-<br />
| 216 || until || Date || Inclusive end date of a sequence. May be present only if recurrence_type > 0. The sequence has no end date if recurrence_type > 0 and this field is not present. Note: since this is a Date, the entire day after the midnight specified by the value is included.<br />
|-<br />
| 217 || notification || Boolean || If true, all participants are notified of any changes to this object. This flag is valid for the current change only, i. e. it is not stored in the database and is never sent by the server to the client.<br />
|-<br />
| 220 || participants || Array || Each element identifies a participant, user, group or booked resource as described in [[#Participant | participant table]].<br />
|-<br />
| 221 || users || Array || Each element represents a participant as described in [[#UserParticipantObject | User participant object]]. User groups are resolved and are represented by their members. Any user can occur only once.<br />
|-<br />
| 222 || occurrences || Number || Specifies how often a recurrence should appear. May be present only if recurrence_type > 0.<br />
|-<br />
| 223 || uid || String || Can only be written when the object is created. Internal and external globally unique identifier of the appointment or task. Is used to recognize appointments within iCal files. If this attribute is not written it contains an automatic generated UUID.<br />
|-<br />
| 224 || organizer || String || Contains the email address of the appointment organizer which is not necessarily an internal user. Not implemented for tasks.<br />
|-<br />
| 225 || sequence || Number || iCal sequence number. Not implemented for tasks. Must be incremented on update. Will be incremented by the server, if not set.<br />
|-<br />
| 226 || confirmations || Array || Each element represents a confirming participant as described in [[#ConfirmingParticipant | confirming participant]]. This can be internal and external user. Not implemented for tasks.<br />
|-<br />
| 227 || organizerId || Number || Contains the userIId of the appointment organizer if it is an internal user. Not implemented for tasks. (Introduced with 6.20.1)<br />
|-<br />
| 228 || principal || String || Contains the email address of the appointment principal which is not necessarily an internal user. Not implemented for tasks. (Introduced with 6.20.1)<br />
|-<br />
| 229 || principalId || Number || Contains the userIId of the appointment principal if it is an internal user. Not implemented for tasks. (Introduced with 6.20.1)<br />
|}<br />
<br />
{| id="Participant" cellspacing="0" border="1"<br />
|+ align="bottom" | Participant identifier<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || User ID<br />
|-<br />
| type || Number || Type of participant:<br />
{|<br />
| 1 || user<br />
|-<br />
| 2 || user group<br />
|-<br />
| 3 || resource<br />
|-<br />
| 4 || resource group<br />
|-<br />
| 5 || external user<br />
|}<br />
|-<br />
| mail || String || mail address of an external participant<br />
|}<br />
<br />
{| id="UserParticipantObject" cellspacing="0" border="1"<br />
|+ align="bottom" | User participant object<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || User ID. Confirming for other users only works for appointments and not for tasks.<br />
|-<br />
| display_name || String || Displayable name of the participant.<br />
|-<br />
| confirmation || Number ||<br />
{| cellspacing="0" border="1"<br />
| 0 || none<br />
|-<br />
| 1 || accepted<br />
|-<br />
| 2 || declined<br />
|-<br />
| 3 || tentative<br />
|}<br />
|-<br />
| confirmmessage || String || Confirm Message of the participant<br />
|}<br />
<br />
{| id="ConfirmingParticipant" cellspacing="0" border="1"<br />
|+ align="bottom" | Confirming participant<br />
! Name !! Type !! Value<br />
|-<br />
| type || Number || Type of participant:<br />
{|<br />
| 1 || user<br />
|-<br />
| 5 || external user<br />
|}<br />
|-<br />
| mail || String || email address of external participant<br />
|-<br />
| display_name || String || display name of external participant<br />
|-<br />
| status || Number ||<br />
{|<br />
| 0 || none<br />
|-<br />
| 1 || accepted<br />
|-<br />
| 2 || declined<br />
|-<br />
| 3 || tentative<br />
|}<br />
|-<br />
| message || String || Confirm Message of the participant<br />
|}<br />
<br />
{| id="DetailedTaskData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed task data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 300 || status || Number || Status of the task:<br />
{| cellspacing="0" border="1"<br />
| 1 || not started<br />
|-<br />
| 2 || in progress<br />
|-<br />
| 3 || done<br />
|-<br />
| 4 || waiting<br />
|-<br />
| 5 || deferred<br />
|}<br />
|-<br />
| 301 || percent_completed || Number || How much of the task is completed. An integer number between 0 and 100.<br />
|-<br />
| 302 || actual_costs|| Number || A monetary attribute to store actual costs of a task. Allowed values must be in the range -9999999999.99 and 9999999999.99.<br />
|-<br />
| 303 || actual_duration<br />
|-<br />
| 304 || after_complete || Date || Deprecated. Only present in AJAX interface. Value will not be stored on OX server.<br />
|-<br />
| 305 || billing_information<br />
|-<br />
| 307 || target_costs|| Number || A monetary attribute to store target costs of a task. Allowed values must be in the range -9999999999.99 and 9999999999.99.<br />
|-<br />
| 308 || target_duration<br />
|-<br />
| 309 || priority || Number || 1 = LOW, 2 = MEDIUM, 3 = HIGH<br />
|-<br />
| 312 || currency<br />
|-<br />
| 313 || trip_meter<br />
|-<br />
| 314 || companies<br />
|-<br />
| 315 || date_completed<br />
|}<br />
<br />
=== Get a list of tasks ===<br />
<br />
PUT <code>/ajax/tasks?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for tasks are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]].<br />
<br />
Request body: An array of with object IDs of requested tasks.<br />
<br />
Response with timestamp: An array with task data. Each array element describes one task and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get updated tasks ===<br />
<br />
GET <code>/ajax/tasks?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for tasks are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested tasks.<br />
* <code>ignore</code> – Which kinds of updates should be ignored. Omit this parameter or set it to "deleted" to not have deleted tasks identifier in the response. Set this parameter to "false" and the response contains deleted tasks identifier.<br />
<br />
Response with timestamp: An array with new, modified and deleted tasks. New and modified tasks are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted tasks would be identified by their object IDs as plain strings, without being part of a nested array.<br />
<br />
=== Get a task ===<br />
<br />
GET <code>/ajax/tasks?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested task.<br />
* <code>folder</code> – Object ID of the task's folder.<br />
<br />
Response with timestamp: An object containing all data of the requested task. The fields of the object are listed in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]]. The field id is not included.<br />
<br />
=== Update a task ===<br />
<br />
PUT <code>/ajax/tasks?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Folder Identifier through that the task is accessed. This is necessary for checking the permissions.<br />
* <code>id</code> – Object ID of the updated task.<br />
* <code>timestamp</code> – Timestamp of the updated task. If the task was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: Task object as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]]. Only modified fields are present.<br />
<br />
=== Create a task ===<br />
<br />
PUT <code>/ajax/tasks?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Task object as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]]. The field id is not present.<br />
<br />
Response: A json objekt with attribute <code>id</code> of the newly created task.<br />
<br />
=== Delete task ===<br />
<br />
PUT <code>/ajax/tasks?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted tasks.<br />
<br />
Request body: An object in the field “id” and “folder”.<br />
<br />
Response: An array with object IDs of tasks which were modified after the specified timestamp and were therefore not deleted.<br />
<br />
=== Delete tasks (since v6.22) ===<br />
<br />
PUT <code>/ajax/tasks?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted tasks.<br />
<br />
Request body: An array of objects with the fields “id” and “folder”.<br />
<br />
Response: An array with object IDs of tasks which were modified after the specified timestamp and were therefore not deleted.<br />
<br />
=== Confirm task ===<br />
<br />
PUT <code>/ajax/tasks?action=confirm</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the to confirm task.<br />
* <code>folder</code> – ID of the folder through that the task is accessed.<br />
* <code>timestamp</code> – Timestamp of the last update of the to confirm task.<br />
<br />
Request body: An object with the fields "confirmation" and "confirmmessage" as described in [[#UserParticipantObject | User participant object]].<br />
<br />
Response: Nothing, except the standard response object with empty data, the timestamp of the confirmed and thereby updated task, and maybe errors.<br />
<br />
=== Search for tasks ===<br />
<br />
PUT <code>/ajax/tasks?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified , then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Request Body: A JSON object with attributes described in [[#SearchTasks | Search tasks]]<br />
<br />
{| id="SearchTasks" cellspacing="0" border="1"<br />
|+ align="bottom" | Search tasks<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find tasks. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|-<br />
| folder || Number || (optional) Defines the folder to search for tasks in. If this is omitted in all task folders will be searched.<br />
|-<br />
| start || Date or Time || (optional) Inclusive start date for a time range the tasks should end in. If start is omitted end is ignored.<br />
|-<br />
| end || Date or Time || (optional) Exclusive end date for a time range the tasks should end in. If this parameter is omitted the time range has an open end.<br />
|}<br />
<br />
Response with timestamp: An array with matching tasks. Tasks are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
== Module "contacts" ==<br />
<br />
The contacts module is used to access contact information.<br />
<br />
=== Get all contacts ===<br />
<br />
GET <code>/ajax/contacts?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried (optional from 6.22.2 on: If not set, the contents of all visible folders are used instead).<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for contacts are defined in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (preliminary, since 6.20) – allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedContactData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed contact data<br />
! ID !! Displayed name !! Name !! Type !! Value<br />
|-<br />
| 223 || || uid || String || Can only be written when the object is created. Internal and external globally unique identifier of the contact. Is used to recognize contacts within vCard files. If this attribute is not written it contains an automatic generated UUID.<br />
|-<br />
| 500 || Display name || display_name || String<br />
|-<br />
| 501 || Given name || first_name || String || First name.<br />
|-<br />
| 502 || Sur name || last_name || String || Last name.<br />
|-<br />
| 503 || Middle name || second_name || String<br />
|-<br />
| 504 || Suffix || suffix || String<br />
|-<br />
| 505 || Title || title || String<br />
|-<br />
| 506 || Street home || street_home || String<br />
|-<br />
| 507 || Postal code home || postal_code_home || String<br />
|-<br />
| 508 || City home || city_home || String<br />
|-<br />
| 509 || State home || state_home || String<br />
|-<br />
| 510 || Country home || country_home || String<br />
|-<br />
| 511 || Birthday || birthday || Date<br />
|-<br />
| 512 || Martial status || marital_status || String<br />
|-<br />
| 513 || Number of children || number_of_children || String<br />
|-<br />
| 514 || Profession || profession || String<br />
|-<br />
| 515 || Nickname || nickname || String<br />
|-<br />
| 516 || Spouse name || spouse_name || String<br />
|-<br />
| 517 || Anniversay || anniversary || Date<br />
|-<br />
| 518 || Note || note || String<br />
|-<br />
| 519 || Department || department || String<br />
|-<br />
| 520 || Position || position || String<br />
|-<br />
| 521 || Employee type || employee_type || String<br />
|-<br />
| 522 || Room number || room_number || String<br />
|-<br />
| 523 || Street business || street_business || String<br />
|-<br />
| 524 || || internal_userid || Number<br />
|-<br />
| 525 || Postal code business || postal_code_business || String<br />
|-<br />
| 526 || City business || city_business || String<br />
|-<br />
| 527 || State business || state_business || String<br />
|-<br />
| 528 || Country business || country_business || String<br />
|-<br />
| 529 || Number of employee || number_of_employees || String<br />
|-<br />
| 530 || Sales volume || sales_volume || String<br />
|-<br />
| 531 || Tax id || tax_id || String<br />
|-<br />
| 532 || Commercial register || commercial_register || String<br />
|-<br />
| 533 || Branches || branches || String<br />
|-<br />
| 534 || Business category || business_category || String<br />
|-<br />
| 535 || Info || info || String<br />
|-<br />
| 536 || Manager's name || manager_name || String<br />
|-<br />
| 537 || Assistant's name || assistant_name || String<br />
|-<br />
| 538 || Street other || street_other || String<br />
|-<br />
| 539 || City other || city_other || String<br />
|-<br />
| 540 || Postal code other || postal_code_other || String<br />
|-<br />
| 541 || Country other || country_other || String<br />
|-<br />
| 542 || Telephone business 1 || telephone_business1 || String<br />
|-<br />
| 543 || Telephone business 2 || telephone_business2 || String<br />
|-<br />
| 544 || FAX business || fax_business || String<br />
|-<br />
| 545 || Telephone callback || telephone_callback || String<br />
|-<br />
| 546 || Telephone car || telephone_car || String<br />
|-<br />
| 547 || Telephone company || telephone_company || String<br />
|-<br />
| 548 || Telephone home 1 || telephone_home1 || String<br />
|-<br />
| 549 || Telephone home 2 || telephone_home2 || String<br />
|-<br />
| 550 || FAX home || fax_home || String<br />
|-<br />
| 551 || Cellular telephone 1 || cellular_telephone1 || String<br />
|-<br />
| 552 || Cellular telephone 2 || cellular_telephone2 || String<br />
|-<br />
| 553 || Telephone other || telephone_other || String<br />
|-<br />
| 554 || FAX other || fax_other || String<br />
|-<br />
| 555 || Email 1 || email1 || String<br />
|-<br />
| 556 || Email 2 || email2 || String<br />
|-<br />
| 557 || Email 3 || email3 || String<br />
|-<br />
| 558 || URL || url || String<br />
|-<br />
| 559 || Telephone ISDN || telephone_isdn || String<br />
|-<br />
| 560 || Telephone pager || telephone_pager || String<br />
|-<br />
| 561 || Telephone primary || telephone_primary || String<br />
|-<br />
| 562 || Telephone radio || telephone_radio || String<br />
|-<br />
| 563 || Telephone telex || telephone_telex || String<br />
|-<br />
| 564 || Telephone TTY/TDD || telephone_ttytdd || String<br />
|-<br />
| 565 || Instantmessenger 1 || instant_messenger1 || String<br />
|-<br />
| 566 || Instantmessenger 2 || instant_messenger2 || String<br />
|-<br />
| 567 || Telephone IP || telephone_ip || String<br />
|-<br />
| 568 || Telephone assostant || telephone_assistant || String<br />
|-<br />
| 569 || Company || company || String<br />
|-<br />
| 570 || || image1 || String<br />
|-<br />
| 571 || Dynamic Field 1 || userfield01 || String<br />
|-<br />
| 572 || Dynamic Field 2 || userfield02 || String<br />
|-<br />
| 573 || Dynamic Field 3 || userfield03 || String<br />
|-<br />
| 574 || Dynamic Field 4 || userfield04 || String<br />
|-<br />
| 575 || Dynamic Field 5 || userfield05 || String<br />
|-<br />
| 576 || Dynamic Field 6 || userfield06 || String<br />
|-<br />
| 577 || Dynamic Field 7 || userfield07 || String<br />
|-<br />
| 578 || Dynamic Field 8 || userfield08 || String<br />
|-<br />
| 579 || Dynamic Field 9 || userfield09 || String<br />
|-<br />
| 580 || Dynamic Field 10 || userfield10 || String<br />
|-<br />
| 581 || Dynamic Field 11 || userfield11 || String<br />
|-<br />
| 582 || Dynamic Field 12 || userfield12 || String<br />
|-<br />
| 583 || Dynamic Field 13 || userfield13 || String<br />
|-<br />
| 584 || Dynamic Field 14 || userfield14 || String<br />
|-<br />
| 585 || Dynamic Field 15 || userfield15 || String<br />
|-<br />
| 586 || Dynamic Field 16 || userfield16 || String<br />
|-<br />
| 587 || Dynamic Field 17 || userfield17 || String<br />
|-<br />
| 588 || Dynamic Field 18 || userfield18 || String<br />
|-<br />
| 589 || Dynamic Field 19 || userfield19 || String<br />
|-<br />
| 590 || Dynamic Field 20 || userfield20 || String || Contains a UUID if one was assigned (after 6.18.2)<br />
|-<br />
| 591 || || links || Array || An array of objects containing links to other contacts. Each contact is describes by an object as defined in [[#ContactLinkData | Contact link data]]. '''deprecated'''<br />
|-<br />
| 592 || || distribution_list || Array || If this contact is a distribution list, then this field is an array of objects. Each object describes a member of the list as defined in [[#DistributionListMember | Distribution list member]].<br />
|-<br />
| 594 || Number of distributionlists || number_of_distribution_list || Number<br />
|-<br />
| 595 || || number_of_links || Number || '''deprecated'''<br />
|-<br />
| 596 || || number_of_images || Number<br />
|-<br />
| 597 || || image_last_modified || Timestamp<br />
|-<br />
| 598 || State other || state_other || String<br />
|-<br />
| 599 || || file_as || String<br />
|-<br />
| 601 || || image1_content_type || String<br />
|-<br />
| 602 || || mark_as_distributionlist || Boolean<br />
|-<br />
| 605 || Default address || default_address || Number<br />
|-<br />
| 606 || || image1_url || String<br />
|-<br />
| 608 || || useCount || Number || In case of sorting purposes the column 609 is also available, which places global address book contacts at the beginning of the result. If 609 is used, the order direction (ASC, DESC) is ignored.<br />
|-<br />
| 610 || || yomiFirstName || String || Kana based representation for the First Name. Commonly used in japanese environments for searchin/sorting issues. (since 6.20)<br />
|-<br />
| 611 || || yomiLastName || String || Kana based representation for the Last Name. Commonly used in japanese environments for searchin/sorting issues. (since 6.20)<br />
|-<br />
| 612 || || yomiCompany || String || Kana based representation for the Company. Commonly used in japanese environments for searchin/sorting issues. (since 6.20)<br />
|-<br />
| 613 || || addressHome || String || Support for Outlook 'home' address field. (since 6.20.1)<br />
|-<br />
| 614 || || addressBusiness || String || Support for Outlook 'business' address field. (since 6.20.1)<br />
|-<br />
| 615 || || addressOther || String || Support for Outlook 'other' address field. (since 6.20.1)<br />
|}<br />
<br />
<br />
{| id="ContactLinkData" cellspacing="0" border="1"<br />
|+ align="bottom" | Contact link data<br />
! Name !! Type !! Value<br />
|-<br />
| id || String || Object ID<br />
|-<br />
| first_name || String || First name<br />
|-<br />
| last_name || String || Last name<br />
|}<br />
<br />
{| id="DistributionListMember" cellspacing="0" border="1"<br />
|+ align="bottom" | Distribution list member<br />
! Name !! Type !! Value<br />
|-<br />
| id || String || Object ID of the member's contact if the member is an existing contact.<br />
|-<br />
| folder_id || String || Parent folder ID of the member's contact if the member is an existing contact (preliminary, from 6.22 on).<br />
|-<br />
| display_name || String || Display name<br />
|-<br />
| mail || String || Email address (mandatory before 6.22, afterwards optional if you are referring to an internal contact)<br />
|-<br />
| mail_field || Number || Which email field of an existing contact (if any) is used for the mail field.<br />
{| cellspacing="0" border="1"<br />
| 0 || independent contact<br />
|-<br />
| 1 || default email field (email1)<br />
|-<br />
| 2 || second email field (email2)<br />
|-<br />
| 3 || third email field (email3)<br />
|}<br />
|}<br />
<br />
=== Get a list of contacts ===<br />
<br />
PUT <code>/ajax/contacts?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for contacts are defined in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]].<br />
<br />
Request body: An array with objects. Each object contains fields “id” and “folder” of requested contacts.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a list of users ===<br />
<br />
PUT <code>/ajax/contacts?action=listuser</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for contacts are defined in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]].<br />
<br />
Request body: An array with id<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
Available with SP4<br />
<br />
=== Get updated contacts ===<br />
<br />
GET <code>/ajax/contacts?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for contacts are defined in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested contacts.<br />
* <code>ignore</code> (mandatory - should be set to "deleted") (deprecated) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
<br />
Response with timestamp: An array with new, modified and deleted contacts. New and modified contacts are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted contacts (should the <code>ignore</code> parameter be ever implemented) would be identified by their object IDs as plain strings, without being part of a nested array.<br />
<br />
=== Get a contact ===<br />
<br />
GET <code>/ajax/contacts?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested contact.<br />
* <code>folder</code> – Object ID of the contact's folder.<br />
<br />
Response with timestamp: An object containing all data of the requested contact. The fields of the object are listed in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]]. The field id is not included.<br />
<br />
=== Get contact by user ID ===<br />
<br />
GET <code>/ajax/contacts?action=getuser</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – User ID (not Object ID) of the requested user.<br />
<br />
Response with timestamp: An object containing all data of the requested contact. The fields of the object are listed in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]]. <br />
<br />
Available with SP4 package.<br />
<br />
=== Update a contact ===<br />
<br />
PUT <code>/ajax/contacts?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Folder identifier through that the contact is accessed. This is necessary for checking the permissions.<br />
* <code>id</code> – Object ID of the updated contact.<br />
* <code>timestamp</code> – Timestamp of the updated contact. If the contact was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: Contact object as described in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]]. Only modified fields are present.<br />
<br />
To remove some contact image send the image attribute set to <code>null</code>.<br />
<br />
To change or add some contact image the PUT command must be replaced with a POST command and all data must be provided within a <code>multipart/form-data</code> body. The normal request body must be placed into a form field named <code>json</code> while the image file must be placed in a file field named <code>file</code>. The response is then an HTML page as described in section [[#File_uploads | File uploads]].<br />
<br />
=== Create a contact ===<br />
<br />
PUT <code>/ajax/contacts?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Contact object as described in [[#CommonObjectData | Common object data]] and [[#DetailedContactData | Detailed contact data]]. The field id is not included.<br />
<br />
Response: A json objekt with attribute <code>id</code> of the newly created contact.<br />
<br />
To add some contact image the PUT command must be replaced with a POST command and all data must be provided within a <code>multipart/form-data</code> body. The normal request body must be placed into a form field named <code>json</code> while the image file must be placed in a file field named <code>file</code>. The response is then an HTML page as described in section [[#File uploads | File uploads]].<br />
<br />
=== Delete a contact ===<br />
<br />
PUT <code>/ajax/contacts?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted contacts.<br />
<br />
Request body: An object with the fields “id” and “folder”.<br />
<br />
=== Delete contacts (since v6.22)===<br />
<br />
PUT <code>/ajax/contacts?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted contacts.<br />
<br />
Request body: An array of objects with the fields “id” and “folder”.<br />
<br />
=== Search contacts ===<br />
<br />
PUT <code>/ajax/contacts?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified. In case of use of column 609 (use count depending order for collected contacts with global address book) the parameter "order" ist NOT necessary and will be ignored.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (preliminary, since 6.20) – allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Request body: An Object as described in [[#SearchContacts | Search contacts]].<br />
<br />
{| id="SearchContacts" cellspacing="0" border="1"<br />
|+ align="bottom" | Search contacts<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find contacts. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves. Matching is performed against any substring of the field <code>display_name</code>.<br />
|-<br />
| startletter || String || Search contacts with the given startletter. If this field is present, the pattern is matched against the contact field which is specified by the property contact_first_letter_field on the server (default: last name). Otherwise, the pattern is matched against the display name.<br />
|-<br />
| folder || Array of Number || If a list of folder identifiers or at least a single folder identifier is given, only in that folders will be searched for contacts. This paramenter is optional but searching in all contact folders that are viewable and where objects can be read in is more expensive on that database than searching in a dedicated number of them. The possibility to provide here an array of folder identifier has been added with 6.10.<br />
|}<br />
<br />
Alternative request body: An Object as described in [[#SearchContactsAlternative | Search contacts alternative]].<br />
<br />
{| id="SearchContactsAlternative" cellspacing="0" border="1"<br />
|+ align="bottom" | Search contacts alternative<br />
! Name !! Type !! Value<br />
|-<br />
| last_name || String || Searches contacts where the last name match with the given last name.<br />
|-<br />
| first_name || String || Searches contacts where the first name match with the given first name.<br />
|-<br />
| display_name || String || Searches contacts where the display name match with the given display name.<br />
|-<br />
| email1 || String || Searches contacts where the email1 address match with the given search pattern. (requires version >= 6.12)<br />
|-<br />
| email2 || String || Searches contacts where the email2 address match with the given search pattern. (requires version >= 6.12)<br />
|-<br />
| email3 || String || Searches contacts where the email3 address match with the given search pattern. (requires version >= 6.12)<br />
|-<br />
| company || String || Searches contacts where the company match with the given search pattern. (requires version >= 6.12)<br />
|-<br />
| categories || String || Searches contacts where the categories match with the given search pattern. <br />
|-<br />
| orSearch || Boolean || If set to true, a contact is returned if any specified pattern matches at the start of the corresponding field. Otherwise, a contact is returned if all specified patterns match any substring of the corresponding field.<br />
|-<br />
| emailAutoComplete || Boolean || If set to true, results are guaranteed to contain at least one email adress and the search is performed as if orSearch were set to true. The actual value of orSearch is ignored.<br />
|-<br />
| exactMatch || Boolean || If set to true, contacts are returned where the specified patterns match the corresponding fields exactly. Otherwise, a 'startsWith' or 'substring' comparison is used based on the 'orSearch' parameter. (requires version > 6.22.1)<br />
|}<br />
<br />
Response: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Search contacts by filter (since 6.20) ===<br />
<br />
PUT <code>/ajax/contacts?action=advancedSearch</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified. <br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (preliminary, since 6.20) – allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Request body: An Object as described in [[#Module_.22search.22_.28alternative_suggestion.2C_still_preliminary.29 | Search Filter]]<br />
<br />
Response: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Search contacts by anniversary (Since 6.22.1, Preliminary) ===<br />
<br />
Find contacts whose anniversary falls into a timerange.<br />
<br />
GET <code>/ajax/contacts?action=anniversaries</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>start</code> – The lower (inclusive) limit of the requested time-range.<br />
* <code>end</code> – The upper (exclusive) limit of the requested time-range.<br />
* <code>columns</code> – The requested fields.<br />
* <code>folder</code> (optional) – Object ID of the parent folder that is searched. If not set, all visible folders are used.<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If not specified, the results are sorted ascending by their anniversary in the supplied timerange. If this parameter is specified, then the parameter order must be also specified. <br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (optional) – Allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Search contacts by birthday (Since 6.22.1, Preliminary) ===<br />
<br />
Find contacts whose birthday falls into a timerange.<br />
<br />
GET <code>/ajax/contacts?action=birthdays</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>start</code> – The lower (inclusive) limit of the requested time-range.<br />
* <code>end</code> – The upper (exclusive) limit of the requested time-range.<br />
* <code>columns</code> – The requested fields.<br />
* <code>folder</code> (optional) – Object ID of the parent folder that is searched. If not set, all visible folders are used.<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If not specified, the results are sorted ascending by their birthday in the supplied timerange. If this parameter is specified, then the parameter order must be also specified. <br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>collation</code> (optional) – Allows you to specify a collation to sort the contacts by. As of 6.20, only supports "gbk" and "gb2312", not needed for other languages. Parameter <code>sort</code> should be set for this to work.<br />
<br />
Response with timestamp: An array with contact data. Each array element describes one contact and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
== Module "calendar" ==<br />
<br />
The calendar module is used to access calendar data.<br />
<br />
=== Get all appointments ===<br />
<br />
GET <code>/ajax/calendar?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> (optional) – Object ID of the folder, whose contents are queried. If not specified, defaults to all calendar folders.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]].<br />
* <code>start</code> – Lower inclusive limit of the queried range as a Date. Only appointments which start on or after this date are returned.<br />
* <code>end</code> – Upper exclusive limit of the queried range as a Date. Only appointments which end before this date are returned.<br />
* <code>recurrence_master</code> – Extract the recurrence to several appointments. The default value is false so every appointment of the recurrence will be calculated.<br />
* <code>showPrivate</code> (optional) – only works in shared folders: When enabled, shows private appointments of the folder owner. Such appointments are anonymized by stripping away all information except start date, end date and recurrence information (since 6.18)<br />
<br />
Response with timestamp: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Appointment sequencies are broken up into individual appointments and each occurrence of a sequence in the requested range is returned separately. The appointments are sorted in ascending order by the field start_date.<br />
<br />
{| id="DetailedAppointmentData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed appointment data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 206 || recurrence_id || Number || Object ID of the entire appointment sequence. Present on series and change exception appointments. Equals to object identifier on series appointment and is different to object identifier on change exceptions.<br />
|-<br />
| 207 || recurrence_position || Number || 1-based position of an individual appointment in a sequence. Present if and only if recurrence_type > 0.<br />
|-<br />
| 208 || recurrence_date_position || Date || Date of an individual appointment in a sequence. Present if and only if recurrence_type > 0.<br />
|-<br />
| 210 || change_exceptions || Array || An array of Dates, representing all change exceptions of a sequence.<br />
|-<br />
| 211 || delete_exceptions || Array || An array of Dates, representing all delete exceptions of a sequence.<br />
|-<br />
| 400 || location || String || Location<br />
|-<br />
| 401 || full_time || Boolean || True if the appointment is a whole day appointment, false otherwise.<br />
|-<br />
| 402 || shown_as || Number || Describes, how this appointment appears in availability queries:<br />
{| cellspacing="0" border="1"<br />
| 1 || reserved<br />
|-<br />
| 2 || temporary<br />
|-<br />
| 3 || absent<br />
|-<br />
| 4 || free<br />
|}<br />
|-<br />
| 408 || timezone || String || Timezone<br />
|-<br />
| 410 || recurrence_start || Date || Start of a sequence without time<br />
|-<br />
| || ignore_conflicts || Boolean || Ignore soft conflicts for the new or modified appointment. This flag is valid for the current change only, i. e. it is not stored in the database and is never sent by the server to the client. <br />
|}<br />
<br />
=== Get appointment information ===<br />
<br />
GET <code>/ajax/calendar?action=has</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>start</code> – Lower inclusive limit of the queried range as a Date. Only appointments which end on or after this date are returned.<br />
* <code>end</code> – Upper exclusive limit of the queried range as a Date. Only appointments which start before this date are returned.<br />
<br />
Response is an array of booleans. Array length is the number of days. Each entry in the array corresponds with one day in the range that was queried, explaining whether there is an appointment on this day or not.<br />
<br />
=== Get a list of appointments ===<br />
<br />
PUT <code>/ajax/calendar?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]].<br />
* <code>recurrence_master</code> – Extract the recurrence to several appointments. The default value is false so every appointment of the recurrence will be calculated.<br />
<br />
Request body: An array with full object IDs (folder, id and optionally either recurrence_position or recurrence_date_position) of requested appointments.<br />
<br />
Response with timestamp: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="FullIdentifierForAnAppointment" cellspacing="0" border="1"<br />
|+ align="bottom" | Full identifier for an appointment<br />
! Name !! Type !! Value<br />
|-<br />
| id || String || Object ID<br />
|-<br />
| pos || Number || Value of the field recurrence_position, if present in the appointment.<br />
|}<br />
<br />
=== Get updated appointments ===<br />
<br />
GET <code>/ajax/calendar?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]].<br />
* <code>timestamp</code> – Timestamp of the last update of the requested appointments.<br />
* <code>start</code> (optional) – Lower inclusive limit of the queried range as a Date. Only appointments which end on or after this date are returned.<br />
* <code>end</code> (optional) – Upper exclusive limit of the queried range as a Date. Only appointments which start before this date are returned.<br />
* <code>ignore</code> (mandatory - should be set to "deleted") (deprecated) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
* <code>recurrence_master</code> – Extract the recurrence to several appointments. The default value is false so every appointment of the recurrence will be calculated.<br />
* <code>showPrivate</code> (optional) – only works in shared folders: When enabled, shows private appointments of the folder owner. Such appointments are anonymized by stripping away all information except start date, end date and recurrence information (since 6.18)<br />
<br />
Response with timestamp: An array with new, modified and deleted appointments. New and modified appointments are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted appointments (should the <code>ignore</code> parameter be ever implemented) would be identified by objects described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]] instead of arrays. Appointment sequencies are broken up into individual appointments and each modified occurrence of a sequence in the requested range is returned separately. The appointments are sorted in ascending order by the field start_date.<br />
<br />
=== Get an appointment ===<br />
<br />
GET <code>/ajax/calendar?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested appointment.<br />
* <code>folder</code> – Folder ID of the requested appointment.<br />
* <code>recurrence_position</code> (optional) – Recurrence Position requested appointment.<br />
<br />
Response with timestamp: An object containing all data of the requested appointment. The fields of the object are listed in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]]. The field id is not included.<br />
<br />
=== Update an appointment ===<br />
<br />
PUT <code>/ajax/calendar?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated appointment.<br />
* <code>folder</code> - Object ID of the appointment's folder.<br />
* <code>timestamp</code> – Timestamp of the updated appointment. If the appointment was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: Appointment object as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]]. The field recurrence_id is always present if it is present in the original appointment. The field recurrence_position is present if it is present in the original appointment and only this single appointment should be modified. The field id is not present because it is already included as a parameter. Other fields are present only if modified.<br />
<br />
=== Create an appointment ===<br />
PUT <code>/ajax/calendar?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Appointment object as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[#DetailedAppointmentData | Detailed appointment data]]. The field id is not present.<br />
<br />
Response: If the appointment was created successfully, an object with the attribute <code>id</code> of the newly created appointment. If the appointment could not be created due to conflicts, the response body is an object with the field <code>conflicts</code>, which is an array of appointment objects which caused the conflict. Each appointment object which represents a resource conflict contains an additional field <code>hard_conflict</code> with the Boolean value true. If the user does not have read access to a conflicting appointment, only the fields <code>id</code>, <code>start_date</code>, <code>end_date</code>, <code>shown_as</code> and <code>participants</code> are present and the field <code>participants</code> contains only the participants which caused the conflict.<br />
<br />
=== Delete an appointment ===<br />
<br />
PUT <code>/ajax/calendar?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted appointments.<br />
<br />
Request body: The appointment object to delete. The fields for the object are described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]]. <br />
<br />
Response: An array of objects identifying the appointments which were modified after the specified timestamp and were therefore not deleted. The fields of each object are described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]].<br />
<br />
=== Delete appointments (since v6.22) ===<br />
<br />
PUT <code>/ajax/calendar?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted appointments.<br />
<br />
Request body: An array of appointment objects to delete. The fields for the object are described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]]. <br />
<br />
Response: An array of objects identifying the appointments which were modified after the specified timestamp and were therefore not deleted. The fields of each object are described in [[#FullIdentifierForAnAppointment | Full identifier for an appointment]].<br />
<br />
=== Confirm appointment ===<br />
<br />
PUT <code>/ajax/calendar?action=confirm</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the appointment to confirm.<br />
* <code>folder</code> – ID of the folder through which the appointment is accessed.<br />
* <code>timestamp</code> – Timestamp of the last update of the to confirmed appointment.<br />
<br />
Request body: An object with the fields "confirmation", "confirmmessage" and "id" (optional) as described in [[#UserParticipantObject | User participant object]].<br />
<br />
Response: Nothing, except the standard response object with empty data, the timestamp of the confirmed and thereby updated task, and maybe errors.<br />
<br />
=== Free & Busy ===<br />
<br />
GET <code>/ajax/calendar?action=freebusy</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> - Internal user id. Must be obtained from the contact module.<br />
* <code>type</code> - Constant for user or resource (1 for users, 3 for resources)<br />
* <code>start</code> – Lower inclusive limit of the queried range as a Date. Only appointments which end on or after this date are returned.<br />
* <code>end</code> – Upper exclusive limit of the queried range as a Date. Only appointments which start before this date are returned.<br />
<br />
Response: An array of objects identifying the appointments which lie between start and end as described.<br><br />
This objects consist of:<br />
{| id="FreeAndBusyAppointment" cellspacing="0" border="1"<br />
! Name !! Type !! Value<br />
|-<br />
| shown_as || Number || Describes, how this appointment appears in availability queries:<br />
{| cellspacing="0" border="1"<br />
| 1 || reserved<br />
|-<br />
| 2 || temporary<br />
|-<br />
| 3 || absent<br />
|-<br />
| 4 || free<br />
|}<br />
|-<br />
| start_date || Date or Time || see [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]]<br />
|- <br />
| end_date || Date or Time || see [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]]<br />
|-<br />
| id || String || Object ID<br />
|-<br />
| folder_id || String || Folder ID. Only set, if the user has the right to see the object. (added 2009-08-18/6.12) <br />
|-<br />
| full_time || Boolean || True if the appointment is a whole day appointment, not present otherwise.<br />
|}<br />
<br />
=== Search appointments ===<br />
<br />
PUT <code>/ajax/calendar?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
<br />
Request body: An Object as described in [[#SearchAppointments | Search appointments]].<br />
<br />
{| id="SearchAppointments" cellspacing="0" border="1"<br />
|+ align="bottom" | Search appointments<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find appointments. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|-<br />
| startletter || String || Search appointments with the given starting letter.<br />
|}<br />
<br />
Request body: An Object as described in [[#SearchAppointments | Search appointments]].<br />
<br />
Response: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get new appointments ===<br />
<br />
GET <code>/ajax/calendar?action=newappointments</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
* <code>start</code> – Lower inclusive limit of the queried range as a Date. Only appointments which end on or after this date are returned.<br />
* <code>end</code> – Upper exclusive limit of the queried range as a Date. Only appointments which start before this date are returned.<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified and holds a column number, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>limit</code> – limits the number of returned object to the given value.<br />
<br />
Response: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Resolve UID ===<br />
<br />
GET <code>/ajax/calendar?action=resolveuid</code><br />
<br />
Parameters<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>uid</code> – The UID to be resolved.<br />
<br />
Response: An object object with the field "id" containing the ox-object id, if existing, an error message otherwise.<br />
<br />
=== Get all Change Exceptions (Since v7.2.0) ===<br />
<br />
GET <code>/ajax/calendar?action=getChangeExceptions</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object id of the appointment series.<br />
* <code>folder</code> – Folder ID of the requested appointments. <br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier.<br />
<br />
Response with timestamp: An array with appointment data. Each array element describes one appointment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
== Module "mail" ==<br />
<br />
The mail module is used to access mail data.<br />
<br />
When mails are stored on an IMAP server, some functionality is not available due to restrictions of the IMAP protocol. Such functionality is marked with "not IMAP".<br />
<br />
=== Get mail count ===<br />
<br />
GET <code>/ajax/mail?action=count</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder whose mail count is queried<br />
<br />
Response (not IMAP: with timestamp): An integer value representing folder's mail count<br />
<br />
=== Get all mails ===<br />
<br />
GET <code>/ajax/mail?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#DetailedMailData | Detailed mail data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response or the string “thread” to return thread-sorted messages. If this parameter is specified and holds a column number, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>left_hand_limit</code> - A positive integer number to specify the "right-hand" limit of the range to return<br />
* <code>right_hand_limit</code> - A positive integer number to specify the "left-hand" limit of the range to return<br />
* <code>limit</code> - A positive integer number to specify how many items shall be returned according to given sorting; overrides <code>left_hand_limit</code>/<code>right_hand_limit</code> parameters and is equal to <code>left_hand_limit=0</code> and <code>right_hand_limit=&lt;limit&gt;</code><br />
<br />
Response (not IMAP: with timestamp): An array with mail data. Each array element describes one mail and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedMailData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed mail data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 102 || color_label || Number || Color number used by Outlook to label the object. The assignment of colors to numbers is arbitrary and specified by the client. The numbers are integer numbers between 1 and 10 (inclusive).<br />
|-<br />
| 600 || id || String || Object ID<br />
|-<br />
| 601 || folder_id || String || Object ID of the parent folder<br />
|-<br />
| 602 || attachment || Boolean || Specifies whether this mail has attachments.<br />
|-<br />
| 603 || from || Array || Each element is a two-element array specifying one sender. The first element of each address is the personal name, the second element is the email address. Missing address parts are represented by <code>null</code> values.<br />
|-<br />
| 604 || to || Array || Each element is a two-element array (see the from field) specifying one receiver.<br />
|-<br />
| 605 || cc || Array || Each element is a two-element array (see the from field) specifying one carbon-copy receiver.<br />
|-<br />
| 606 || bcc || Array || Each element is a two-element array (see the from field) specifying one blind carbon-copy receiver.<br />
|-<br />
| 607 || subject || String || Subject line.<br />
|-<br />
| 608 || size || Number || Size of the mail in bytes.<br />
|-<br />
| 609 || sent_date || Time || Date and time as specified in the mail by the sending client.<br />
|-<br />
| 610 || received_date || Time || Date and time as measured by the receiving server.<br />
|-<br />
| 611 || flags || Number || Various system flags. A sum of zero or more of following values:<br />
{| cellspacing="0" border="1"<br />
| 1 || answered<br />
|-<br />
| 2 || deleted<br />
|-<br />
| 4 || draft<br />
|-<br />
| 8 || flagged<br />
|-<br />
| 16 || recent<br />
|-<br />
| 32 || seen<br />
|-<br />
| 64 || user<br />
|-<br />
| 256 || forwarded<br />
|}<br />
See javax.mail.Flags.Flag for details.<br />
|-<br />
| 612 || level || Number || Zero-based nesting level in a thread.<br />
|-<br />
| 613 || disp_notification_to || String || Content of message's header “Disposition-Notification-To”<br />
|-<br />
| 614 || priority || Number || Value of message's “X-Priority” header:<br />
{| cellspacing="0" border="1"<br />
| 0 || No priority<br />
|-<br />
| 5 || Very Low<br />
|-<br />
| 4 || Low<br />
|-<br />
| 3 || Normal<br />
|-<br />
| 2 || High<br />
|-<br />
| 1 || Very High<br />
|}<br />
|-<br />
| 615 || msg_ref || String || Message reference on reply/forward.<br />
|-<br />
| 651 || flag_seen || String || Special field to sort mails by seen status<br />
|-<br />
| 652 || account_name || String || Message's account name.<br />
|-<br />
| 653 || account_id || int || Message's account identifier. Since v6.20.2<br />
|-<br />
| || user || Array || An array with user-defined flags as strings.<br />
|-<br />
| || headers || Object || An object with a field for every non-standard header. The header name is the field name. The header value is the value of the field as string.<br />
|-<br />
| || attachments || Array || Each element is an attachment as described in [[#Attachment | Attachment]]. The first element is the mail text. If the mail has multiple representations (multipart-alternative), then the alternatives are placed after the mail text and have the field disp set to alternative.<br />
|-<br />
| || nested_msgs || Array || Each element is a mail object as described in this table, except for fields id, folder_id and attachment.<br />
|}<br />
<br />
{| id="Attachment" cellspacing="0" border="1"<br />
|+ align="bottom" | Attachment<br />
! Name !! Type !! Value<br />
|-<br />
| id || String || Object ID (unique only inside the same message)<br />
|-<br />
| content_type || String || MIME type<br />
|-<br />
| content || String || Content as text. Present only if easily convertible to text.<br />
|-<br />
| filename || String || Displayed filename (mutually exclusive with content).<br />
|-<br />
| size || Number || Size of the attachment in bytes.<br />
|-<br />
| disp || String || Attachment's disposition: null, inline, attachment or alternative.<br />
|}<br />
<br />
=== Get all mail conversations (since v7.x) ===<br />
<br />
GET <code>/ajax/mail?action=threadedAll</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#DetailedMailData | Detailed mail data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response or the string “thread” to return thread-sorted messages. If this parameter is specified and holds a column number, then the parameter order must be also specified. <b>Note</b>: Applies only to root-level messages.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified. <b>Note</b>: Applies only to root-level messages.<br />
* <code>includeSent</code> - A boolean value to signal that conversations also include messages taken from special "sent" aka "sent items" folder<br />
* <code>left_hand_limit</code> - A positive integer number to specify the "right-hand" limit of the range to return. <b>Note</b>: Applies only to root-level messages.<br />
* <code>right_hand_limit</code> - A positive integer number to specify the "left-hand" limit of the range to return. <b>Note</b>: Applies only to root-level messages.<br />
* <code>limit</code> - A positive integer number to specify how many items shall be returned according to given sorting; overrides <code>left_hand_limit</code>/<code>right_hand_limit</code> parameters and is equal to <code>left_hand_limit=0</code> and <code>right_hand_limit=&lt;limit&gt;</code>. <b>Note</b>: Applies only to root-level messages.<br />
<br />
Response (not IMAP: with timestamp): An JSON array consisting of JSON objects, each representing a conversation's root message along with its message thread. The root message's JSON object is filled according to specified columns and is enhanced by special <code>"thread"</code> JSON field representing the full message thread (including the root message itself). The <code>"thread"</code> JSON field is a JSON array of JSON objects; each representing a message in the conversation sorted by time-line, also filled with specified columns. E.g.<br />
<br />
<pre><br />
{<br />
"flags":32,<br />
"color_label":0,<br />
"unreadCount":0,<br />
"id":"263852",<br />
"folder_id":"default0/INBOX",<br />
"thread":[<br />
{<br />
"id":"263852",<br />
"folder_id":"default0/INBOX",<br />
"flags":32,<br />
"color_label":0<br />
},<br />
{<br />
"id":"263853",<br />
"folder_id":"default0/INBOX",<br />
"flags":32,<br />
"color_label":0<br />
},<br />
{<br />
"id":"26323",<br />
"folder_id":"default0/Sent",<br />
"flags":32,<br />
"color_label":0<br />
},<br />
{<br />
"id":"263854",<br />
"folder_id":"default0/INBOX",<br />
"flags":32,<br />
"color_label":0<br />
}<br />
]<br />
}<br />
</pre><br />
<br />
=== Search mails ===<br />
<br />
PUT <code>/ajax/mail?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for appointments are defined in [[#DetailedMailData | Detailed mail data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response or the string “thread” to return thread-sorted messages. If this parameter is specified and holds a column number, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Request Body: A JSON array of JSON objects each containing the search field and its search pattern: e.g.:<br />
<code>[{"col": 612, "pattern": "Joe"}, {"col": 614, "pattern": "Tuesday"}]</code> Supported values for <code>col</code> are 603 to 607 (from, to, cc, bcc and subject) and -1 for full text search.<br />
<br />
Response (not IMAP: with timestamp): An array with mail data. Each array element describes one mail and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a list of mails ===<br />
<br />
PUT <code>/ajax/mail?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for mails are defined in [[#DetailedMailData | Detailed mail data]].<br />
* <code>headers</code> - (preliminary) A comma-separated list of header names. Each name requests denoted header from each mail<br />
<br />
Request body: An array with one object for each requested mail. Each object contains the fields <code>folder</code> and <code>id</code>.<br />
<br />
Response (not IMAP: with timestamp): An array with mail data. Each array element describes one mail and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter followed by requested headers.<br />
<br />
=== Copy mails ===<br />
<br />
PUT <code>/ajax/mail?action=copy</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested mail.<br />
* <code>folder</code> – Object ID of the source folder.<br />
<br />
Request Body: A JSON object containing the id of the destination folder inside the "folder_id" field: e.g.:<br />
<code>{"folder_id": 1376}</code><br />
<br />
Response: A JSON array containing the ID of the copied mail<br />
<br />
=== Move mails ===<br />
<br />
PUT <code>/ajax/mail?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested mail.<br />
* <code>folder</code> – Object ID of the source folder.<br />
<br />
Request Body: A JSON object containing the id of the destination folder inside the "folder_id" field: e.g.:<br />
<code>{"folder_id": 1376}</code><br />
<br />
<br />
Response: A JSON array containing the ID of the moved mail<br />
<br />
=== Update mails ===<br />
<br />
PUT <code>/ajax/mail?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested mail.<br />
* <code>message_id</code> – (Preliminary) The value of "Message-Id" header of the requested mail. This parameter is a substitute for "id" parameter.<br />
* <code>folder</code> – Object ID of the folder.<br />
<br />
'''Note''': If neither parameter "<code>id</code>" nor parameter "<code>message_id</code>" is specified, all folder's messages are updated accordingly. Available with v6.20.<br />
<br />
Request Body: A JSON object which carries the new values that ought to be applied to mail as described in [[#UpdateMail | Update mail]] or [[#UpdateMailExtended | Update mail extended]] (available with SP6 v6.10).<br />
<br />
Response: A JSON object containing the Object ID of the updated mail and its folder.<br />
<br />
{| id="UpdateMail" cellspacing="0" border="1"<br />
|+ align="bottom" | Update mail<br />
! Name !! Type !! Value<br />
|-<br />
| color_label || Number || The color number between 1 and 10.<br />
|-<br />
| flags || Number || A set of flags to add or remove. Note: Flags for "recent" (8) and "user" (64) are ignored.<br />
|-<br />
| value || Boolean || <code>true</code> to add the flags specified by <code>flags</code> (logical OR), <code>false</code> to remove them (logical AND with the inverted value).<br />
|}<br />
<br />
<br />
<br />
{| id="UpdateMailExtended" cellspacing="0" border="1"<br />
|+ align="bottom" | Update mail extended (available with SP6 v6.10)<br />
! Name !! Type !! Value<br />
|-<br />
| set_flags || Number || A set of flags to add. Note: Flags for "recent" (8) and "user" (64) are ignored.<br />
|-<br />
| clear_flags || Number || A set of flags to remove. Note: Flags for "recent" (8) and "user" (64) are ignored.<br />
|}<br />
<br />
=== Not IMAP: Get updated mails ===<br />
<br />
GET <code>/ajax/mail?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: Just an empty JSON array is going to be returned since this action cannot be applied to IMAP.<br />
<br />
=== Get a mail ===<br />
<br />
GET <code>/ajax/mail?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested mail.<br />
* <code>message_id</code> – (Preliminary) The value of "Message-Id" header of the requested mail. This parameter is a substitute for "id" parameter.<br />
* <code>folder</code> – Object ID of the mail's folder.<br />
* <code>edit</code> (optional) – 1 indicates that this request should fill the message compose dialog to edit a message and thus display-specific date is going to be withheld.<br />
* <code>hdr</code> (optional) – 1 to let the response contain only the (formatted) message headers as plain text<br />
* <code>src</code> (optional) – 1 to let the response contain the complete message source as plain text<br />
* <code>save</code> (optional) – 1 to write the complete message source to output stream. '''NOTE:''' This parameter will only be used if parameter <code>src</code> is set to 1.<br />
* <code>view</code> (optional - available with SP4)<br />
** "raw" returns the content as it is, meaning no preparation are performed and thus no guarantee for safe contents is given (available with SP6 v6.10).<br />
** "text" forces the server to deliver a text-only version of the requested mail's body, even if content is HTML.<br />
** "textNoHtmlAttach" is the same as "text", but does not deliver the HTML part as attachment in case of multipart/alternative content.<br />
** "html" to allow a possible HTML mail body being transferred as it is (but white-list filter applied).<br />
** "noimg" to allow a possible HTML content being transferred but without original image src attributes which references external images: Can be used to prevent loading external linked images (spam privacy protection).<br />
** '''NOTE:''' if set, the corresponding gui config setting will be ignored.<br />
* <code>unseen</code> (optional) – "1" or "true" to leave an unseen mail as unseen although its content is requested<br />
<br />
Response (not IMAP: with timestamp): An JSON object containing all data of the requested mail. The fields of the object are listed in [[#DetailedMailData | Detailed mail data]]. The fields id and attachment are not included. '''NOTE:''' Of course response is not a JSON object if either parameter <code>hdr</code> or parameter <code>src</code> are set to "1". Then the response contains plain text. Moreover if optional parameter <code>save</code> is set to "1" the complete message source is going to be directly written to output stream to open browser's save dialog.<br />
<br />
=== Get multiple mails as a ZIP file ===<br />
<br />
GET <code>/ajax/mail?action=zip_messages</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – The folder identifier.<br />
* <code>id</code> – A comma-separated list of Object IDs of the requested mails<br />
<br />
Response body: The raw byte data of the ZIP file.<br />
<br />
=== Get a mail attachment ===<br />
<br />
GET <code>/ajax/mail?action=attachment</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – The folder identifier.<br />
* <code>id</code> – Object ID of the mail which contains the attachment.<br />
* <code>attachment</code> – ID of the requested attachment '''OR'''<br />
* <code>cid</code> – Value of header 'Content-ID' of the requested attachment<br />
* <code>save</code> – 1 overwrites the defined mimetype for this attachment to force the download dialog, otherwise 0.<br />
* <code>filter</code> (optional) – 1 to apply HTML white-list filter rules if and only if requested attachment is of MIME type <code>text/htm*</code> '''AND''' parameter <code>save</code> is set to 0.<br />
<br />
Response body: The raw byte data of the document. The response type for the HTTP Request is set accordingly to the defined mimetype for this attachment, except the parameter save is set to 1.<br />
<br />
=== Get multiple mail attachments as a ZIP file ===<br />
<br />
GET <code>/ajax/mail?action=zip_attachments</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – The folder identifier.<br />
* <code>id</code> – Object ID of the mail which contains the attachments.<br />
* <code>attachment</code> – A comma-separated list of IDs of the requested attachments<br />
<br />
Response body: The raw byte data of the ZIP file.<br />
<br />
=== Send a mail ===<br />
<br />
POST <code>/ajax/mail?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request Body: This method uses the encoding multipart/form-data or multipart/mixed.<br />
* The form filed <code>json_0</code> contains the rudimentary mail as JSON object as described in [[#DetailedMailData | Detailed mail data]] with just its message body (as html content) defined in nested JSON array "attachments" and its header data (from, to, subject, etc.). The field "content_type" defines whether the mail ought to be sent as plain text ("text/plain"), as html ("text/html") or as multipart/alternative ("ALTERNATIVE"). Sending a mail requires some special fields inside JSON mail object. The field "infostore_ids" defines a JSON array of infostore document ID(s) that ought to be appended to this mail as attachments. The field "msgref" indicates the ID of the referenced original mail. Moreover the field "sendtype" indicates the type of the message:<br />
** 0 - A normal new mail (optional)<br />
** 1 - A reply mail. The field "msgref" must be present<br />
** 2 - A forward mail. The field "msgref" must be present<br />
** 3 - A draft edit operation. The field "msgref" must be present in order to delete previous draft message since e.g. IMAP does not support changing/replacing a message but requires a delete-and-insert sequence<br />
** 4 - Transport of a draft mail. The field "msgref" must be present<br />
** 6 - This type signals that user intends to send out a saved draft message and expects the draft message (referenced by "msgref" field) being deleted after successful transport<br />
Example of a normal new mail which appends user's VCard and requests a read receipt from receiver:<br />
<br />
<code>Content-Disposition: form-data; name="json_0"....{"from":"\u0022Muster, Karl\u0022 <karl.muster@somewhere.com>","to":"someone@somewhere.com","cc":"","bcc":"",<br />
"subject":"Mail Subject","priority":"3","disp_notification_to":true,"vcard":1,<br />
"attachments":[{"content_type":"ALTERNATIVE","content":"Simple Mail Text!&lt;br&gt;&lt;br&gt;\u000a\u000a"}]}</code><br />
* The request accepts file fields in upload form that denote referenced files that are going to be appended as attachments<br />
<br />
==== Attach data sources ====<br />
Moreover the JSON representation may contain data sources which should be appended as file attachments to the mail. Then the mail contains the <code>"datasources"</code> key which is expected to be a JSON array of data source descriptions.<br />
<br />
A data source description follows the [[#Module_.22conversion.22_.28preliminary.29 | conversion specification]].<br />
<br />
For example to attach a file through an URL the field looks like this (available with v6.18.2):<br />
<br />
<pre><br />
{<br />
"from": "someone@somewhere.com,<br />
...<br />
"datasources"<br />
[<br />
{<br />
"identifier": "com.openexchange.url.mail.attachment",<br />
"args":<br />
{<br />
"url": <url-string>,<br />
"timeout": <optional-timeout-millis-int, default is 2500msec>,<br />
"contentType": <optional-content-type-string>,<br />
"charset": <optional-charset-string>,<br />
"size": <optional-size-int>,<br />
"disposition": <optional-disposition-string>,<br />
"fileName": <optional-file-name-string>,<br />
}<br />
}<br />
]<br />
}<br />
</pre><br />
<br />
Response: Object ID of the newly created mail.<br />
<br />
=== Send/Save mail as MIME data block (RFC822) (added in SP5) ===<br />
<br />
PUT <code>/ajax/mail?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> - A session ID previously obtained from the login module.<br />
* <code>folder</code> (optional) - In case the mail should not be sent out, but saved in a specific folder, the "folder" parameter can be used. If the mail should be sent out to the recipient, the "folder" parameter must not be included and the mail is stored in the folder "Sent Items". Example "folder=default.INBOX/Testfolder"<br />
* <code>flags</code> (optional) - In case the mail should be stored with status "read" (e.g. mail has been read already in the client inbox), the parameter "flags" has to be included. If no "folder" parameter is specified, this parameter must not be included. For infos about mail flags see [[#DetailedMailData | Detailed mail data]] spec.<br />
<br />
Request Body: The MIME Data Block<br />
<br />
Response: Object ID of the newly created/moved mail.<br />
<br />
=== Import of mails as MIME data block (RFC822) (added with 6.18) ===<br />
<br />
This request can be used to store a single or a lot of mails in the OX mail storage backend. This action should be used instead of <code>action=new</code> because it is faster and tolerant to 8bit encoded emails.<br />
<br />
<code>POST /ajax/mail?action=import</code><br />
<br />
Parameters:<br />
* <code>session</code> - A session ID previously obtained from the login module.<br />
* <code>folder</code> - For the import this parameter is required to specify the folder into that the emails should be imported. Example "folder=default.INBOX/Testfolder"<br />
* <code>flags</code> (optional) - In case the mail should be stored with status "read" (e.g. mail has been read already in the client inbox), the parameter "flags" has to be included. For infos about mail flags see [[#DetailedMailData | Detailed mail data]] spec.<br />
*<code>force</code> (optional) - If this parameter is set to true, the server skips checking the valid From-address<br />
<br />
Request Body: A multipart/form-data with a single or multiple file parts each having a different name and containing the RFC822 encoded email as binary data like in a file upload.<br />
<br />
Response: A JSON object containing the folder identifier and the object identifier of the imported mail or a JSON array of those JSON objects if multiple mails are imported.<br />
<br />
=== Reply/Forward a mail ===<br />
<br />
GET <code>/ajax/mail?action=reply</code><br><br />
GET <code>/ajax/mail?action=replyall</code><br><br />
GET <code>/ajax/mail?action=forward</code><br><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested Message.<br />
* <code>folder</code> - Object ID of the folder, whose contents are queried.<br />
* <code>view</code> (optional - available with SP6) - "text" forces the server to deliver a text-only version of the requested mail's body, even if content is HTML. "html" to allow a possible HTML mail body being transferred as it is (but white-list filter applied).'''NOTE:''' if set, the corresponding gui config setting will be ignored.<br />
<br />
Response (not IMAP: with timestamp): An object containing all data of the requested mail. The fields of the object are listed in [[#DetailedMailData | Detailed mail data]]. The fields id and attachment are not included.<br />
<br />
=== Delete mails ===<br />
<br />
PUT <code>/ajax/mail?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* Not IMAP: <code>timestamp</code> – Timestamp of the last update of the deleted mails.<br />
<br />
Request body: An array of objects providing folder IDs and object IDs of the deleted mails.<br />
<code><br><br />
[<br><br />
&nbsp;{&nbsp;&quot;folder&quot;:&quot;default0/INBOX&quot;,&nbsp;&quot;id&quot;:&quot;123&quot;&nbsp;}<br><br />
&nbsp;...<br><br />
&nbsp;{&nbsp;&quot;folder&quot;:&quot;default0/MyFolder&quot;,&nbsp;&quot;id&quot;:&quot;134&quot;&nbsp;}<br><br />
]<br><br />
</code><br />
<br />
Not IMAP: Response: An array with object IDs of mails which were modified after the specified timestamp and were therefore not deleted.<br />
<br />
=== Clear mail folder(s) ===<br />
<br />
PUT <code>/ajax/mail?action=clear</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* Not IMAP: <code>timestamp</code> – Timestamp of the last update of the deleted mails.<br />
<br />
Request body: An array with IDs of the mail folders to clear<br />
<br />
Response: An array with IDs of mail folder that could not be cleared; meaning the response body is an empty JSON array if everything went well.<br />
<br />
== Module "groups" ==<br />
<br />
The group module allows to query available groups. It is mainly used by the dialog for the selection of participants.<br />
<br />
=== Get a group ===<br />
<br />
GET <code>/ajax/group?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The group id.<br />
<br />
Response: A group object as described in [[#GroupData | Group data]].<br />
<br />
=== List groups ===<br />
<br />
PUT <code>/ajax/group?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An array with group identifiers.<br />
<br />
Response: An array of group objects as described in [[#GroupData | Group data]].<br />
<br />
=== Search for groups ===<br />
<br />
PUT <code>/ajax/group?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An object with search parameters as described in [[#GroupSearch | Group search]].<br />
<br />
{| id="GroupSearch" cellspacing="0" border="1"<br />
|+ align="bottom" | Group search<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find groups. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|}<br />
<br />
Response with timestamp: An array of group objects as described in [[#GroupData | Group data]].<br />
<br />
{| id="GroupData" cellspacing="0" border="1"<br />
|+ align="bottom" | Group data<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || ID<br />
|-<br />
| display_name || String || Display name<br />
|-<br />
| name || String || Name with character restrictions<br />
|-<br />
| members || Array || The array contains identifier of users that are member of the group.<br />
|}<br />
<br />
=== Create a group ===<br />
<br />
introduced 2008-06-12<br />
<br />
PUT <code>/ajax/group?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Group object as described in [[#GroupData | Group data]]. The field id is not present.<br />
<br />
Response: A json objekt with attribute <code>id</code> of the newly created group.<br />
<br />
=== Delete a group ===<br />
<br />
introduced 2008-06-12<br />
<br />
PUT <code>/ajax/group?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the group to delete.<br />
<br />
Request body: An object with the field “id” containing the unique identifier of the group.<br />
<br />
Response: An empty json array if the group was deleted successfully.<br />
<br />
=== Change a group ===<br />
<br />
introduced 2008-06-12<br />
<br />
PUT <code>/ajax/group?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the group to update.<br />
* <code>timestamp</code> – Time stamp of the group to update. If the group was modified after the specified time stamp, then the update must fail. <br />
<br />
Request body: Group object as described in [[#GroupData | Group data]]. Only modified fields are present and the field id is omitted.<br />
<br />
=== Get updates (since v6.18.1) ===<br />
<br />
introduced 2010-09-13<br />
<br />
GET <code>/ajax/group?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested groups.<br />
<br />
Response with timestamp: An array with new, modified and deleted groups. New, modified and deleted groups are represented by JSON objects as described in [[#GroupData | Group data]].<br />
<br />
== Module "resource" ==<br />
<br />
The resource module allows to query available resources. It is mainly used by the dialog for the selection of participants.<br />
<br />
=== Get all resources ===<br />
<br />
GET <code>/ajax/resource?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: An array of resource identifier.<br />
<br />
=== List resources ===<br />
<br />
PUT <code>/ajax/resource?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
<br />
Request body: An array with resources ids.<br />
<br />
Response: An array of resource objects as described in [[#ResourceResponse | Resource response]].<br />
<br />
=== Get a resource ===<br />
<br />
GET <code>/ajax/resource?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The resource id.<br />
<br />
Response: An array of resource objects as described in [[#ResourceResponse | Resource response]].<br />
<br />
=== Search for resources ===<br />
<br />
PUT <code>/ajax/resource?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An object with search parameters as described in [[#ParticipantSearch | Participant search]].<br />
<br />
{| id="ParticipantSearch" cellspacing="0" border="1"<br />
|+ align="bottom" | Participant search<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find resources. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|}<br />
<br />
Response: An array of resource objects as described in [[#ResourceResponse | Resource response]].<br />
<br />
{| id="ResourceResponse" cellspacing="0" border="1"<br />
|+ align="bottom" | Resource Response<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || ID<br />
|-<br />
| display_name || String || Display name<br />
|-<br />
| name || String || internal name<br />
|-<br />
| mailaddress || String || email address<br />
|-<br />
| availability || Boolean || can be false to mark the resource currently unavailable<br />
|-<br />
| description || String || description of the resource<br />
|-<br />
| last_modified || Time || Date and time of the last modification.<br />
|-<br />
| last_modified_utc || Timestamp || Date and time of the last modification.<br />
|}<br />
<br />
=== Create a resource ===<br />
<br />
PUT <code>/ajax/resource?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Resource object as described in [[#ResourceResponse | Resource response]]. The field id is not present.<br />
<br />
Response: An object with attribute <code>id</code> of the newly created resource.<br />
<br />
=== Delete a resource ===<br />
<br />
PUT <code>/ajax/resource?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the resource to delete.<br />
<br />
Request body: An object with the field “id” containing the unique identifier of the resource.<br />
<br />
Response: An empty json array if the resource was deleted successfully.<br />
<br />
=== Delete resources (since v6.22) ===<br />
<br />
PUT <code>/ajax/resource?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the resource to delete.<br />
<br />
Request body: An array of objects with the field “id” containing the unique identifier of the resource.<br />
<br />
Response: An empty json array if the resources were deleted successfully.<br />
<br />
=== Change a resource ===<br />
<br />
PUT <code>/ajax/resource?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the resource to update.<br />
* <code>timestamp</code> – Time stamp of the resource to update. If the resource was modified after the specified time stamp, then the update must fail. <br />
<br />
Request body: Resource object as described in [[#ResourceResponse | Resource response]]. Only modified fields are present and the field id is omitted.<br />
<br />
=== Get updates (since v6.18.1) ===<br />
<br />
introduced 2010-09-13<br />
<br />
GET <code>/ajax/resource?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested resources.<br />
<br />
Response with timestamp: An array with new, modified and deleted resources. New, modified and deleted resources are represented by JSON objects as described in [[#ResourceResponse | Resource response]].<br />
<br />
== Module "infostore" or "Filestore" or "Files" or "Drive" ==<br />
This module has been renamed quite often. Whatever its name, it combines the knowledge database, bookmarks and document storage.<br />
<br />
=== Get all infoitems ===<br />
<br />
GET <code>/ajax/infostore?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for infoitems are defined in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response with timestamp: An array with infoitem data. Each array element describes one infoitem and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedInfoitemData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed infoitem data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 700 || title || String || Title<br />
|-<br />
| 701 || url || String || Link/URL<br />
|-<br />
| 702 || filename || String || Displayed filename of the document.<br />
|-<br />
| 703 || file_mimetype || String || MIME type of the document. The client converts known types to more readable names before displaying them.<br />
|-<br />
| 704 || file_size || Number || Size of the document in bytes.<br />
|-<br />
| 705 || version || Number || Version number of the document. New documents start at 1. Every update increments the version by 1.<br />
|-<br />
| 706 || description || String || Description<br />
|-<br />
| 707 || locked_until || Time || The time until which this item will presumably be locked. Only set if the docment is currently locked, 0 otherwise.<br />
|-<br />
| 708 || file_md5sum || String || MD5Sum of the document. Not yet implemented, so this is currently always empty.<br />
|-<br />
| 709 || version_comment || String || A version comment is used to file a changelog for the file.<br />
|-<br />
| 710 || current_version || Boolean || “true” if this version is the current version “false” otherwise. . Note: This is not writeable<br />
|-<br />
| 711 || number_of_versions || Number || The number of all versions of the infoitem. Note: This is not writeable.<br />
|}<br />
<br />
=== Get a list of infoitems ===<br />
<br />
PUT <code>/ajax/infostore?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for infoitems are defined in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
<br />
Request body: An array with object IDs of requested infoitems.<br />
<br />
Response with timestamp: An array with infoitem data. Each array element describes one infoitem and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get updated infoitems ===<br />
<br />
GET <code>/ajax/infostore?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for infoitems are defined in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested infoitems.<br />
* <code>ignore</code> (optional) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
<br />
Response with timestamp: An array with new, modified and deleted infoitems. New and modified infoitems are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted infoitems (should the <code>ignore</code> parameter be ever implemented) would be identified by their object IDs as plain strings, without being part of a nested array.<br />
<br />
=== Get an infoitem ===<br />
<br />
GET <code>/ajax/infostore?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested infoitem.<br />
* <code>version</code> (optional) – If present the infoitem data describes the given version. Otherwise the current version is returned <br />
<br />
Response with timestamp: An object containing all data of the requested infoitem. The fields of the object are listed in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. The field id is not included.<br />
<br />
=== Search infoitems ===<br />
<br />
PUT <code>/ajax/infostore?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields as per tables [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>start</code> (optional) – The start index (inclusive) in the ordered search, that is requested.<br />
* <code>end</code> (optional) – The last index (inclusive) from the ordered search, that is requested.<br />
<br />
Request body: An Object as described in [[#SearchContacts | Search contacts]].<br />
<br />
=== Get an infoitem document ===<br />
<br />
GET <code>/ajax/infostore/[filename]?action=document</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested infoitem.<br />
* <code>folder</code> – Object ID of the infoitem's folder.<br />
* <code>version</code> (optional) – If present the infoitem data describes the given version. Otherwise the current version is returned <br />
* <code>content_type</code>(optional) – If present the response declares the given content_type in the Content-Type header.<br />
<br />
Response body: The raw byte data of the document. The response type for the HTTP Request is set accordingly to the defined mimetype for this infoitem or the content_type given.<br />
<br />
Note: The Filename may be added to the customary infostore path to suggest a filename to a Save-As dialog.<br />
<br />
=== Get all versions ===<br />
<br />
GET <code>/ajax/infostore?action=versions</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the infoitem whose versions are requested.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for infoitems are defined in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response with timestamp: An array with infoitem data. Each array element describes one infoitem and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. The timestamp is the timestamp relating to the requested infostore item.<br />
<br />
=== Get multiple documents as a ZIP archive (available with v7.4.0) ===<br />
<br />
GET <code>/ajax/infostore?action=zipdocuments</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>body</code> – A URL-encoded JSON array; see below for details<br />
<br />
Parameter <code>body</code>: A JSON array of JSON object tuples specifying the documents' versions to include in the requested ZIP archive; e.g<br><br />
<pre><br />
[{"id":"61820","folder":"70303"},{"id":"61821","folder":"70303", "version": "1"}]<br />
</pre><br />
The field <code>"version"</code> is optional; if missing it refers to latest/current version.<br><br />
So, a valid parameter would look like:<br />
<pre><br />
...&body=%5B%7B%22id%22%3A%2261820%22%2C%22folder%22%3A%2270303%22%7D%2C%7B%22id%22%3A%2261821%22%2C%22folder%22%3A%2270303%22%2C%22version%22%3A%221%22%7D%5D<br />
</pre><br />
<br />
Response: The download offer for the requested ZIP archive containing specified document versions<br />
<br />
=== Update an infoitem via PUT ===<br />
<br />
PUT <code>/ajax/infostore?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated infoitem.<br />
* <code>timestamp</code> – Timestamp of the updated infoitem. If the infoitem was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. Only modified fields are present.<br />
<br />
=== Update an infoitem via POST ===<br />
<br />
POST <code>/ajax/infostore?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated infoitem.<br />
* <code>timestamp</code> – Timestamp of the updated infoitem. If the infoitem was modified after the specified timestamp, then the update must fail.<br />
* <code>json</code> - Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. Only modified fields are present.<br />
* <code>file</code> – File Metadata as per <input type=”file” /><br />
<br />
Request Body: Body of content-type “multipart/form-data” or “multipart/mixed” containing the above mentioned fields and file-data.<br />
<br />
Response: The response is sent as a HTML document (see introduction).<br />
<br />
=== Create an infoitem via PUT ===<br />
<br />
PUT <code>/ajax/infostore?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. The field id is not included.<br />
<br />
Response: Object ID of the newly created infoitem.<br />
<br />
=== Create an infoitem via POST ===<br />
<br />
POST <code>/ajax/infostore?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>json</code> - Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. The field id is not included.<br />
* <code>file</code> – File metadata as per <input type=”file” /><br />
<br />
Request Body: Body of content-type “multipart/form-data” or “multipart/mixed” containing the above mentioned fields and file-data.<br />
<br />
Response: Object ID of the newly created infoitem. The response is sent as a HTML document (see introduction).<br />
<br />
=== Save an attachment in the infostore ===<br />
<br />
PUT <code>/ajax/infostore?action=saveAs</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>attached</code> – The Object ID of the Object with the attachment<br />
* <code>folder</code> – The Folder ID of the Object with the attachment<br />
* <code>module</code> – The Module type of the Object with the attachment.<br />
* <code>Attachment</code> – The id of the attachement to save.<br />
<br />
Request body: Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. The field id is not included. The fields in this infoitem object override values from the attachment. The folder_id must be given.<br />
<br />
Response: Object ID of the newly created infoitem.<br />
<br />
=== Delete infoitems ===<br />
<br />
PUT <code>/ajax/infostore?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>timestamp</code> – Timestamp of the last update of the deleted infoitems.<br />
<br />
Request body: An array with objects to delete. The fields for the object are described in [[#FullIdentifierForAnInfostoreDocument|Full identifier for an infostore document]].<br />
<br />
Response: An array with [[]]. <br />
<br />
{| id="FullIdentifierForAnInfostoreDocument" cellspacing="0" border="1"<br />
|+ align="bottom" | Full identifier for an infostore document<br />
! Name !! Type !! Value<br />
|-<br />
| id || Number || Object ID<br />
|-<br />
| folder || Number || Folder ID<br />
|}<br />
<br />
=== Delete versions of infostore documents ===<br />
<br />
PUT <code>/ajax/infostore?action=detach</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the base Object<br />
* <code>folder</code> – The Folder of the Object<br />
* <code>timestamp</code> - Timestamp of the infostore object<br />
<br />
Request body: A List of arrays with the version numbers of the infoitems to detach.<br />
<br />
Response: An array with version numbers that were not deleted.<br />
<br />
Note: When the current version of a document is deleted the new current version will be the newest version.<br />
<br />
=== Delete all versions of infostore documents ===<br />
<br />
PUT <code>/ajax/infostore?action=revert</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the base Object<br />
* <code>folder</code> – The Folder of the Object<br />
* <code>timestamp</code> - Timestamp of the infostore object<br />
<br />
Removes all versions of the infostore document leaving only the base object.<br />
<br />
=== Copy an infostore document via PUT ===<br />
<br />
PUT <code>/ajax/infostore?action=copy</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the base Object<br />
* <code>folder</code> – The Folder of the Object<br />
* <code>timestamp</code> - Timestamp of the infostore object<br />
<br />
Request body: Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. Only modified fields are present.<br />
<br />
Response: The id of the newly created object<br />
<br />
Note: Only the fields (and the file) of the current document will be copied. Those fields present in the request are modified accordingly.<br />
<br />
=== Copy an infostore document via POST ===<br />
<br />
POST <code>/ajax/infostore?action=copy</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated infoitem.<br />
* <code>timestamp</code> – Timestamp of the updated infoitem. If the infoitem was modified after the specified timestamp, then the update must fail.<br />
* <code>json</code> - Infoitem object as described in [[#CommonObjectData | Common object data]] and [[#DetailedInfoitemData | Detailed infoitem data]]. Only modified fields are present.<br />
* <code>file</code> – File Metadata as per <input type=”file” /><br />
<br />
Request Body: Body of content-type “multipart/form-data” or “multipart/mixed” containing the above mentioned fields and file-data.<br />
<br />
Response: The response is sent as a HTML document (see introduction).<br />
<br />
Note: Only the fields (and the file) of the current document will be copied. Those fields present in the request are modified accordingly.<br />
<br />
=== Lock an infoitem ===<br />
<br />
GET <code>/ajax/infostore?action=lock</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the infoitem that should be locked.<br />
* <code>diff</code> (optional) – If present the value is added to the current time on the server (both in ms). The document will be locked until that time. If this parameter is not present, the document will be locked for a duration as configured on the server.<br />
<br />
Response with timestamp: Can only include errors.<br />
<br />
=== Unlock an infoitem ===<br />
<br />
GET <code>/ajax/infostore?action=unlock</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the infoitem that should be unlocked.<br />
<br />
Response with timestamp: Can only contain errors.<br />
<br />
== Module "Links" (deprecated) ==<br />
<br />
The link module provides the ability to connect two objects from any module. <br />
<br />
=== Get All Links from an Object ===<br />
<br />
GET <code>/ajax/link?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The Object ID of the Object<br />
* <code>folder</code> – The Folder ID of the Object<br />
* <code>module</code> – The Module type of the Object<br />
<br />
Response: An Array with all Links ([[#LinkObject | Link object]]) from the given Object ID.<br />
<br />
=== Create a Link ===<br />
<br />
PUT <code>/ajax/link?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: Link object as described in [[#LinkObject | Link object]].<br />
<br />
Response: An OK.<br />
<br />
{| id="LinkObject" cellspacing="0" border="1"<br />
|+ align="bottom" | Link Object<br />
! Field !! Name !! Type !! Description<br />
|-<br />
| First Object ID || id1 || Number || The ID of the first Object you want to start to link<br />
|-<br />
| First Module Type || module1 || Number || The Module of this Object Possible Values:<br />
{| cellspacing="0" border="1"<br />
| 1 || Appointment<br />
|-<br />
| 4 || Task<br />
|-<br />
| 7 || Contact<br />
|-<br />
| 13 || Project<br />
|-<br />
| 17 || Forum<br />
|-<br />
| 18 || Pin board<br />
|-<br />
| 19 || Email<br />
|-<br />
| 137 || Infostore<br />
|}<br />
|-<br />
| First Folder ID || folder1 || String || The Folder of this Object<br />
|-<br />
| Second Object ID || id2 || Number || The ID of the second Object you want to link the first Object with<br />
|-<br />
| Second Module Type || module2 || Number || The Module of the second Object<br />
Possible Values:<br />
{| cellspacing="0" border="1"<br />
| 1 || Appointment<br />
|-<br />
| 4 || Task<br />
|-<br />
| 7 || Contact<br />
|-<br />
| 13 || Project<br />
|-<br />
| 17 || Forum<br />
|-<br />
| 18 || Pin board<br />
|-<br />
| 19 || Email<br />
|-<br />
| 137 || Infostore<br />
|}<br />
|-<br />
| Second Folder ID || folder2 || String || The Folder of the second Object<br />
|}<br />
<br />
=== Delete Link ===<br />
<br />
PUT <code>/ajax/link?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the base Object<br />
* <code>module</code> – The type of the Object<br />
* <code>folder</code> – The Folder of the Object<br />
<br />
Request body: A List of arrays with the information of the Links to delete which looks like [[#DeleteObject | Delete object]].<br />
<br />
Response: A List of arrays with object Ids of links which are not readable by the user and were therefore not deleted. See [[#DeleteObject | Delete object]].<br />
<br />
{| id="DeleteObject" cellspacing="0" border="1"<br />
|+ align="bottom" | Delete Object<br />
! Field !! Type !! Array Position<br />
|-<br />
| Object id || Number || 0<br />
|-<br />
| Module || Number || 1<br />
|-<br />
| Folder || String || 2<br />
|}<br />
<br />
== Module "Attachments" ==<br />
<br />
The Attachment Module allows file attachments to arbitrary objects. Object addresses are defined analogous to the Link module. An Attachment always belongs to an object (called 'attached') in a certain folder of a certain module. <br />
<br />
=== Get All Attachments for an Object ===<br />
<br />
GET <code>/ajax/attachment?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>attached</code> – The Object ID of the Object<br />
* <code>folder</code> – The Folder ID of the Object<br />
* <code>module</code> – The Module type of the Object<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for attachment's are defined in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response: An array with attachment data. Each array element describes one attachment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a list of attachments ===<br />
<br />
PUT <code>/ajax/attachment?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for attachments are defined in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]].<br />
* <code>attached</code> – The Object ID of the Object<br />
* <code>folder</code> – The Folder ID of the Object<br />
* <code>module</code> – The Module type of the Object<br />
<br />
Request body: An array of with object IDs of requested tasks.<br />
<br />
Response with timestamp: An array with attachment data. Each array element describes one attachment and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Create an Attachment ===<br />
<br />
POST <code>/ajax/attachment?action=attach</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>json_[index]</code> – The JSON representation of an attachment object as described in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]].<br />
* <code>file_[index]</code> – The file metadata as per <input type=file /> upload.<br />
<br />
Note: The JSON Object and file fields describe the corresponding attachment. For ex.: json_0 contains metadata for file_0, json_1 for file_1 and so on. Indexes start with 0.<br />
<br />
Request body: multipart/form-data or multipart/mixed containing the file data of the attached file and the above fields.<br />
<br />
Response: HTML page with javascript callback as per introduction. Contains a JSON-Array of ids of the newly created attachments. The order of the ids corresponds to the indexes in the request.<br />
<br />
{| id="AttachmentObject" cellspacing="0" border="1"<br />
|+ align="bottom" | Attachment Object<br />
! ID !! Name !! Type !! Description<br />
|-<br />
| 800 || folder || Number || The ID of the first Folder in which the attached object resides.<br />
|-<br />
| 801 || attached || Number || The object id of the object this attachement is attached to.<br />
|-<br />
| 802 || module || Number || The Module of this Object Possible Values:<br />
{| cellspacing="0" border="1"<br />
| 1 || Appointment<br />
|-<br />
| 4 || Task<br />
|-<br />
| 7 || Contact<br />
|-<br />
| 137 || Infostore<br />
|}<br />
|-<br />
| 803 || filename || String || The filename of the attached file.<br />
|-<br />
| 804 || file_size || Number || The file size (in bytes) of the attached file.<br />
|-<br />
| 805 || file_mimetype || String || The MIME-Type of the attached file<br />
|-<br />
| 806 || rft_flag || Boolean || If the attachment is a RTF Attachment of Outlook. (Outlook descriptions can be stored as RTF Documents).<br />
|}<br />
<br />
=== Delete Attachment ===<br />
<br />
PUT <code>/ajax/attachment?action=detach</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>attached</code> – The ID of the base Object<br />
* <code>module</code> – The type of the Object<br />
* <code>folder</code> – The Folder of the Object<br />
<br />
Request body: An array with the ids of the attachments to delete.<br />
<br />
=== Get updated attachments ===<br />
<br />
GET <code>/ajax/attachment?action=updates</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>attached</code> – Object ID of the object to which the attachments are attached.<br />
* <code>module</code> – Module ID (as per [[#AttachmentObject | Attachment object]]) of the attached object.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for attachments are defined in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
* <code>timestamp</code> – Timestamp of the last update of the requested infoitems.<br />
ignore (optional) – Which kinds of updates should be ignored. Currently, the only valid value – "deleted" – causes deleted object IDs not to be returned.<br />
<br />
Response with timestamp: An array with new and deleted attachments for the specified object. New attachments are represented by arrays. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter. Deleted attachments (should the <code>ignore</code> parameter be ever implemented) would be identified by their object IDs as plain numbers, without being part of a nested array.<br />
<br />
=== Get an attachment ===<br />
<br />
GET <code>/ajax/attahment?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>attached</code> – Object ID of the object to which the attachments are attached.<br />
* <code>module</code> – Module ID (as per [[#AttachmentObject | Attachment object]]) of the attached object.<br />
* <code>id</code> – Object ID of the requested attachment.<br />
<br />
Response with timestamp: An object containing all data of the requested attachment. The fields of the object are listed in [[#CommonObjectData | Common object data]] (with only id, created_by and creation_date available) and [[#AttachmentObject | Attachment object]]. <br />
<br />
=== Get an attachments filedata ===<br />
<br />
GET <code>/ajax/attachment/[filename]?action=document</code><br />
<br />
Parameters:<br />
<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – Object ID of the folder, whose contents are queried.<br />
* <code>attached</code> – Object ID of the object to which the attachments are attached.<br />
* <code>module</code> – Module ID (as per [[#AttachmentObject | Attachment object]]) of the attached object.<br />
* <code>id</code> – Object ID of the requested attachment.<br />
* <code>content_type</code> (optional) – If set the responses Content-Type header is set to this value, not the attachements file mime type.<br />
<br />
Response body: The raw byte data of the document. The response type for the HTTP Request is set accordingly to the defined mimetype for this infoitem.<br />
Note: The Filename may be added to the customary infostore path to suggest a filename to a Save-As dialog.<br />
<br />
== Module "reminder" ==<br />
<br />
The reminder module provides the ability to fetch all active reminders for a user between two dates.<br />
<br />
=== Get reminder range ===<br />
<br />
GET <code>/ajax/reminder?action=range</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>end</code> – The End date of the reminder range<br />
<br />
Response: An Array with all reminders which are scheduled until the specified time. Each reminder is described in [[#ReminderResponse | Reminder response]].<br />
<br />
{| id="ReminderResponse" cellspacing="0" border="1"<br />
|+ align="bottom" | Reminder response<br />
! Field !! Type !! Description<br />
|-<br />
| id || Number || The ID of the reminder.<br />
|-<br />
| target_id || Number || The target_id where this reminder is attached to<br />
|-<br />
| alarm || Time || The time of the alarm<br />
|-<br />
| module || Number || The module of the reminder<br />
|-<br />
| servertime || Time || The time on the server<br />
|-<br />
| user_id || Number || The ID of the user.<br />
|-<br />
| last_modified || Time || The last modification timestamp of the reminder<br />
|-<br />
| recurrence_position || Number || The recurrence position for series appointments or 0 if no series<br />
|-<br />
| folder || Number || The ID of the folder through that the object can be read<br />
|-<br />
|}<br />
<br />
=== Delete a Reminder===<br />
<br />
PUT <code>/ajax/reminder?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An object with the field “id”.<br />
<br />
Response body: An JSON array with the id that was not deleted.<br />
<br />
=== Delete Reminders (since v6.22)===<br />
<br />
PUT <code>/ajax/reminder?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An array of objects with the field “id”.<br />
<br />
Response body: An JSON array with the ids that were not deleted.<br />
<br />
=== Remind again (since v6.18.1) ===<br />
<br />
PUT <code>/ajax/reminder?action=remindAgain</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the reminder whose date shall be changed.<br />
<br />
Request body: The JSON representation of the reminder; mainly containing the field “alarm” which provides the new reminder date.<br><br />
E.g. <code>{ "alarm": 1283418027381 }</code><br />
<br />
Response body: The JSON representation of the updated reminder.<br />
<br />
== Module "multiple" ==<br />
<br />
The multiple module allows to bundle multiple requests to most other modules in a single request. Not supported are:<br />
* modules login and multiple,<br />
* POST requests with a multipart encoding (uploads),<br />
* GET requests which do not use an object as described in [[#ResponseBody | Response body]] as response body (downloads).<br />
<br />
=== Multiple requests ===<br />
<br />
PUT <code>/ajax/multiple</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>continue</code> – Specifies whether processing of requests should stop when an error occurs, or whether all request should be processed regardless of errors.<br />
<br />
Request body: An array with request objects. Each request object contains all URI parameters of the "normal" request as fields. The module name of the "normal" request is included in the field module. The parameter session is not included. If the "normal" request has a request body, the object which is represented by that request body is includes as the value of the field data.<br />
<br />
Response: An array with reply objects as described in [[#ResponseBody | Response body]]. The order of reply objects corresponds to the order of requests in the request body. Unlike with all other modules, this response is itself not part of a response object as described in [[#ResponseBody | Response body]].<br />
<br />
== Module "quota" ==<br />
<br />
The filestore module allows accesssing information about the use and quota of the filestore.<br />
<br />
=== Get the filestore usage data ===<br />
<br />
GET <code>/ajax/quota?action=filestore</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: A JSON Object containing the fields “use” and “quota”. “use” represents the uploaded files sizes sum and the field “quota” represents the maximum.<br />
<br />
=== Get the mail usage data ===<br />
<br />
GET <code>/ajax/quota?action=mail</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: A JSON Object containing the fields “use” and “quota”. “use” represents the use mail quota and the field “quota” represents the maximum. -1 represents an unlimited quota.<br />
<br />
<br />
== Module "import"==<br />
The module import allows to import specific module data (like Contacts, Tasks or Appointments) in several formats (iCal, vCard, CSV) into a folder. Please note: The callback for all actions of this bundle is callback_import, not callback_$actionname for legacy purposes.<br />
<br />
=== Import CSV ===<br />
POST <code>/ajax/import?action=CSV</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder into which data should be imported. This must be a Contact folder.<br />
<br />
Request body: A "multipart/form-data" encoded .CSV file. The field name for the file is "file". The column titles of the table are those used within the OX, see column ''Displayed Name'' in [[#DetailedContactData]].<br />
<br />
Response: An array of JSON-Objects, one for each entry in the list, containing: The Object ID of the entry, the Object ID of the folder the data was written into, a timestamp of the modification (in case of error, of modification attempt) and an error in case the data could not be entered.<br />
<br />
=== Import Outlook CSV ===<br />
POST <code>/ajax/import?action=OUTLOOK_CSV</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder into which data should be imported. This must be a Contact folder.<br />
<br />
Request body: An .CSV file with Windows' default encoding Windows-1252. The column titles of the table may be those used by the English, French or German version of Outlook.<br />
<br />
Response: An array of JSON-Objects, one for each entry in the list, containing: The Object ID of the entry, the Object ID of the folder the data was written into, a timestamp of the modification (in case of error, of modification attempt) and an error in case the data could not be entered.<br />
<br />
=== Import iCAL ===<br />
POST <code>/ajax/import?action=ICAL</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder into which data should be imported. This may be an Appointment or a Task folder. May even be a list containing both.<br />
* <code>suppressNotification</code> – This optional parameter can be used to disable the notifications for new appointments that are imported through the given iCal file. This help keeping the Inbox clean if a lot of appointments need to be imported. The value of this parameter does not matter because only for the existence of the parameter is checked.<br />
* <code>ignoreUIDs</code> – Optional. When set to "true", UIDs are partially ignored during import of tasks and appointments from iCal. Internally, each UID is replaced statically by a random one to preserve possibly existing relations between recurring appointments in the same iCal file, but at the same time to avoid collisions with already existing tasks and appointments.<br />
<br />
Request body: An iCalendar file.<br />
<br />
Response: An array of JSON-Objects, one for each entry in the list, containing: The Object ID of the entry, the Object ID of the folder the data was written into, a timestamp of the modification (in case of error, of modification attempt) and an error in case the data could not be entered, and warnings (under the key "warnings") containing an Array of objects with the warning data, containing all customary error fields.<br />
<br />
=== Import vCard ===<br />
POST <code>/ajax/import?action=VCARD</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder into which data should be imported. This must be a Contact folder.<br />
<br />
Request body: An vCard file, maybe of the formats: vCard 2.1, vCard 3.0 or vCalendar 1.0<br />
<br />
Response: An array of JSON-Objects, one for each entry in the list, containing: The Object ID of the entry, the Object ID of the folder the data was written into, a timestamp of the modification (in case of error, of modification attempt) and an error in case the data could not be entered.<br />
<br />
== Module "export" ==<br />
The module export allows to export specific module data (like Contacts, Tasks or Appointments) from a folder in several formats (iCal, vCard, CSV).<br />
<br />
=== Exporting CSV ===<br />
GET <code>/ajax/export?action=CSV</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder whose contents are to be exported. This must be a Contact folder.<br />
* <code>columns</code> – (optional) Columns to be imported from the given file, given as an array of column numbers. See [[#DetailedContactData | Detailed contact data]] for numbers.<br />
* <code>export_dlists</code> – (optional) toggles whether distribution lists are exported, too. Default is false. Option exists since 7.4.1.<br />
Response: An InputStream containing the file of the MIME type <code>text/csv</code>.<br />
<br />
=== Exporting iCAL ===<br />
GET <code>/ajax/export?action=ICAL</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder whose contents are to be exported. This must be a Calendar folder.<br />
<br />
Response: An InputStream containing the file, of the MIME type <code>text/calendar</code>.<br />
<br />
=== Exporting vCard ===<br />
GET <code>/ajax/export?action=VCARD</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>folder</code> – ObjectID of the folder whose contents are to be exported. This must be a Contact folder.<br />
<br />
Response: An InputStream containing the file, of the MIME type <code>text/x-vcard</code>.<br />
<br />
== Module "sync" ==<br />
The module sync delivers several core API extensions to support common operations used in a mobile synchronization environment.<br />
<br />
=== Clearing a folder's content ===<br />
PUT <code>/ajax/sync?action=refresh_server</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON array containing the folder ID(s) whose content should be cleared. '''NOTE:''' Although the requests offers to clear multiple folders at once it is recommended to clear only one folder per request since if any exception occurs<br />
(e.g. missing permissions) the complete request is going to be aborted.<br />
<br />
Response: A JSON array containing the IDs of folders that could not be cleared due to a concurrent modification. Meaning you receive an empty JSON array if everything worked well.<br />
<br />
== Module "token" (since 7.4.0) ==<br />
The module token delivers several core API extensions to support token based logins.<br />
<br />
=== Get a login token ===<br />
GET <code>/ajax/token?action=acquireToken</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response:<br />
A JSON object with the timestamp of the creation date and a token which can be used to create a new session.<br />
<br />
== Module "mailfilter" ==<br />
The module mailfilter describes how to add, update or delete mail filter rules or to check which actions are supported by the underlying system.<br />
<br />
A detailed description can be found here [[ HTTP_API_MailFilter | Mail Filter HTTP API]]<br />
<br />
== Module "ajax file upload" ==<br />
This module offers to store files in server's dedicated download directory for a configureable amount of time. The files are then accessible for further operations like inline images in (html) mails<br />
<br />
=== Uploading a file ===<br />
POST <code>/ajax/file?action=new</code> <br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>module</code> – The module for which the file is uploaded to determine proper upload quota constraints (e.g. "mail", "infostore", etc.).<br />
* <code>type</code> – The file type filter to define which file types are allowed during upload. Currently supported filters are: <code>file=all, text=text/*, media=image OR audio OR video, image=image/*, audio=audio/*, video=video/*, application=application/*</code><br />
<br />
Request body: A common POST request body of MIME type "multipart/*" which holds the file(s) to upload<br />
<br />
Response: A JSON array containing the IDs of the uploaded files. The files are accessible through the returned IDs for future use.<br />
<br />
=== Updating a file's last access timestamp (keep alive) ===<br />
By updating the last access timestamp it's prevented from being deleted from both session and disk storage.<br />
<br />
GET <code>/ajax/file?action=keepalive</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the uploaded file whose timestamp should be updated<br />
<br />
Response: The string "null" in response's data element<br />
<br />
=== Requesting a formerly uploaded file ===<br />
GET <code>/ajax/file?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the uploaded file<br />
<br />
Response: The content of the requested file is directly written into output stream<br />
<br />
== Module "image" ==<br />
This module allows to download images from Open-Xchange server without providing a session ID in request's URL parameters.<br />
<br />
=== Requesting an image ===<br />
GET <code>/ajax/image</code> <br />
<br />
Parameters:<br />
* <code>uid</code> – The unique ID referring to the desired image<br />
<br />
Response: The content of the requested image is directly written into output stream<br />
<br />
== Module "conversion" (preliminary) ==<br />
<br />
A generic module to request data from a data source and to process obtained/submitted data with a data handler. Thus data is converted from a data source by a data handler.<br />
<br />
=== Converting data ===<br />
PUT <code>/ajax/conversion?action=convert</code><br><br />
or<br><br />
POST <code>/ajax/conversion?action=convert</code> <br />
<br />
Parameters: &lt;no parameters required&gt;<br />
<br />
Request body: A [[#ConversionRequest | conversion request]] JSON object containing nested JSON objects for [[#DataSource | data source]] and [[#DataHandler | data handler]]<br />
<br />
<br />
{| id="ConversionRequest" cellspacing="0" border="1"<br />
|+ align="bottom" | Conversion request object<br />
! Field !! Type !! Description<br />
|-<br />
| datasource || JSON object || The data source object.<br />
|-<br />
| datahandler || JSON object || The data handler object.<br />
|-<br />
|}<br />
<br />
<br />
{| id="DataSource" cellspacing="0" border="1"<br />
|+ align="bottom" | Data source object<br />
! Field !! Type !! Description<br />
|-<br />
| identifier || String || The identifier of the data source.<br />
|-<br />
| args || JSON array or JSON object || The '''optional''' name-value-pairs as a single JSON object or a JSON object for each kept inside a JSON array for data source<br />
|-<br />
|}<br />
<br />
<br />
{| id="DataHandler" cellspacing="0" border="1"<br />
|+ align="bottom" | Data handler object<br />
! Field !! Type !! Description<br />
|-<br />
| identifier || String || The identifier of the data handler.<br />
|-<br />
| args || JSON array or JSON object || The '''optional''' name-value-pairs as a single JSON object or a JSON object for each kept inside a JSON array for data handler<br />
|-<br />
|}<br />
<br />
Response: The result of converted data ready as an appropriate JSON response<br />
<br />
==== Saving an ICal email attachment ====<br />
<br />
If an ICal file is attached to an email, its content can be saved as appointments and tasks into given calendar and task folder.<br />
If the fields "com.openexchange.groupware.calendar.confirmstatus" and "com.openexchange.groupware.calendar.confirmmessage" are set, the data handler inserts the appointment with the given status for the user, if the appointment does not exist. If it is already existing, the handler just updates the participant status.<br />
<br />
Data source's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.mail.ical&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.fullname&quot;:&quot;&lt;folder-fullname&gt;&quot;},<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.mailid&quot;:&quot;&lt;mail-id&gt;&quot;},<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.sequenceid&quot;:&quot;&lt;attachment-sequence-id&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Data handler's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.ical&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.groupware.calendar.folder&quot;:&quot;&lt;calendar-folder-id&gt;&quot;},<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.task.folder&quot;:&quot;&lt;task-folder-id&gt;&quot;},<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.calendar.confirmstatus&quot;:&quot;&lt;status&gt;&quot;},<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.calendar.confirmmessage&quot;:&quot;&lt;message&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Response: A JSON array of JSON objects each providing folder and object ID of added appointment/task; e.g. <code>[{&quot;folder_id&quot;:2567, &quot;id&quot;:7689}, ...]</code><br />
<br />
==== Converting an ICal email attachment into JSON objects ====<br />
<br />
If an ICal file is attached to an email, its content can converted to JSON appointments and tasks.<br />
<br />
Data source's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.mail.ical&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.fullname&quot;:&quot;&lt;folder-fullname&gt;&quot;}<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.mailid&quot;:&quot;&lt;mail-id&gt;&quot;}<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.sequenceid&quot;:&quot;&lt;attachment-sequence-id&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Data handler's JSON object.<br><br />
'''Note''' that all arguments are optional: Default is user time zone and zero recurrence position<br><br />
"com.openexchange.groupware.calendar.searchobject" triggers a search for the uid, and replaces the object_id and folder_id with the data of the corresponding ox-object id, if existing. The returned objects are still the ical objects and NOT the ox-objects.<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.ical.json&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.groupware.calendar.timezone&quot;:&quot;&lt;timezone-id&gt;&quot;}<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.calendar.recurrencePosition&quot;:&quot;&lt;recurrence-position&gt;&quot;}<br><br />
&nbsp;&nbsp;<br />
{&quot;com.openexchange.groupware.calendar.searchobject&quot;:&quot;&lt;true|false&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Response: A JSON array of JSON objects for each appointment/task as described in [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]] and [[##DetailedTaskData | Detailed task data]]/[[##DetailedAppointmentData | Detailed appointment data]]<br />
<br />
==== Saving a VCard email attachment ====<br />
<br />
If a VCard file is attached to an email, its content can be saved as contacts into given contact folder.<br />
<br />
Data source's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.mail.vcard&quot;,<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.fullname&quot;:&quot;&lt;folder-fullname&gt;&quot;},<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.mailid&quot;:&quot;&lt;mail-id&gt;&quot;},<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.mail.conversion.sequenceid&quot;:&quot;&lt;attachment-sequence-id&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Data handler's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.contact&quot;,<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;com.openexchange.groupware.contact.folder&quot;:&quot;&lt;contact-folder-id&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Response: A JSON array of JSON objects each providing folder and object ID of added contact; e.g. <code>[{&quot;folder_id&quot;:2567, &quot;id&quot;:7689}, ...]</code><br />
<br />
==== Contact(s) attached to a new email as a VCard file ====<br />
<br />
Obtain VCard data from specified contact object(s).<br />
<br />
Data source's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.contact&quot;<br><br />
&nbsp;&quot;args&quot;:<br><br />
&nbsp;&nbsp;[<br><br />
&nbsp;&nbsp;&nbsp;{&quot;folder&quot;:&quot;&lt;folder-id1&gt;&quot;,&quot;id&quot;:&quot;&lt;id1&gt;&quot;}<br><br />
&nbsp;&nbsp;&nbsp;...<br><br />
&nbsp;&nbsp;&nbsp;{&quot;folder&quot;:&quot;&lt;folder-idn&gt;&quot;,&quot;id&quot;:&quot;&lt;idn&gt;&quot;}<br><br />
&nbsp;&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
Get a new email's JSON object with specified VCard data source attached.<br />
<br />
Data handler's JSON object<br><br />
<code><br />
{<br><br />
&nbsp;&quot;identifier&quot;:&quot;com.openexchange.mail.vcard&quot;<br><br />
&nbsp;&quot;args&quot;:[]<br><br />
}<br><br />
</code><br />
<br />
Response: A [[#DetailedMailData | mail]] JSON object.<br />
<br />
== Module "search" (preliminary) ==<br />
<br />
The search module is an enhancement to each search request as an optional JSON object via PUT method to filter elements; e.g.<br />
<br />
<code><br />
PUT /ajax/contacts?action=all&...<br />
<br />
{"filter":{search-term-object}}<br />
</code><br />
<br />
This section describes the syntax of the optional JSON object representing the search term.<br><br />
In general the structure of a search term is in prefix notation; meaning the operator is written before its operands:<br />
<br />
<code>{"operation":"equals","operands":[...]}</code><br />
<br />
Moreover there are two different types of a search terms:<br />
* A single search term<br />
* A composite search term<br />
<br />
A single search term reflects an operation which cannot hold nested search terms as operands; e.g. "equals". In opposite to this a composite search term holds one or more nested search terms as operands; e.g. "not" or the logical junctors "and"/"or".<br />
<br />
By now the following operations are supported:<br />
* composite operations<br />
** "and" - The AND junctor<br />
** "or" - The OR junctor<br />
** "not" - Negation<br />
* single operations<br />
** "equals" - Equals comparison<br />
** "lt" - Less-than comparison<br />
** "gt" - Greater-than comparison<br />
<br />
Furthermore following operand types are supported for single search terms:<br />
* Column - Providing a name referring to a field/column<br />
* Constant - A constant<br />
<br />
Example of an EQUALS search term:<br><br />
<code><br />
{"operation":"equals","operands":[{"type":"column","value":"first_name"},"Jane"]}<br />
</code><br />
<br />
Example of an OR search term:<br><br />
<code><br />
{"operation":"or","operands":<br><br />
&nbsp;[<br><br />
&nbsp;&nbsp;{"operation":"equals","operands":[{"type":"column","value":"first_name"},"Jane"]},<br><br />
&nbsp;&nbsp;{"operation":"gt","operands":[{"type":"column","value":"birthday"},"1975-05-01"]}<br><br />
&nbsp;]<br><br />
}<br><br />
</code><br />
<br />
<br />
Refer to object data tables introduced by different modules to know which field names are supported; e.g. for tasks it is [[#CommonObjectData | Common object data]], [[#DetailedTaskAndAppointmentData | Detailed task and appointment data]], and [[#DetailedTaskData | Detailed task data]].<br />
<br />
== Module "search" (alternative suggestion, still preliminary) ==<br />
<br />
The search module is an enhancement to each search request as an optional JSON object via PUT method to filter elements; e.g.<br />
<br />
<code><br />
PUT /ajax/contacts?action=all&...<br />
<br />
{"filter":<i>[search term]</i>}<br />
</code><br />
<br />
This section describes the syntax of the optional JSON object representing the search term.<br />
In general the structure of a search term is in prefix notation; meaning the operator is written before its operands:<br />
<br />
<code>[">", 5, 2]</code><br />
<br />
The available operators are:<br />
* Comparison operators ">", "<", "=", "<=", ">=", "<>"<br />
* logic operators "not", "and", "or"<br />
<br />
Comparison operators have exactly two operands. Each operand can be either a field name or a constant. A field name is an object with the member "field" specifying the field name, e.g. <code>{ field: "first_name" }</code>. The available field names depend on the searched module. Primitive JSON types are interpreted as constants. Arrays are not valid operands for comparison operators.<br />
<br />
The logic operator "not" has exactly one operand, the other logic operators can have any number of operands. Each operand must be an array representing a nested search expression.<br />
<br />
== Module "mail account" (available with v6.12) ==<br />
<br />
The mail account module is used to manage multiple mail accounts held by a user.<br />
<br />
=== Get All mail accounts ===<br />
<br />
GET <code>/ajax/account?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for mail account's are defined in [[#MailAccountData | mail account data]].<br />
<br />
Response: An array with attachment data. Each array element describes one mail account and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a mail account ===<br />
<br />
GET <code>/ajax/account?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The ID of the account to return.<br />
<br />
Response: A JSON object representing the desired mail account. See [[#MailAccountData | mail account data]].<br />
<br />
{| id="MailAccountData" cellspacing="0" border="1"<br />
|+ align="bottom" | Mail account data<br />
! ID !! Name !! Type !! Value<br />
|-<br />
| 1001 || id || Number || Account ID<br />
|-<br />
| 1002 || login || String || The login.<br />
|-<br />
| 1003 || password || String || The (optional) password.<br />
|-<br />
| 1004 || mail_url || String || The mail server URL; e.g. "imap://imap.somewhere.com:143". '''URL is preferred over single fields''' (like mail_server, mail_port, etc.)<br />
|-<br />
| 1005 || transport_url || String || The transport server URL; e.g. "smtp://smtp.somewhere.com:25". '''URL is preferred over single fields''' (like transport_server, transport_port, etc.)<br />
|-<br />
| 1006 || name || String || Account's display name.<br />
|-<br />
| 1007 || primary_address || String || User's primary address in account; e.g. "someone@somewhere.com"<br />
|-<br />
| 1008 || spam_handler || String || The name of the spam handler used by account.<br />
|-<br />
| 1009 || trash || String || The name of the default trash folder.<br />
|-<br />
| 1010 || sent || String || The name of the default sent folder.<br />
|-<br />
| 1011 || drafts || String || The name of the default drafts folder.<br />
|-<br />
| 1012 || spam || String || The name of the default spam folder.<br />
|-<br />
| 1013 || confirmed_spam || String || The name of the default confirmed-spam folder.<br />
|-<br />
| 1014 || confirmed_ham || String || The name of the default confirmed-ham folder.<br />
|-<br />
| 1015 || mail_server || String || The mail server's hostname or IP address.<br />
|-<br />
| 1016 || mail_port || Number || The mail server's port.<br />
|-<br />
| 1017 || mail_protocol || String || The mail server's protocol. '''Always use basic protocol name.''' E.g. use "imap" instead of "imaps"<br />
|-<br />
| 1018 || mail_secure || Boolean || Whether to establish a secure connection to mail server (SSL, TLS).<br />
|-<br />
| 1019 || transport_server || String || The transport server's hostname or IP address.<br />
|-<br />
| 1020 || transport_port || Number || The transport server's port.<br />
|-<br />
| 1021 || transport_protocol || String || The transport server's protocol. '''Always use basic protocol name.''' E.g. use "smtp" instead of "smtps"<br />
|-<br />
| 1022 || transport_secure || Boolean || Whether to establish a secure connection to transport server (SSL, TLS).<br />
|-<br />
| 1023 || transport_login || String || The transport login. If empty "login" is taken as transport login as well.<br />
|-<br />
| 1024 || transport_password || String || The transport password. If empty "password" is taken as transport password as well.<br />
|-<br />
| 1025 || unified_inbox_enabled || Boolean || If enabled for Unified INBOX<br />
|-<br />
| 1026 || trash_fullname || String || Path to default trash folder. Preferred over "trash"<br />
|-<br />
| 1027 || sent_fullname || String || Path to default sent folder. Preferred over "sent"<br />
|-<br />
| 1028 || drafts_fullname || String || Path to default drafts folder. Preferred over "drafts"<br />
|-<br />
| 1029 || spam_fullname || String || Path to default spam folder. Preferred over "spam"<br />
|-<br />
| 1030 || confirmed_spam_fullname || String || Path to default confirmed-spam folder. Preferred over "confirmed_spam"<br />
|-<br />
| 1031 || confirmed_ham_fullname || String || Path to default confirmed-ham folder. Preferred over "confirmed_ham"<br />
|-<br />
| 1032 || pop3_refresh_rate || Number || The interval in minutes the POP3 account is refreshed<br />
|-<br />
| 1033 || pop3_expunge_on_quit || Boolean || Whether POP3 messages shall be deleted on actual POP3 account after retrieval or not<br />
|-<br />
| 1034 || pop3_delete_write_through || Boolean || If option "pop3_expunge_on_quit" is disabled, this property defines whether a delete in local INBOX also deletes affected message in actual POP3 account<br />
|-<br />
| 1035 || pop3_storage || String || The name of POP3 storage provider, default is "mailaccount"<br />
|-<br />
| 1036 || pop3_path || String || Path to POP3's virtual root folder in storage, default is name of the POP3 account beside default folders<br />
|-<br />
| 1037 || personal || String || The customizable personal part of email address<br />
|-<br />
| 1038 || reply_to || String || The customizable reply-to email address<br />
|-<br />
| 1039 || addresses || String || The comma-separated list of available E-Mail addresses including aliases. !! Only available for primary mail account !!<br />
|}<br />
<br />
=== Create a new mail account ===<br />
<br />
PUT <code>/ajax/account?action=new</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request: A JSON object describing the new account to create. See [[#MailAccountData | mail account data]].<br />
<br />
Response: A JSON object representing the inserted mail account. See [[#MailAccountData | mail account data]].<br />
<br />
=== Update a mail account ===<br />
<br />
PUT <code>/ajax/account?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request: A JSON object identifiying (field ID is present) and describing the account to update. See [[#MailAccountData | mail account data]].<br />
<br />
Response: A JSON object representing the updated mail account. See [[#MailAccountData | mail account data]].<br />
<br />
=== Delete a mail account ===<br />
<br />
PUT <code>/ajax/account?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An array with the ID of the mail account to delete.<br />
<br />
=== Validate a mail account (which shall be created) ===<br />
<br />
PUT <code>/ajax/account?action=validate</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>tree</code> - An optional boolean parameter which indicates whether on successful validation the folder tree shall be returned (NULL on failure) or if set to "false" or missing only a boolean is returned which indicates validation result<br />
<br />
Request: A JSON object describing the new account to validate. See [[#MailAccountData | mail account data]].<br />
<br />
Response: Dependent on optional "tree" parameter a JSON folder object or a boolean value indicating the validation result<br />
<br />
The JSON folder object corresponding to [[#CommonFolderData | Common folder data]] and [[#DetailedFolderData | Detailed folder data]].<br />
Additionally a field "subfolder_array" is added which contains possible subfolders. This field is missing if a folder contains no subfolders.<br />
<br />
[[Category: OX6]]<br />
<br />
== Module Auto Configuration (since 6.22) ==<br />
<br />
=== Get Auto Configuration ===<br />
<br />
GET <code>/ajax/autoconfig?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>email</code> – Email Adress for which a mail configuration will be discovered.<br />
* <code>password</code> – Corresponding password for the mail account (optional)<br />
<br />
Response: A JSON Object containing the best available settings for an appropriate mail Server for the given email address. The fields are described in [[#MailAccountData | mail account data]]. The Data may be incomplete or even empty.<br />
<br />
== Module "user" (available with v6.14) ==<br />
<br />
The user module is used to access user information.<br />
<br />
=== Get all users ===<br />
<br />
GET <code>/ajax/user?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for users are defined in [[#CommonObjectData | Common object data]], [[#DetailedContactData | Detailed contact data]] and [[#DetailedUserData | Detailed user data]].<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Response with timestamp: An array with user data. Each array element describes one user and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
{| id="DetailedUserData" cellspacing="0" border="1"<br />
|+ align="bottom" | Detailed user data<br />
! ID !! Displayed name !! Name !! Type !! Value<br />
|-<br />
| 610 || Aliases || aliases || Array || The user's aliases<br />
|-<br />
| 611 || Time zone || timezone || String || The time zone ID.<br />
|-<br />
| 612 || Locale || locale || String || The name of user's entire locale, with the language, country and variant separated by underbars. E.g. "en", "de_DE"<br />
|-<br />
| 613 || Groups || groups || Array || The IDs of user's groups<br />
|-<br />
| 614 || Contact ID || contact_id || Number || The contact ID of the user<br />
|-<br />
| 615 || Login info || login_info || String || The user's login information<br />
|}<br />
<br />
=== Get a list of users ===<br />
<br />
PUT <code>/ajax/user?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – A comma-separated list of columns to return. Each column is specified by a numeric column identifier. Column identifiers for users are defined in [[#CommonObjectData | Common object data]], [[#DetailedContactData | Detailed contact data]] and [[#DetailedUserData | Detailed user data]].<br />
<br />
Request body: An array of numbers. Each number is the ID of requested user. Since v6.18.1, a <code>null</code> value in the array is interpreted as the currently logged in user.<br />
<br />
Response with timestamp: An array with user data. Each array element describes one user and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get a user ===<br />
<br />
GET <code>/ajax/user?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the requested user. Since v6.18.1, this parameter is optional: the default is the currently logged in user.<br />
<br />
Response with timestamp: An object containing all data of the requested user. The fields of the object are listed in [[#CommonObjectData | Common object data]], [[#DetailedContactData | Detailed contact data]] and [[#DetailedUserData | Detailed user data]].<br />
<br />
=== Update a user ===<br />
<br />
PUT <code>/ajax/user?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – Object ID of the updated user.<br />
* <code>timestamp</code> – Timestamp of the updated user. If the user was modified after the specified timestamp, then the update must fail.<br />
<br />
Request body: User object as described in [[#CommonObjectData | Common object data]], [[#DetailedContactData | Detailed contact data]] and [[#DetailedUserData | Detailed user data]]. Only modified fields are present.<br />
<br />
'''Note''': "timezone" and "locale" are the only fields from [[#DetailedUserData | Detailed user data]] which are allowed to be updated.<br />
<br />
Response with timestamp: An empty object.<br />
<br />
=== Search users ===<br />
<br />
PUT <code>/ajax/user?action=search</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>columns</code> – The requested fields<br />
* <code>sort</code> (optional) – The identifier of a column which determines the sort order of the response. If this parameter is specified, then the parameter order must be also specified. In case of use of column 609 (use count depending order for collected users with global address book) the parameter "order" ist NOT necessary and will be ignored.<br />
* <code>order</code> (optional) – "asc" if the response entires should be sorted in the ascending order, "desc" if the response entries should be sorted in the descending order. If this parameter is specified, then the parameter sort must be also specified.<br />
<br />
Request body: An Object as described in [[#SearchUsers | Search users]].<br />
<br />
{| id="SearchUsers" cellspacing="0" border="1"<br />
|+ align="bottom" | Search users<br />
! Name !! Type !! Value<br />
|-<br />
| pattern || String || Search pattern to find users. In the pattern, the character "*" matches zero or more characters and the character "?" matches exactly one character. All other characters match only themselves.<br />
|-<br />
| startletter || String || Search users with the given startletter. If this field is present, the pattern is matched against the user field which is specified by the property contact_first_letter_field on the server (default: last name). Otherwise, the pattern is matched against the display name.<br />
|}<br />
<br />
Alternative request body: An Object as described in [[#SearchUsersAlternative | Search users alternative]].<br />
<br />
{| id="SearchUsersAlternative" cellspacing="0" border="1"<br />
|+ align="bottom" | Search users alternative<br />
! Name !! Type !! Value<br />
|-<br />
| last_name || String || Searches users where the last name match with the given last name.<br />
|-<br />
| first_name || String || Searches users where the first name match with the given first name.<br />
|-<br />
| display_name || String || Searches users where the display name match with the given display name.<br />
|-<br />
| orSearch || Boolean || If set to true, the fields are connected through an OR search habit.<br />
|-<br />
| emailAutoComplete || Boolean || If set to true, results are guaranteed to contain at least one email adress and the search is performed by connecting the relevant fields through an OR search habit.<br />
|}<br />
<br />
Response: An array with user data. Each array element describes one user and is itself an array. The elements of each array contain the information specified by the corresponding identifiers in the columns parameter.<br />
<br />
=== Get user attribute (available with v6.20) ===<br />
<br />
GET <code>/ajax/user?action=getAttribute</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – ID of the user. <br />
* <code>name</code> – The attribute name. <br />
<br />
Response without timestamp: A JSON object providing name and value of the requested attribute<br />
<pre><br />
{ "name":"somename", "value":"somevalue"}<br />
</pre><br />
<br />
=== Set user attribute (available with v6.20) ===<br />
<br />
PUT <code>/ajax/user?action=setAttribute</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – ID of the user. <br />
* <code>setIfAbsent</code> - Set to "true" to put the value only if the specified name is not already associated with a value, otherwise "false" to put value in any case<br />
<br />
Request body: A JSON object providing name and value of the attribute. If the <code>"value"</code> field id missing or NULL, the attribute is removed.<br />
<pre><br />
{ "name":"somename", "value":"somevalue"}<br />
</pre><br />
<br />
Response: The boolean value "true" if PUT was successful; otherwise "false"<br />
<br />
== Module "OAuth" (available with v6.20) ==<br />
<br />
The OAuth module is used to manage multiple OAuth accounts for certian online services for a user. The OAuth mechanism allows the Open-Xchange application to act as behalf of this user using previously obtained access tokens granted by user.<br />
<br />
The OAuth interface is divided into two parts: Account access and service's meta data access.<br />
<br />
=== OAuth account access ===<br />
<br />
The OAuth service account access description.<br />
<br />
<br />
==== Get all OAuth accounts ====<br />
<br />
GET <code>/ajax/oauth/accounts?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – The <b>optional</b> service meta data identifier. If missing all accounts of all services are returned; otherwise all accounts of specified service are returned<br />
<br />
Response: An array with account data. Each array element is a JSON object describing an OAuth account as specified in [[#OAuthAccountData | OAuth account data]].<br />
<br />
==== Get an OAuth account ====<br />
<br />
GET <code>/ajax/oauth/accounts?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The account identifier.<br />
<br />
Response: A JSON object describing an OAuth account as specified in [[#OAuthAccountData | OAuth account data]].<br />
<br />
{| id="OAuthAccountData" cellspacing="0" border="1"<br />
|+ align="bottom" | OAuth account<br />
! Field !! Type !! Description<br />
|-<br />
| id || Number || The numeric identifier of the OAuth account.<br />
|-<br />
| displayName || String || The account display name<br />
|-<br />
| serviceId || String || The identifier of the associated service meta data; e.g. <code>"com.openexchange.oauth.twitter"</code><br />
|-<br />
| token || String || The token<br />
|-<br />
| secret || String || The token secret<br />
|-<br />
|}<br />
<br />
==== Delete an OAuth account ====<br />
<br />
PUT <code>/ajax/oauth/accounts?action=delete</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The account identifier.<br />
<br />
Response: The boolean value "true" if successful<br />
<br />
==== Update an OAuth account ====<br />
<br />
PUT <code>/ajax/oauth/accounts?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The account identifier. May also be provided in request body's JSON OAuth account representation by <code>"id"</code> field.<br />
<br />
Request body: A JSON object providing the OAuth account fields to update. See [[#OauthAccountData | OAuth account data]]. Currently the only values which make sende being updated are <code>"displayName"</code> and the <code>"token"</code>-<code>"secret"</code>-pair.<br />
<br />
Response: The boolean value "true" if successful<br />
<br />
==== Initialize creation of an OAuth account ====<br />
<br />
GET <code>/ajax/oauth/accounts?action=init</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – The service meta data identifier; e.g. <code>"com.openexchange.oauth.twitter"</code><br />
<br />
Response: An JSON representation of the resulting interaction providing needed information to complete account creation. See [[#OauthInteractionData | OAuth interaction data]].<br />
<br />
{| id="OauthInteractionData" cellspacing="0" border="1"<br />
|+ align="bottom" | OAuth interaction<br />
! Field !! Type !! Description<br />
|-<br />
| authUrl || String || The numeric identifier of the OAuth account.<br />
|-<br />
| type || String || The interaction type name; <code>"outOfBand"</code> or <code>"callback"</code><br />
|-<br />
| token || String || The token<br />
|-<br />
| uuid || String || The UUID for this OAuth interaction<br />
|-<br />
|}<br />
<br />
==== Create an OAuth account ====<br />
<br />
Note: This action is typically called by provided call-back URL and is ony intended for manual invocation if "outOfBand" interaction is returned by preceeding <code>/ajax/oauth/account?action=init</code> step.<br />
<br />
PUT <code>/ajax/oauth/accounts?action=create</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module<br />
* <code>oauth_token</code> – The request token from preceeding OAuth interaction<br />
* <code>uuid</code> – The UUID of the preceeding OAuth interaction<br />
* <code>oauth_verfifier</code> – The verifier string which confirms that user granted access<br />
* <code>displayName</code> – The display name for the new account<br />
<br />
Response: A JSON object describing the newly created OAuth account as specified in [[#OAuthAccountData | OAuth account data]].<br />
<br />
=== OAuth service meta data access ===<br />
<br />
The OAuth service meta data access description.<br />
<br />
<br />
==== Get all OAuth services' meta data ====<br />
<br />
GET <code>/ajax/oauth/services?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: An array with service data. Each array element is a JSON object describing an OAuth service's meta data as specified in [[#OAuthServiceMetaData | OAuth service meta data]].<br />
<br />
==== Get an OAuth service's meta data ====<br />
<br />
GET <code>/ajax/oauth/services?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The service's identifier.<br />
<br />
Response: A JSON object describing an OAuth service's meta data as specified in [[#OAuthServiceMetaData | OAuth service meta data]].<br />
<br />
{| id="OAuthServiceMetaData" cellspacing="0" border="1"<br />
|+ align="bottom" | OAuth service meta data<br />
! Field !! Type !! Description<br />
|-<br />
| id || Number || The numeric identifier of the OAuth account.<br />
|-<br />
| displayName || String || The account display name<br />
|-<br />
|}<br />
<br />
== Module "JSlob" (available with v6.22) ==<br />
<br />
The JSlob module is used to store&retrieve arbitrary JSON-structured configuration for a single user.<br />
<br />
<br />
=== Get all JSLobs ===<br />
<br />
GET <code>/ajax/jslob?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
<br />
<br />
Response: An array with JSON configurations. Each array element is a JSON object representing a certain configuration consisting if a "id" and "jslob" field. See [[#JSlobData | JSlob data ]]<br />
<br />
{| id="JSlobData" cellspacing="0" border="1"<br />
|+ align="bottom" | JSlob data<br />
! Field !! Type !! Description<br />
|-<br />
| id || String or Number || The identifier of the JSlob.<br />
|-<br />
| jslob || JSON object || The JSON configuration.<br />
|-<br />
|}<br />
<br />
=== List denoted JSLobs ===<br />
<br />
PUT <code>/ajax/jslob?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
<br />
<br />
Request body: A JSON array of JSlob identifiers; e.g. <code>[ "1", "2", … ]</code><br />
<br />
Response: An array with JSON configurations. Each array element is a JSON object representing a certain configuration consisting if a "id" and "jslob" field. See [[#JSlobData | JSlob data ]]<br />
<br />
=== Delete a JSlob ===<br />
<br />
PUT <code>/ajax/jslob?action=set</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
* <code>id</code> – The JSlob identifier.<br />
<br />
<br />
Request body: An empty request body<br />
<br />
Response: Nothing<br />
<br />
=== Store a JSlob ===<br />
<br />
PUT <code>/ajax/jslob?action=set</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
* <code>id</code> – The identifier for the new JSlob to create<br />
<br />
<br />
Request body: A JSON object containing the "path" and "value" of the JSON configuration to store. If "path" is missing the current configuration<br />
is merged with given JSON object.<br />
<br />
Response: Nothing<br />
<br />
=== Update a single value inside a JSlob ===<br />
<br />
PUT <code>/ajax/jslob?action=update</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>serviceId</code> – Optional identifier for the JSlob service. Default is <code>com.openexchange.jslob.config</code><br />
* <code>id</code> – The identifier for the new JSlob to create<br />
<br />
<br />
Request body: The new value to store inside specified JSlob<br />
<br />
Response: A JSlob representation according to [[#JSlobData | JSlob data ]]<br />
<br />
=== REST-like access to JSlob module ===<br />
<br />
to be done...<br />
<br />
<br />
== Module "freebusy" (available with v6.22.1) ==<br />
<br />
Provides access to free/busy information.<br />
<br />
<br />
=== Get free/busy information ===<br />
<br />
GET <code>/ajax/freebusy?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>participant</code> – The participant to get the free/busy data for. May be either an internal user-, group- or resource-ID, or an e-mail address for external participants.<br />
* <code>from</code> – The lower (inclusive) limit of the requested time-range.<br />
* <code>until</code> – The upper (exclusive) limit of the requested time-range.<br />
* <code>merged</code> (optional) – True or False. Whether to pre-process the free/busy data on the server or not. This includes sorting as well as merging overlapping free/busy intervals.<br />
<br />
Response: An array of free/busy intervals as described in [[#FreeBusyInterval | Free/Busy interval]]<br />
<br />
{| id="FreeBusyInterval" cellspacing="0" border="1"<br />
|+ align="bottom" | Free/Busy interval<br />
! Name !! Type !! Value<br />
|-<br />
| start_date || Time || Start time of the interval.<br />
|-<br />
| end_date || Time || End time of the interval.<br />
|-<br />
| shown_as || Number || The busy status of this interval, one of:<br />
{| cellspacing="0" border="1"<br />
| 1 || unknown<br />
|-<br />
| 1 || reserved<br />
|-<br />
| 2 || temporary<br />
|-<br />
| 3 || absent<br />
|-<br />
| 4 || free<br />
|}<br />
|-<br />
| id || String || Object ID of the corresponding appointment if available.<br />
|-<br />
| folder_id || String || Folder ID of the corresponding appointment if available.<br />
|-<br />
| title || String || Title of the corresponding appointment if available.<br />
|-<br />
| location || String || Location of the corresponding appointment if available.<br />
|-<br />
| full_time || Boolean || True if the corresponding appointment is a whole day appointment, not present otherwise.<br />
|}<br />
<br />
<br />
=== Get a list of free/busy information ===<br />
<br />
PUT <code>/ajax/freebusy?action=list</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>from</code> – The lower (inclusive) limit of the requested time-range.<br />
* <code>until</code> – The upper (exclusive) limit of the requested time-range.<br />
* <code>merged</code> (optional) – True or False. Whether to pre-process the free/busy data on the server or not. This includes sorting as well as merging overlapping free/busy intervals.<br />
<br />
Request body: An array of participants to get the free/busy data for. Each participant may be either an internal user-, group- or resource-ID, or an e-mail address for external participants.<br />
<br />
Response: The free/busy data for all requested participants inside a JSON object with the participants as keys. Besides a combined data element for a requested group, all group members are resolved and listed seperately in the result. If the 'merged' view was requested, an additional data element named 'merged' representing a combined view for all requested participants is added to the results implicitly.<br />
<br />
<br />
== Messaging Services ==<br />
<br />
Messaging Services represent a messaging backend. The messaging services add a new folder module "messaging". <br />
<br />
A *Messaging Service* Object has the following structure:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Messaging Service<br />
! Field !! Type !! Description<br />
|-<br />
| id || String || Identifies a messagingService. Usually a String in reverse domain name notation. Example: "com.openexchange.messaging.twitter"<br />
|-<br />
| displayName || String || Human readable display name of the service. Example: "Twitter" <br />
|-<br />
| formDescription || Array || A description for dynamic form fields. Same as in PubSub <br />
|-<br />
| messagingActions || Array || An array of Strings a dynamic set of actions that are possible with messages of this service. Described in detail later on. <br />
|-<br />
|}<br />
<br />
The available JSON calls are:<br />
<br />
GET /ajax/messaging/service?action=all<br />
<br />
* session - A session ID previously obtained from the login module. <br />
<br />
Response: A standard response object containing an array of messaging service objects. <br />
<br />
<br />
GET /ajax/messaging/service?action=get<br />
<br />
* session - A session ID previously obtained from the login module. <br />
* id - The ID of the messaging service to load<br />
<br />
Response: A standard response object containing a messaging service object.<br />
<br />
== Messaging Accounts ==<br />
<br />
A messaging account represents the concrete configuration of an account of a given messaging service.<br />
A *messaging account* has the following structure:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Messaging Account<br />
! Field !! Type !! Description<br />
|-<br />
| id || Number || Identifies a given messaging account. This is not writeable and is generated by the server <br />
|-<br />
| messagingService || String || The messaging service id of the messaging service this account belongs to <br />
|-<br />
| displayName || String || User chosen String to identify a given account. Will also be translated into the folder name of the folder representing the accounts content <br />
|-<br />
| configuration || Object || Configuration data according to the formDescription of the relevant messagingService <br />
|-<br />
|}<br />
<br />
The available JSON calls are:<br />
<br />
PUT /ajax/messaging/account?action=new<br />
<br />
* session - A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON Object describing the account to be created.<br />
Response: A response object containing the new account id as its data.<br />
<br />
<br />
PUT /ajax/messaging/account?action=update<br />
<br />
* session - A session ID previously obtained from the login module.<br />
<br />
Request body: A JSON Object describing the update to the account. Note that the "id" and "messagingService" must always be set.<br />
Response: A response object containing the number 1 as its data on success.<br />
<br />
GET /ajax/messaging/account?action=get<br />
<br />
* session - A session ID previously obtained from the login module.<br />
* messagingService - The messaging service id that the account belongs to<br />
* id - An account ID to load<br />
<br />
Response: A response object containing the JSON Object representing the loaded account as its data.<br />
<br />
GET /ajax/messaging/account?action=delete<br />
<br />
* session - A session ID previously obtained from the login module.<br />
* messagingService - The messaging service id that the account belongs to<br />
* id - An account ID to delete<br />
<br />
Response: A response object containing 1 as its data on success.<br />
<br />
GET /ajax/messaging/account?action=all<br />
<br />
* session - A session ID previously obtained from the login module<br />
* messagingService - (optional) list only those accounts that belong to the given messagingService.<br />
<br />
Response: A response object containing a JSON array of account objects in its data section.<br />
<br />
<br />
== Messaging Messages ==<br />
<br />
A Messaging Message represents a single message. It consists of some metadata, headers and a content. The content attribute varies by the content-type header. <br />
If the content type is text/* it is a string, if it is a multipart/* it is an array of objects, each representing a part of the multipart. If it is anything else<br />
it is considered binary and is a Base64 encoded string (ToDo : This is not smart enough yet. I suppose we'll have to include encoding options for binaries much like in our EAVJSONProposal).<br />
<br />
The folder id of a message follows a predefined format:<br />
<br />
<pre><br />
[messagingService]://[accountId]/[path]<br />
</pre><br />
<br />
for an imaginary example consider: "com.openexchange.messaging.twitter://535/defaultTimeline/directMessages"<br />
<br />
The structure of a Messaging Message is as follows:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Messaging Message<br />
! Field !! Type !! Description<br />
|-<br />
|id ||String || The id of this message. Only unique in the given folder. <br />
|-<br />
|folder ||String || The folder id. <br />
|-<br />
|threadLevel ||Number || The nesting level of this message according to the conversation it's belonged to. May not be set. <br />
|-<br />
|flags ||Number || Bitmask showing the state of this message. The same as in the module "mail". <br />
|-<br />
|receivedDate ||Time || The time this message was received. <br />
|-<br />
|colorLabel ||Number || An arbitrary number marking this message in a certain color. The same as the colorLabel common to all groupware objects (see HTTP API)<br />
|-<br />
|user ||Array || An array of strings. Represents user flags. <br />
|-<br />
|size ||Number || The binary size of this message in bytes. <br />
|-<br />
|picture || String || A string depicting the URL to a picture for this message <br />
|-<br />
|url || String || A string that contains a link to the messages origin. Currently used in RSS messages.<br />
|-<br />
|headers ||JSONObject || A JSON Object of header data. Usually the value is either a String or an Array (if the headers has more than one value). Certain headers are rendered as more complex structures, see the section "Complex Headers". <br />
|-<br />
|content ||String or Array || See introductory note for Messaging Messages. <br />
|-<br />
|}<br />
<br />
The structure of a Multipart Part (an element of the content array in a multipart/* message) is a s follows:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Multipart Element<br />
! Field !! Type !! Description<br />
|-<br />
|sectionId || String || The sectionId of this part.<br />
|-<br />
|headers || JSONObject || Same as above. <br />
|-<br />
|content || String or Array || Same as above. <br />
|-<br />
|}<br />
<br />
Some *Complex Headers* have a structure differing from simple key/value(s) pairs. These are:<br />
<br />
=== Content-Type ===<br />
<br />
The Content-Type header is represented as a JSON Object with the following structure:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Content Type Header<br />
! Field !! Type !! Description<br />
|-<br />
| type || String || The type string (eg. text/plain). This governs the rendering of the content of a message. <br />
|-<br />
| params || Object || An Object with the keys "charset", containing the charset of this message and "name" pointing to the filename this part or message should have. <br />
|-<br />
|}<br />
<br />
When setting the content-type header in a messaging messages generated on the client the header may also be sent in it's short form. The short form is the type followed by a semi-colon separated list of key=value pairs<br />
of the params. For example: "text/plain;charset=utf-8;name=something.txt".<br />
<br />
=== Address Headers ===<br />
<br />
Address headers ( From, To,Cc,Bcc,Reply-To,Resent-Reply-To,Disposition-Notification-To,Resent-To,Sender,Resent-Sender,Resent-To,Resent-Cc,Resent-Bcc ) are formatted as an array of objects, or in case of "From" as a single object, with the attributes *address* and *personal*:<br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Address Headers<br />
! Field !! Type !! Description<br />
|-<br />
| address || String || The technical part of the address<br />
|-<br />
| personal || String || A displayable description of the addressee. May be unset.<br />
|-<br />
|}<br />
<br />
When setting an address header the header may also be sent by clients in the short form <code>"personal &lt;address&gt;"</code>, for example <code>"Clark Kent &lt;clark.kent@dailyplanet.com&gt;"</code>. <br />
<br />
=== List renderings of Messaging Messages ===<br />
<br />
Actions returning lists of messages usually return only a selection of attributes of a message driven by a "columns" parameter. The columns that are addressable point either to attributes of the top-level message or its headers. <br />
<br />
{| id="MessagingService" cellspacing="0" border="1"<br />
|+ align="bottom" | Header Equivalence<br />
! Column !! Refers To<br />
|-<br />
| *column* | *refers to* <br />
|-<br />
| id || The id attribute <br />
|-<br />
| folderId || The folder attribute <br />
|-<br />
| contentType || The "Content-Type" header <br />
|-<br />
| from || The "From" header <br />
|-<br />
| to || The "To" header <br />
|-<br />
| cc || The "Cc" header <br />
|-<br />
| bcc || The "Bcc" header <br />
|-<br />
| subject || The "Subject" header <br />
|-<br />
| size || The size attribute <br />
|-<br />
| sentDate || The "Date" header <br />
|-<br />
| receivedDate || The receivedDate attribute <br />
|-<br />
| flags || The flags attribute <br />
|-<br />
| threadLevel || The threadLevel attribute <br />
|-<br />
| dispositionNotificationTo || The "Disposition-Notification-To" header. <br />
|-<br />
| priority || The "X-Priority" header <br />
|-<br />
| colorLabel || The colorLabel attribute <br />
|-<br />
| url || The url attribute <br />
|-<br />
| body || The content attribute <br />
|-<br />
| headers || The headers attribute <br />
|-<br />
|}<br />
<br />
=== JSON calls ===<br />
<br />
GET /ajax/messaging/message?action=get<br />
<br />
* session - A session ID previously obtained from the login module<br />
* id - The ID of the message to load<br />
* peek - (optional) if set to "true" the read/unread state of the message will not change. Defaults to false.<br />
* folder - The folder id<br />
<br />
Response: An Object representing the loaded message.<br />
<br />
PUT /ajax/messaging/message?action=send<br />
<br />
* session - A session ID previously obtained from the login module<br />
* recipients - (optional) If set the message is sent to the given list of recipients, otherwise this defaults to the "To" header of the message.<br />
<br />
Request Body: The Request Body should contain the JSON Object representing the message to be sent.<br />
Response: "1" as the data of a regular response on success.<br />
<br />
GET or PUT /ajax/messaging/message?action=perform<br />
<br />
* session - A session ID previously obtained from the login module<br />
* action - The messaging action to invoke<br />
* id - The id of the message the action should be invoked on. Only used on actions of type "storage".<br />
* folder - The folder id.<br />
<br />
Request Body: On actions of type "message" the body should contain the JSON representation of the message the action should be applied to.<br />
Response: Either 1 if no further user interaction is needed or a messaging message that, after having the user modify it has to be supplied back to the follower action of this action.<br />
<br />
Thus, to invoke a messaging action of type "storage" the folder and id are needed. Messaging actions of type "message" need a folder and message in the body. <br />
Messaging actions of type "none" need a messaging message and account. <br />
<br />
==== List style requests ====<br />
<br />
GET /ajax/messaging/message?action=all<br />
<br />
* session - A session ID previously obtained from the login module<br />
* columns - A comma-separated list of column names.<br />
* sort - (optional) A column to sort by.<br />
* order - (optional) The order direction. "asc" for ascending or "desc" for descending. Defaults to "asc"<br />
* folder - The folder id.<br />
<br />
Response: An array of arrays with the sub arrays containing the values of the fields asked for by the the columns parameter.<br />
<br />
<br />
PUT /ajax/messaging/messages?action=list<br />
<br />
* session - A session ID previously obtained from the login module<br />
* columns - A comma-separated list of column names.<br />
<br />
Request Body: An array of arrays with the folder and id as elements each identifying a message. <br />
<br />
Response: An array of arrays with the sub arrays containing the values of the fields asked for by the columns parameter.<br />
<br />
== Snippet module (available with v7.0.0/v6.22.0) ==<br />
<br />
=== Gets a certain snippet by identifier ===<br />
<br />
GET /ajax/snippet?action=get<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
<br />
Response:<br />
The snippet's JSON representation; e.g.<br />
<br />
{<br />
"id": "1",<br />
"type": "signature",<br />
"props": {"x-custom": "any value"},<br />
"module": "mail",<br />
"displayname": "My signature",<br />
"misc": {"foo": "bar"},<br />
"createdby": 17,<br />
"content": "-- \\nMy name and position here",<br />
"accountid": 0,<br />
"shared": false,<br />
"files":<br />
[<br />
{<br />
"mimetype": "image/png; name=pic.png",<br />
"filename": "pic.png",<br />
"id": "46f49f8a-40d5-4f29-8bc9-728f3420864c",<br />
"size": 6074<br />
}<br />
]<br />
}<br />
<br />
=== Gets all snippets associated with the current user and context ===<br />
<br />
GET /ajax/snippet?action=all<br />
<br />
* session - The session identifier<br />
* type - Optional CSV of types to filter by; e.g. "signature"<br />
<br />
Response:<br />
A JSON array of snippets' JSON representations<br />
<br />
<br />
<br />
=== Gets certain snippets by identifiers ===<br />
<br />
GET /ajax/snippet?action=list<br />
<br />
* session - The session identifier<br />
<br />
Request body:<br />
A JSON array of snippet identifiers<br />
<br />
Response:<br />
A JSON array of snippets' JSON representations<br />
<br />
<br />
<br />
=== Gets a certain snippet's attachment by identifier ===<br />
<br />
GET /ajax/snippet?action=getattachment<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
* attachmentid - The attachment identifier<br />
<br />
Response:<br />
The attachment's raw data<br />
<br />
<br />
<br />
=== Creates a new snippet ===<br />
<br />
PUT /ajax/snippet?action=new<br />
<br />
* session - The session identifier<br />
<br />
Request body:<br />
A JSON representation of the snippet.<br />
Excluding its attachments (see attach/detach actions)<br />
<br />
Response:<br />
The created snippet's identifier<br />
<br />
<br />
<br />
=== Updates a certain snippet by identifier ===<br />
<br />
PUT /ajax/snippet?action=update<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
<br />
Request body:<br />
A JSON representation of the snippet providing the fields that should be changed.<br />
Excluding its attachments (see attach/detach actions)<br />
<br />
Response:<br />
The updated snippet's JSON representation<br />
<br />
<br />
<br />
=== Deletes a certain snippet by identifier ===<br />
<br />
PUT /ajax/snippet?action=delete<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier (otherwise provide one or more identifiers through request body's JSON array)<br />
<br />
Request body:<br />
A JSON array of identifiers denoting the snippets to delete<br />
<br />
Response:<br />
An empty/dummy result (don't care)<br />
<br />
<br />
<br />
=== Attaches one or more files to an existing snippet ===<br />
<br />
POST /ajax/snippet?action=attach<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
<br />
Request body:<br />
Multipart form data providing the upload files to attach to the snippet.<br />
<br />
Response:<br />
The updated snippet's identifier<br />
<br />
<br />
<br />
=== Detaches open or more files from an existing snippet ===<br />
<br />
PUT /ajax/snippet?action=detach<br />
<br />
* session - The session identifier<br />
* id - The snippet identifier<br />
<br />
Request body:<br />
A JSON array providing the identifiers of the attachments to remove from snippet<br />
<br />
Response:<br />
The updated snippet's identifier<br />
<br />
== Picture Halo (since 7.4.1) ==<br />
<br />
GET /appsuite/api/halo/contact/picture<br />
* session - (optional) falls back to the public session cookie<br />
* internal_userid - (optional) The internal user id of a user whose picture you want to load<br />
* userid - (optional) an alias for internal_userid<br />
* user_id - (optional) an alias for internal_userid<br />
* id - (optional) a contact id<br />
* email - (optional) an email to search for. Will pick global address book matches before regular matches. After that picks the most recently changed contact<br />
* email1 - (optional) an alias for email<br />
* email2 - (optional) another email address to use to find matches<br />
* email3 - (optional) and yet another email address to use to find matches<br />
<br />
''At least one of the optional search parameters should be set. All parameters are connected by OR during the search. More specific parameters like user_id or id are prioritized in case of multiple matches.''<br />
<br />
Response:<br />
The picture with proper eTag and caching headers set, or an HTTP Status 404 response, if no picture could be found.<br />
<br />
<br />
== Module "capabilities" (available with v7.4.2) ==<br />
<br />
Provides access to capabilities, i.e. modules or features that are available on the backend and the user has access to.<br />
<br />
=== Get a capability ===<br />
<br />
GET <code>/ajax/capabilities?action=get</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
* <code>id</code> – The identifier of the capability<br />
<br />
Response: The requested capability as described in [[#Capability| Capability]], if available, otherwise an empty result<br />
<br />
{| id="Capability" cellspacing="0" border="1"<br />
|+ align="bottom" | Capability<br />
! Name !! Type !! Value<br />
|-<br />
| id || String || The identifier of the capability<br />
|-<br />
| attributes || Object || A JSON object holding optional properties of the capability <br />
|}<br />
<br />
=== Get all capabilities ===<br />
<br />
GET <code>/ajax/capabilities?action=all</code><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Response: An array of capability objects as described in [[#Capability| Capability]].<br />
<br />
== Module "emig" ==<br />
<br />
'''Available with 7.4.2.''' This module checks the status of e-mail sender and recipients regarding their compliance with the initiative [http://www.e-mail-made-in-germany.de/ E-Mail made in Germany].<br />
<br />
=== Check the sender address ===<br />
<br />
<tt>PUT /ajax/emig?action=sender</tt><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: The sender as described in [[#EmiG sender|EmiG sender]].<br />
<br />
Response: <tt>true</tt> if EmiG is enabled for this sender address.<br />
<br />
{| id="EmiG sender" cellspacing="0" border="1"<br />
|+ align="bottom" | EmiG sender<br />
! Name !! Type !! Value<br />
|-<br />
| account || String || Optional account ID. Determined automatically if absent.<br />
|-<br />
| sender || String || The e-mail address of the sender to check.<br />
|}<br />
<br />
=== Check recipient addresses ===<br />
<br />
<tt>PUT /ajax/emig?action=recipients</tt><br />
<br />
Parameters:<br />
* <code>session</code> – A session ID previously obtained from the login module.<br />
<br />
Request body: An array with recipient addresses as strings.<br />
<br />
Response: An array with a status number for each recipient address. The meaning of the number values is defined in [[#EmiG status|EmiG status]].<br />
<br />
{| id="EmiG status" cellspacing="0" border="1"<br />
|+ align="bottom" | EmiG status<br />
! Status !! Meaning<br />
|-<br />
| 0 || Encrypted transport is not guaranteed.<br />
|-<br />
| 1 || Encrypted transport to the recipient's server. If the recipient's client supports SSL, also to the recipient.<br />
|-<br />
| 2 || Encrypted transport is guaranteed. Unencrypted transport is disabled.<br />
|}</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=Portal:AppSuite_UI/Topics&diff=16937Portal:AppSuite UI/Topics2014-02-03T11:39:48Z<p>Viktor.Pracht: linked the new Getting Started article</p>
<hr />
<div>== Getting started ==<br />
* [[AppSuite:GettingStarted | Getting started developing an external app]]<br />
* [[AppSuite:UI developer primer| Skills needed to develop the UI]]<br />
* [[AppSuite:Getting started developing the UI | Getting started developing the UI]]<br />
* [[AppSuite:UI_Development_Style_Guide | UI Development Style Guide]]<br />
* [[AppSuite:Appserver | Appserver]]<br />
* [[AppSuite:Apache Configuration | Apache Configuration]]<br />
* [[AppSuite:Definition of done|Definition of done]]<br />
* [[Appsuite:UI_FAQ | Frequently asked questions]]<br />
<br />
== Testing ==<br />
* [[AppSuite:Test basics | Lessons learned while testing]]<br />
* [[AppSuite:RunTests | Running ui tests]]<br />
<br />
== How-to articles ==<br />
* [[AppSuite:Action links|Understanding action links]]<br />
** [[AppSuite:Files App Actions|Adding actions to the files app]]<br />
* [[AppSuite:Date_and_time|Date and time]]<br />
* [[AppSuite:i18n | Internationalization (i18n)]]<br />
* [[AppSuite:a11y | Accessibility (a11y)]]<br />
* [[AppSuite:Mediaplayer | Mediaplayer]]<br />
* [[AppSuite:Theming | Theming]]<br />
* [[AppSuite:UI manifests explained | UI manifests explained]]<br />
* [[AppSuite:Upsell | Upsell]]<br />
* [[AppSuite:VGrid | VGrid]]<br />
* [[AppSuite:Mobile | Mobile development]]<br />
* [[AppSuite:Upsell tools| Upsell tools]]<br />
* [[AppSuite:Guided tours| Guided tours]]<br />
* [[AppSuite:Browserdetection | Browser detection with form-login]]<br />
<br />
=== Server communication ===<br />
* [[AppSuite:APIs | APIs]]<br />
* [[AppSuite:API_Factory | API Factory]]<br />
* [[AppSuite:http.js | http.js]]<br />
<br />
=== Extension points ===<br />
* [[AppSuite:Extending_the_UI_(Hands-on_introduction)| Hands-on introduction]]<br />
* [[AppSuite:Extending_the_UI | General information on extension points]]<br />
* [[AppSuite:Modifying forms by using extension points | Modifying forms]]<br />
* [[AppSuite:Extension points for calendar |extension points: Calendar]]<br />
* [[AppSuite:Extension points for contact |extension points: Contact]]<br />
* [[AppSuite:Extension points for core | extension points: Core]]<br />
* [[AppSuite:Extension points for email | extension points: E-Mail]]<br />
* [[AppSuite:Extension points for files |extension points: Files]]<br />
* [[AppSuite:Extension points for tasks |extension points: Tasks]]<br />
* [[AppSuite:Extension points for miscellaneous |extension points: Miscellaneous]]<br />
<br />
=== Writing components ===<br />
* [[AppSuite:Writing a portal plugin | Writing a portal plugin]]<br />
** [[AppSuite:Configuring portal plugins|Configuring a portal plugin]]<br />
** [[AppSuite:Using the Upsell widget|Using the Upsell widget]]<br />
* [[AppSuite:Writing a simple application | Writing a simple application]]<br />
* [[AppSuite:Writing a notification area plugin | Writing a plugin for the notification area]]<br />
* [[AppSuite:Writing a wizard | Writing a wizard]]<br />
* [[AppSuite:Capabilities | Capabilities explained]] - if you want to enable or disable your plugin<br />
<br />
== Miscellaneous articles ==<br />
* [[AppSuite:External libraries for the UI | External libraries used by the UI]]<br />
* [[AppSuite:Configuration| Configuration]]<br />
* [[AppSuite:Custom configurations| Custom configurations]]<br />
* [[AppSuite:UI build system| The UI build system]]<br />
* [[AppSuite:Embedding your settings into AppSuite settings|How to embed your own settings into the Appsuite settings page]]<br />
* [[AppSuite:Debugging the UI|Debugging the UI]]<br />
* All articles regarding the UI are filed in the category [[:Category:UI]]</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:Creating_a_settings_section_in_AppSuite_settings&diff=16888AppSuite:Creating a settings section in AppSuite settings2014-01-23T16:56:33Z<p>Viktor.Pracht: /* Register */</p>
<hr />
<div><div class="title">Creating a settings section in AppSuite settings</div><br />
<br />
This article explains how to add an settings section into AppSuite settings. You can also [[AppSuite:Embedding_your_settings_into_AppSuite_settings | implement your own settings using iframes]]. <br />
<br />
<br />
__TOC__ <br />
<br />
== Folder structure ==<br />
Assuming you got an app or plugin in a folder like <code>com.example/helloWorld</code> for which you want to implement settings in AppSuite, you will need a new subfolder called <code>settings</code>. So <code>com.example/helloWorld/settings</code> will prospectively contain the files managing your settings.<br />
<br />
== File Structure ==<br />
=== Manifest ===<br />
Creating a [[AppSuite:UI_manifests_explained | manifest]] is quite easy, writing the following into <code>com.example/helloWorld/settings/manifest.json</code> to load your settings, once AppSuite loads it's settings<br />
<br />
<pre class="language-javascript"><br />
{<br />
namespace: ['io.ox/settings/main']<br />
}<br />
</pre><br />
<br />
=== Defaults ===<br />
<code>com.example/helloWorld/settings/defaults.js</code> should contain your default settings, so an example setting the variable <code>exampleBoolean</code> to <code>false</code> and <code>exampleInteger</code> to 15 might be<br />
<pre class="language-javascript"><br />
define('com.example/helloWorld/settings/defaults', [], function () {<br />
<br />
'use strict';<br />
<br />
// define the default values for your settings here<br />
var settingsDefaults = {<br />
exampleBoolean: false,<br />
exampleInteger: 15<br />
};<br />
<br />
return settingsDefaults;<br />
});<br />
</pre><br />
<br />
=== Model ===<br />
<code>com.example/helloWorld/settings/model.js</code> contains an example of a simple default model, which you can use for your first settings<br />
<br />
<pre class="language-javascript"><br />
define('plugins/mail/AdvertOxMail/settings/model',<br />
['settings!plugins/mail/AdvertOxMail'], function (settings) {<br />
<br />
'use strict';<br />
<br />
// Very simple default model<br />
var exampleModel = Backbone.Model.extend({<br />
initialize: function (options) {<br />
<br />
},<br />
<br />
save: function () {<br />
settings.save(this.attributes);<br />
},<br />
<br />
destroy: function () {<br />
<br />
}<br />
});<br />
return exampleModel;<br />
});<br />
</pre><br />
<br />
=== Register ===<br />
Create a file called <code>com.example/helloWorld/settings/register.js</code> to extend the AppSuite settings and implement your own. <br />
<br />
The Head should look like this:<br />
<pre class="language-javascript"><br />
define("com.example/helloWorld/settings/register",<br />
['io.ox/core/extensions',<br />
'settings!com.example/helloWorld'<br />
],<br />
function (ext, settings) {<br />
'use strict';<br />
</pre><br />
<br />
Extend the panel which stores the different setting categories:<br />
<pre class="language-javascript"><br />
ext.point("io.ox/settings/pane").extend({<br />
id: 'com.example/helloWorld',<br />
title: 'Hello World Settings',<br />
ref: 'com.example/helloWorld',<br />
loadSettingPane: false,<br />
index: 400,<br />
lazySaveSettings: true<br />
});<br />
</pre><br />
<br />
And now extend the extension point which was established through reffering to <code>com.example/helloWorld</code> above.<br />
<code>(ref: 'com.example/helloWorld')</code><br />
<pre class="language-javascript"><br />
ext.point("com.example/helloWorld/settings/detail").extend({<br />
index: 50,<br />
id: 'extensions',<br />
draw: function () {<br />
var content=$('div').addClass('content');<br />
content.text('Add form elements to control your settings here');<br />
this.append(content);<br />
}<br />
});<br />
});<br />
</pre><br />
<br />
== Stuck somewhere? ==<br />
You got stuck with a problem while developing? OXpedia might help you out with the article about [[AppSuite:Debugging_the_UI | debugging the UI]].</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:Creating_a_settings_section_in_AppSuite_settings&diff=16885AppSuite:Creating a settings section in AppSuite settings2014-01-22T17:48:08Z<p>Viktor.Pracht: /* Defaults */</p>
<hr />
<div><div class="title">Creating a settings section in AppSuite settings</div><br />
<br />
This article explains how to add an settings section into AppSuite settings. You can also [[AppSuite:Embedding_your_settings_into_AppSuite_settings | implement your own settings using iframes]]. <br />
<br />
<br />
__TOC__ <br />
<br />
== Folder structure ==<br />
Assuming you got an app or plugin in a folder like <code>com.example/helloWorld</code> for which you want to implement settings in AppSuite, you will need a new subfolder called <code>settings</code>. So <code>com.example/helloWorld/settings</code> will prospectively contain the files managing your settings.<br />
<br />
== File Structure ==<br />
=== Manifest ===<br />
Creating a [[AppSuite:UI_manifests_explained | manifest]] is quite easy, writing the following into <code>com.example/helloWorld/settings/manifest.json</code> to load your settings, once AppSuite loads it's settings<br />
<br />
<pre class="language-javascript"><br />
{<br />
namespace: ['io.ox/settings/main']<br />
}<br />
</pre><br />
<br />
=== Defaults ===<br />
<code>com.example/helloWorld/settings/defaults.js</code> should contain your default settings, so an example setting the variable <code>exampleBoolean</code> to <code>false</code> and <code>exampleInteger</code> to 15 might be<br />
<pre class="language-javascript"><br />
define('com.example/helloWorld/settings/defaults', [], function () {<br />
<br />
'use strict';<br />
<br />
// define the default values for your settings here<br />
var settingsDefaults = {<br />
exampleBoolean: false,<br />
exampleInteger: 15<br />
};<br />
<br />
return settingsDefaults;<br />
});<br />
</pre><br />
<br />
=== Model ===<br />
<code>com.example/helloWorld/settings/model.js</code> contains an example of a simple default model, which you can use for your first settings<br />
<br />
<pre class="language-javascript"><br />
define('plugins/mail/AdvertOxMail/settings/model',<br />
['settings!plugins/mail/AdvertOxMail'], function (settings) {<br />
<br />
'use strict';<br />
<br />
// Very simple default model<br />
var exampleModel = Backbone.Model.extend({<br />
initialize: function (options) {<br />
<br />
},<br />
<br />
save: function () {<br />
settings.save(this.attributes);<br />
},<br />
<br />
destroy: function () {<br />
<br />
}<br />
});<br />
return exampleModel;<br />
});<br />
</pre><br />
<br />
=== Register ===<br />
Create a file called <code>com.example/helloWorld/settings/register.js</code> to extend the AppSuite settings and implement your own. <br />
<br />
The Head should look like this:<br />
<pre class="language-javascript"><br />
define("com.example/helloWorld/settings/register",<br />
['io.ox/core/extensions',<br />
'settings!com.example/helloWorld'<br />
],<br />
function (ext, settings) {<br />
'use strict';<br />
</pre><br />
<br />
Extend the panel which stores the different setting categories:<br />
<pre class="language-javascript"><br />
ext.point("io.ox/settings/pane").extend({<br />
id: 'com.example/helloWorld',<br />
title: 'Hello World Settings,<br />
ref: 'com.example/helloWorld',<br />
loadSettingPane: false,<br />
index: 400,<br />
lazySaveSettings: true<br />
});<br />
</pre><br />
<br />
And now extend the extension point which was established through reffering to <code>com.example/helloWorld</code> above.<br />
<code>(ref: 'com.example/helloWorld')</code><br />
<pre class="language-javascript"><br />
ext.point("com.example/helloWorld/settings/detail").extend({<br />
index: 50,<br />
id: 'extensions',<br />
draw: function () {<br />
var content=$('div').addClass('content');<br />
content.text('Add form elements to control your settings here');<br />
this.append(content);<br />
}<br />
});<br />
});<br />
</pre><br />
<br />
== Stuck somewhere? ==<br />
You got stuck with a problem while developing? OXpedia might help you out with the article about [[AppSuite:Debugging_the_UI | debugging the UI]].</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:Theming&diff=16881AppSuite:Theming2014-01-21T17:16:27Z<p>Viktor.Pracht: /* Providing custom icons */</p>
<hr />
<div>{{Stability-experimental}}<br />
<br />
<div class="title">Theming</div><br />
<br />
'''Abstract.''' In this article, you can learn how to create customized themes and use them to change the look of you appsuite installation.<br />
__TOC__<br />
== LESS.JS ==<br />
Appsuite used LESS as dynamic stylesheet language. LESS extends CSS with dynamic behavior such as variables, mixins, operations and functions.<br />
<br />
Please read [http://lesscss.org/#docs LESS.JS] documentation first.<br />
<br />
=== Using less.js ===<br />
If your theme depends on less.js, you will need one more step to make it work. Why? To accelerate the login, compilation of LessCSS files was moved from the login process in the browser to the installation process on the backend. <br />
<br />
Backend packages for themes and any apps which ship .less files require the following changes:<br />
<br />
1. Add "skipLess=1" to the build command in *.spec and in debian/rules:<br />
sh /opt/open-xchange-appsuite-dev/bin/build-appsuite app skipLess=1<br />
2. Add %post and %postun sections to *.spec:<br />
%post<br />
if [ "$1" = 1 ]; then<br />
UPDATE=/opt/open-xchange/appsuite/share/update-themes.sh<br />
[ -x $UPDATE ] && $UPDATE<br />
fi<br />
%postun<br />
UPDATE=/opt/open-xchange/appsuite/share/update-themes.sh<br />
[ -x $UPDATE ] && $UPDATE<br />
<br />
For multiple binary packages, the %post and %postun sections should apply only to backend packages <br />
which contain .less files.<br />
<br />
3. Add debian/postinst and debian/postrm containing the same content:<br />
#!/bin/sh<br />
UPDATE=/opt/open-xchange/appsuite/share/update-themes.sh<br />
[ -x $UPDATE ] && $UPDATE<br />
<br />
For multiple binary packages, the postinst and postrm files should apply only to backend packages which contain .less files.<br />
<br />
Note: Since 7.2.1, LessCSS files must have the file extension .less to be usable with the 'less' RequireJS plugin (module dependencies of the form 'less!filename.less'). Previously we were more lenient and dealt with .css, too.<br />
<br />
== File structure ==<br />
A theme basically consists of two files located in <code>apps/themes/<var>THEME_ID</var>/</code>. These files are described in this and the following sections.<br />
<br />
<code><var>THEME_ID</var></code> is a unique identifier for your theme, which is not visible to users. By convention, it is best derived from a domain name you control, e.g. <code>com.example.prettytheme</code>.<br />
<br />
=== definitions.less ===<br />
This file can be used to override variables described in the "Variables" section of this article.<br />
<br />
=== style.less ===<br />
This file can be used to define any CSS you like. Before doing this, check, if there really is no variable that can be used to achieve the same thing.<br />
<br />
=== Referencing paths ===<br />
Since 7.2.1, all URLs are relative to the source .less file in which they are contained. This means that unless a theme changes an image it does not need to include that image anymore. <br />
<br />
Old themes must be updated if they change an image from the default theme: All styles from the default theme which refer to a changed image must be overwritten in the custom theme. This way the URLs resolve to the new image.<br />
<br />
== Variables ==<br />
<br />
Naming of the variables should be straight forward. Variables containing the word ''Background'' will always refer to the background color. Variables containing ''Color'' will refer to the foreground color of an element, like color of a font. ''Hover'' in most cases means "hovered" elements. ''Selected'' relates to the currently selected item. Elements that are supposed to catch the users eye can use the ''Highlight'' class and the variable contains this word.<br />
<br />
=== Basic ===<br />
<br />
==== Font ====<br />
<br />
{|<br />
! Variable || Default || Description <br />
|-<br />
| @sansFontFamily || "Helvetica Neue", Helvetica, Arial, sans-serif<br />
|-<br />
| @serifFontFamily || Georgia, "Times New Roman", Times, serif<br />
|-<br />
| @monoFontFamily || Monaco, Menlo, Consolas, "Courier New", monospace<br />
|-<br />
| @baseFontSize || 14px<br />
|-<br />
| @baseFontFamily || @sansFontFamily<br />
|-<br />
| @baseLineHeight || 20px<br />
|-<br />
| @altFontFamily || @serifFontFamily<br />
|-<br />
| @touchFontSize || 15px<br />
|-<br />
| @headingsFontFamily || inherit<br />
|-<br />
| @headingsFontWeight || bold<br />
|-<br />
| @fontSizeLarge || @baseFontSize * 1.25<br />
|-<br />
| @fontSizeSmall || @baseFontSize * 0.85<br />
|-<br />
| @fontSizeMini || @baseFontSize * 0.75<br />
|-<br />
| @vgridFontSize || 13px<br />
|}<br />
<br />
==== Colors ====<br />
<br />
{|<br />
! Variable || Default || Description <br />
|-<br />
| @bodyBackground || @white<br />
|-<br />
| @textColor || @grayDark<br />
|-<br />
| @linkColor || #08c<br />
|-<br />
| @linkColorHover || darken(@linkColor, 15%)<br />
|-<br />
| @linkAccentColor || #ffad00<br />
|-<br />
| @linkAccentColorHover || darken(@linkAccentColor, 15%)<br />
|-<br />
| @badgeColor || @white<br />
|-<br />
| @badgeBackground || #555<br />
|-<br />
| @headingsColor || inherit<br />
|-<br />
| @black || #000<br />
|-<br />
| @grayDarker || #222<br />
|-<br />
| @grayDark || #333<br />
|-<br />
| @gray || #555<br />
|-<br />
| @grayLight || #aaa<br />
|-<br />
| @grayLighter || #eee<br />
|-<br />
| @white || #fff<br />
|-<br />
| @blue || darken(#049cdb, 5%)<br />
|-<br />
| @blueDark || #0064cd<br />
|-<br />
| @blueLight || lighten(#049cdb, 25%)<br />
|-<br />
| @green || #1A8D1A<br />
|-<br />
| @greenLight || #92D050<br />
|-<br />
| @red || #cc0000<br />
|-<br />
| @yellow || #F8E400<br />
|-<br />
| @orange || #f89406<br />
|-<br />
| @pink || #E01CD9<br />
|-<br />
| @purple || #7E16CF<br />
|-<br />
|}<br />
<br />
==== Space ====<br />
<br />
{|<br />
! Variable || Default || Description<br />
|-<br />
| @paddingLarge || 11px 19px<br />
|-<br />
| @paddingSmall || 2px 10px<br />
|-<br />
| @paddingMini || 0 6px<br />
|-<br />
| @baseBorderRadius || 4px<br />
|-<br />
| @borderRadiusLarge || 6px<br />
|-<br />
| @borderRadiusSmall || 3px<br />
|}<br />
<br />
=== Pagination ===<br />
<br />
Used where pagination is done, for example in the Calendar weekview, each week is on one "page"; one can switch the week using a pagination widget styled with these variables.<br />
<br />
{|<br />
! Variable || Default || Description<br />
|-<br />
| @paginationBackground || #fff<br />
|-<br />
| @paginationBorder || #ddd<br />
|-<br />
| @paginationActiveBackground || #f5f5f5<br />
|}<br />
<br />
=== Buttons ===<br />
<br />
{|<br />
! Variable || Default || Description<br />
|-<br />
| @btnBackground || @white<br />
|-<br />
| @btnBackgroundHighlight || darken(@white, 10%)<br />
|-<br />
| @btnBorder || #bbb<br />
|-<br />
| @btnPrimaryBackground || @linkColor<br />
|-<br />
| @btnPrimaryBackgroundHighlight || spin(@btnPrimaryBackground, 20%)<br />
|-<br />
| @btnInfoBackground || #5bc0de<br />
|-<br />
| @btnInfoBackgroundHighlight || #2f96b4<br />
|-<br />
| @btnSuccessBackground || #62c462<br />
|-<br />
| @btnSuccessBackgroundHighlight || #51a351<br />
|-<br />
| @btnWarningBackground || lighten(@orange, 15%)<br />
|-<br />
| @btnWarningBackgroundHighlight || @orange<br />
|-<br />
| @btnDangerBackground || #ee5f5b<br />
|-<br />
| @btnDangerBackgroundHighlight || #bd362f<br />
|-<br />
| @btnInverseBackground || #444<br />
|-<br />
| @btnInverseBackgroundHighlight || @grayDarker<br />
|}<br />
<br />
=== Dropdowns ===<br />
<br />
{|<br />
! Variable || Default || Description<br />
|-<br />
| @dropdownBackground || @white<br />
|-<br />
| @dropdownBorder || rgba(0,0,0,.2)<br />
|-<br />
| @dropdownDividerTop || #e5e5e5<br />
|-<br />
| @dropdownDividerBottom || @white<br />
|-<br />
| @dropdownLinkColor || @grayDark<br />
|-<br />
| @dropdownLinkColorHover || @white<br />
|-<br />
| @dropdownLinkColorActive || @white<br />
|-<br />
| @dropdownLinkBackgroundActive || @linkColor<br />
|-<br />
| @dropdownLinkBackgroundHover || @dropdownLinkBackgroundActive<br />
|}<br />
<br />
=== Foldertree ===<br />
{|<br />
! Variable || Default || Description <br />
|-<br />
| @foldertreeSidepanelBackground || #333 ||<br />
|-<br />
| @foldertreeSectionTitleColor || #888 || Color for sectiontitles in foldertree (like "Public" folders)<br />
|-<br />
| @foldertreeActiveLabelColor || #ccc || ''Active'' means, user can perform an action on this item<br />
|-<br />
| @foldertreePassiveLabelColor || #ccc || ''Passive'' means, user can '''not''' perform any action with this item <br />
|-<br />
| @foldertreeHoverBackground || #888 ||<br />
|-<br />
| @foldertreeSelectedBackground || #222 ||<br />
|-<br />
| @foldertreeBadgeBackground || @bagdeBackground || see [[#Colors]] for definition of @badgeBackground<br />
|-<br />
| @foldertreeBadgeColor ||@badgeColor || see [[#Colors]] for definition of @badgeBackground<br />
|}<br />
<br />
=== Calendar ===<br />
==== Appointment ====<br />
{|<br />
! Variable || Default || Description <br />
|-<br />
| @appointmentReserved || #08c /* blue */ || Appointment status color<br />
|-<br />
| @appointmentTemporary || #ffbb00 /* yellow */ || Appointment status color<br />
|-<br />
| @appointmentAbsent || #913f3f /* red */ || Appointment status color<br />
|-<br />
| @appointmentFree || #8eb360 /* green */ || Appointment status color<br />
|-<br />
| @appointmentPrivate || #555 /* gray */ || Appointment status color<br />
|-<br />
| @appointmentDeclinedFont || #888 /* dark gray */|| Font color for declined Appointments<br />
|-<br />
| @appointmentUnconfirmedAlpha || 0.4 || Transparency value for unconfirmed Appointments<br />
|-<br />
| @appointmentDeclinedAlpha || 0.3 || Transparency value for declined Appointments<br />
|-<br />
| @appointmentHoverPct || 15% || Percentage increase of the dark pigment content on hover effect<br />
|}<br />
<br />
==== Week View ====<br />
{|<br />
! Variable || Default || Description <br />
|-<br />
| @weekviewAppointmentLasso || #aeaeff || Lasso frame color<br />
|-<br />
| @weekviewDayIn || #fff /* white */ || Default background color in week view<br />
|-<br />
| @weekviewDayOut || #e0e0e0 /* grey */ || Background color outside of the mean working time<br />
|-<br />
| @weekviewTimeline || #f00 /* red */ || Color of the Line indicating the current time<br />
|-<br />
| @weekviewTimeWith || 58px || With of the time labels on the left side<br />
|-<br />
| @calendarToolbarHeight || 41px || Height of the control toolbar <br />
|}<br />
<br />
==== Month View ====<br />
{|<br />
! Variable || Default || Description <br />
|-<br />
| @monthviewAppointmentOut || #aaa /* light gray */ || Color of appointments, which are not in focus<br />
|-<br />
| @monthviewToday || #daefff /* light blue */|| Background color of the current day<br />
|-<br />
| @calendarToolbarHeight || 41px || Height of the control toolbar<br />
|}<br />
<br />
== Area names ==<br />
<br />
The variables sometimes refer to common areas. To identify which area is located where, see the following annotated screenshots.<br />
<br />
[[File:Colors_mail.png|800px||Mail application]]<br />
<br />
[[File:Colors_launchpad.png|800px||Launchpad application]]<br />
<br />
== Replacing the logo ==<br />
<br />
One of the most common theme changes which requires editing <code>style.css</code> is changing the logo in the top right corner. The logo is displayed as the background image for an element with the ID <code>io-ox-top-logo-small</code>. A theme can therefore change the size and URL of the image:<br />
#io-ox-top-logo-small {<br />
width: 60px;<br />
height: 22px;<br />
margin: 8px 13px 0 13px;<br />
background-image: url(mylogo.png);<br />
}<br />
The file <code>mylogo.png</code> is expected to be in the same directory as <code>style.css</code>. If you want to place the image somewhere else, then use a relative path in <code>url()</code>.<br />
<br />
Remember that images in OX App Suite are served by the web server and not by the application server. This means that images need to be packaged separately (for dedicated web servers) and installed in <code>/var/www/appsuite/</code> (or similar, depending on the target platform) instead of <code>/opt/open-xchange/appsuite/</code>. Direct support for multiple packages is coming in version 7.4.1. Until then, use the build system from the <code>develop</code> branch to [[AppSuite:UI_build_system#init-packaging|initialize the packaging]] if your theme contains images.<br />
<br />
== Mixins ==<br />
In LESS, it is possible to include a bunch of properties from one ruleset into another ruleset. So say we have the following class:<br />
<br />
=== Sample ===<br />
<pre class="language-css"><br />
.border-radius(@radius: 0px) {<br />
-webkit-border-radius: @radius;<br />
-moz-border-radius: @radius;<br />
-ms-border-radius: @radius;<br />
border-radius: @radius;<br />
}<br />
<br />
#menu a {<br />
color: #111;<br />
.border-radius(5px);<br />
}<br />
</pre><br />
<br />
Read [http://www.lesscss.org/#-mixins LESS Mixins]<br />
<br />
=== global OX Mixins ===<br />
<br />
they can be found at [[#definitions.less | definitions.less]]<br />
<br />
{|<br />
! Mixin || Sample || Description <br />
|-<br />
| .box-sizing(@boxmodel) || .box-sizing(border-box) ||<br />
|-<br />
| .user-select(@select) || .user-select(none) ||<br />
|-<br />
| .border-radius(@radius) || .border-radius(3px) ||<br />
|-<br />
| .box-shadow(@shadow) || .box-shadow(3px) ||<br />
|-<br />
| .vertical-gradient(@startColor, @endColor) || .vertical-gradient(#888, #555) ||<br />
|-<br />
| .radial-gradient(@color1, @color2, @color3) || .radial-gradient(#111, #222, #333) ||<br />
|-<br />
| .transition(@transition) || .transition(background-color 0.2s linear) ||<br />
|-<br />
| .animation(@animation) || .animation(slidein 300ms) ||<br />
|-<br />
| .animation-name(@name) || .animation-name(slideright) ||<br />
|-<br />
| .ellipsis || .ellipsis ||<br />
|-<br />
| .overflow(@type) || .overflow(hidden) ||<br />
|-<br />
| .overflow-x(@type) || .overflow-x(hidden) ||<br />
|-<br />
| .overflow-y(@type) || .overflow-y(hidden) ||<br />
|-<br />
| .backface-visibility(@type) || .backface-visibility(hidden) ||<br />
|}<br />
<br />
== How to activate a theme during development ==<br />
<br />
When creating a new theme, you will want to test changes quickly without building packages reinstalling them. The trick is to use [[Appsuite:Appserver|appserver]].<br />
<br />
# First, you need to add the theme to the list of available themes on the backend. Simply create a new file in <code>/opt/open-xchange/etc/settings/</code> with the extension <code>.properties</code> and add a line for your theme to it: <pre&lt;noinclude&gt;&lt;/noinclude&gt;>io.ox/core/settingOptions//themes/<var>ID</var>=<var>Theme Name</var></pre&lt;noinclude&gt;&lt;/noinclude&gt;> Replace <var>ID</var> by the identifier (directory name) of your theme, and <var>Theme Name</var> by the human-readable name which should appear in the UI.<br />
# The server needs to be restarted to read the new settings.<br />
# Now, you can use <code>appserver</code> ([[AppSuite:appserver#Use_with_Apache|with a local web server]] if your theme includes images) to get your theme in combination with the UI which is already installed on the backend.<br />
# Finally, activate your theme the list in the <code>Settings -> Basic</code> view behind the option <code>Theme</code>.<br />
<br />
In case you also want to access the same backend without <code>appserver</code> while your theme is selected, that theme (or at least some empty <code>.less</code> files) should be also installed on the backend to avoid errors. To just use an empty theme, run the following as root:<br />
touch /opt/open-xchange/appsuite/apps/themes/<var>ID</var>/definitions.less<br />
touch /opt/open-xchange/appsuite/apps/themes/<var>ID</var>/style.less<br />
/opt/open-xchange/appsuite/share/update-themes.sh<br />
The value of <var>ID</var> here must be the same as in your <code>.properties</code> file.<br />
<br />
== Favicons and mobile homescreen icons ==<br />
'''Note''': This chapter is not about changing AppSuite icons which are used in the application like the brand on the upper right.<br />
<br />
'''This documentation applies for AppSuite v.7.4.2'''<br />
<br />
AppSuite ships with a standard set of icons containing a<br />
# favicon<br />
# set of touch icons which are mainly used by mobile Safari on iOS<br />
<br />
These icons are used as default for all devices and browsers as long as you don't deliver your own icons with your theme. <br />
<br />
=== Favicon ===<br />
All major browsers support the use of a favicon. The favicon is a pixel image with the size of 16x16 (32x32) and the "ico" file ending. (see [http://en.wikipedia.org/wiki/Favicon Wikipedia Favicon] for details).<br />
<br />
You should provide your custom favicon within your custom theme. If you do not add a custom favicon to your theme the global OX default will be used. The default icon is located under <tt>apps/themes/icons/default</tt> on the web server.<br />
<br />
=== Apple touch icons ===<br />
iOS devices (iPhone/iPad/iPod) support so called "Webclips". Webclips are bookmarks to websites or webapps which provide a App Icon that is shown on the iOS homescreen. AppSuite offers full support for Webclips by providing all needed App icons, splashscreens and full screen support. If a user uses the "Add to homescreen" button on his iOS device, a Webclip is created, taking the right icon for his current device. Most devices need custom resolutions of the Webclip icon in the '''png''' format.<br />
<br />
* iPhone 3: 57 x 57 px<br />
* iPhone 4 retina: 114x114 px<br />
* iPhone iPhone 5 retina: 120 x 120 px<br />
* iPad: 72 x 72 px<br />
* iPad (iOS 7): 76 x 76px<br />
* iPad retina: 144 x 144 px <br />
* iPad retina (iOS 7): 152 x 152 px <br />
<br />
Furthermore a fullscreen Webclip App will show a splashscreen, a jpg file that is displayed on startup during app load. There are currently three different resolutions as jpg files available. '''Note''': Splashscreens must be JPG files<br />
<br />
* iPhone: 320 x 460 px<br />
* iPhone 4: 640 x 920 px<br />
* iPhone 5: 640 x 1096 px<br />
<br />
'''Note''': We do not provide splashscreens for iPad<br />
<br />
This list may change with Apple's iOS updates. We recommend providing all of this resolutions when customizing the Webclip icons and splashscreens, even if some iOS devices use the next best resolution for an icon if a certain file is missing.<br />
<br />
=== Providing custom icons ===<br />
To provide custom Webclip icons locate the following path in the AppSuite installation on your web server:<br />
pathToAppSuite/apps/themes/icons/default<br />
<br />
This folder contains all OX default icons for Webclips icons and splashscreens. Use these as samples for your own versions.<br />
<br />
A clean installation will have all our default icons in the "default" directory. To customize the icons we recommend using our default icons as samples and save your customized version in your theme. '''Note''': The filename has to be the same as in the default folder. Otherwise the fallback will be applied and the default icons will be used. If more advanced rewriting is needed one should edit the contents of the <tt>.htaccess</tt> file located under <tt>apps/themes</tt><br />
<br />
== Theming the login page ==<br />
<br />
The login page is a little bit special. If you don’t use the [[Open-Xchange_servlet_for_external_login_masks|form login]] and provide your own login page, you might want to theme the login page, too. [[AppSuite:Theming the login page|Learn how to do this here]].<br />
<br />
=== Providing domain based login themes ===<br />
<br />
If you have a multibrand installation and you want to deliver not only custom themes but also custom login-themes this can be done via Apache mod_rewrite. You can do so by a domain-based rewrite rule to deliver custom themes to a user based on the URI he's using. The needed config file <tt>.htaccess</tt> is located under <tt>apps/themes</tt><br />
<br />
<pre><br />
# Sample config for domain based login theme<br />
RewriteCond %{HTTP_HOST} ^www\.domain\.com$<br />
RewriteCond %{REQUEST_FILENAME} -f<br />
RewriteRule ^login/(.*)$ domain_com_logintheme/$1 [L]<br />
</pre><br />
<br />
== Best practice ==<br />
<br />
To be really safe, it’s best to only define your own values for the variables shown above. If this really breaks anything, we consider this a bug, please report it [https://bugs.open-xchange.com/] in our bugzilla.<br />
<br />
Of course, using CSS in <code>style.less</code> file to define your own styles is also possible. Make sure to test your style in such cases more carefully. It is most likely safe to change minor things using this file, but if you plan to change any positions of larger elements, this might break the complete design. So please be careful when overwriting the default CSS rules.<br />
<br />
== Links ==<br />
[http://bradfrost.github.io/this-is-responsive/resources.html Responsive design]<br />
<br />
[http://lesscss.org/ LESS]<br />
<br />
== Caveats ==<br />
<br />
It is '''not''' recommended to change the size of elements or their position. If you really want to do so, please check on all devices and in all browsers and make sure you didn’t break anything. You even have to be careful when changing the font, because this might have effects on positioning, too.<br />
<br />
As mentioned before, changing colors should be safe.<br />
<br />
[[Category:AppSuite]]<br />
[[Category:UI]]</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:Theming&diff=16880AppSuite:Theming2014-01-21T17:14:59Z<p>Viktor.Pracht: /* Favicon */</p>
<hr />
<div>{{Stability-experimental}}<br />
<br />
<div class="title">Theming</div><br />
<br />
'''Abstract.''' In this article, you can learn how to create customized themes and use them to change the look of you appsuite installation.<br />
__TOC__<br />
== LESS.JS ==<br />
Appsuite used LESS as dynamic stylesheet language. LESS extends CSS with dynamic behavior such as variables, mixins, operations and functions.<br />
<br />
Please read [http://lesscss.org/#docs LESS.JS] documentation first.<br />
<br />
=== Using less.js ===<br />
If your theme depends on less.js, you will need one more step to make it work. Why? To accelerate the login, compilation of LessCSS files was moved from the login process in the browser to the installation process on the backend. <br />
<br />
Backend packages for themes and any apps which ship .less files require the following changes:<br />
<br />
1. Add "skipLess=1" to the build command in *.spec and in debian/rules:<br />
sh /opt/open-xchange-appsuite-dev/bin/build-appsuite app skipLess=1<br />
2. Add %post and %postun sections to *.spec:<br />
%post<br />
if [ "$1" = 1 ]; then<br />
UPDATE=/opt/open-xchange/appsuite/share/update-themes.sh<br />
[ -x $UPDATE ] && $UPDATE<br />
fi<br />
%postun<br />
UPDATE=/opt/open-xchange/appsuite/share/update-themes.sh<br />
[ -x $UPDATE ] && $UPDATE<br />
<br />
For multiple binary packages, the %post and %postun sections should apply only to backend packages <br />
which contain .less files.<br />
<br />
3. Add debian/postinst and debian/postrm containing the same content:<br />
#!/bin/sh<br />
UPDATE=/opt/open-xchange/appsuite/share/update-themes.sh<br />
[ -x $UPDATE ] && $UPDATE<br />
<br />
For multiple binary packages, the postinst and postrm files should apply only to backend packages which contain .less files.<br />
<br />
Note: Since 7.2.1, LessCSS files must have the file extension .less to be usable with the 'less' RequireJS plugin (module dependencies of the form 'less!filename.less'). Previously we were more lenient and dealt with .css, too.<br />
<br />
== File structure ==<br />
A theme basically consists of two files located in <code>apps/themes/<var>THEME_ID</var>/</code>. These files are described in this and the following sections.<br />
<br />
<code><var>THEME_ID</var></code> is a unique identifier for your theme, which is not visible to users. By convention, it is best derived from a domain name you control, e.g. <code>com.example.prettytheme</code>.<br />
<br />
=== definitions.less ===<br />
This file can be used to override variables described in the "Variables" section of this article.<br />
<br />
=== style.less ===<br />
This file can be used to define any CSS you like. Before doing this, check, if there really is no variable that can be used to achieve the same thing.<br />
<br />
=== Referencing paths ===<br />
Since 7.2.1, all URLs are relative to the source .less file in which they are contained. This means that unless a theme changes an image it does not need to include that image anymore. <br />
<br />
Old themes must be updated if they change an image from the default theme: All styles from the default theme which refer to a changed image must be overwritten in the custom theme. This way the URLs resolve to the new image.<br />
<br />
== Variables ==<br />
<br />
Naming of the variables should be straight forward. Variables containing the word ''Background'' will always refer to the background color. Variables containing ''Color'' will refer to the foreground color of an element, like color of a font. ''Hover'' in most cases means "hovered" elements. ''Selected'' relates to the currently selected item. Elements that are supposed to catch the users eye can use the ''Highlight'' class and the variable contains this word.<br />
<br />
=== Basic ===<br />
<br />
==== Font ====<br />
<br />
{|<br />
! Variable || Default || Description <br />
|-<br />
| @sansFontFamily || "Helvetica Neue", Helvetica, Arial, sans-serif<br />
|-<br />
| @serifFontFamily || Georgia, "Times New Roman", Times, serif<br />
|-<br />
| @monoFontFamily || Monaco, Menlo, Consolas, "Courier New", monospace<br />
|-<br />
| @baseFontSize || 14px<br />
|-<br />
| @baseFontFamily || @sansFontFamily<br />
|-<br />
| @baseLineHeight || 20px<br />
|-<br />
| @altFontFamily || @serifFontFamily<br />
|-<br />
| @touchFontSize || 15px<br />
|-<br />
| @headingsFontFamily || inherit<br />
|-<br />
| @headingsFontWeight || bold<br />
|-<br />
| @fontSizeLarge || @baseFontSize * 1.25<br />
|-<br />
| @fontSizeSmall || @baseFontSize * 0.85<br />
|-<br />
| @fontSizeMini || @baseFontSize * 0.75<br />
|-<br />
| @vgridFontSize || 13px<br />
|}<br />
<br />
==== Colors ====<br />
<br />
{|<br />
! Variable || Default || Description <br />
|-<br />
| @bodyBackground || @white<br />
|-<br />
| @textColor || @grayDark<br />
|-<br />
| @linkColor || #08c<br />
|-<br />
| @linkColorHover || darken(@linkColor, 15%)<br />
|-<br />
| @linkAccentColor || #ffad00<br />
|-<br />
| @linkAccentColorHover || darken(@linkAccentColor, 15%)<br />
|-<br />
| @badgeColor || @white<br />
|-<br />
| @badgeBackground || #555<br />
|-<br />
| @headingsColor || inherit<br />
|-<br />
| @black || #000<br />
|-<br />
| @grayDarker || #222<br />
|-<br />
| @grayDark || #333<br />
|-<br />
| @gray || #555<br />
|-<br />
| @grayLight || #aaa<br />
|-<br />
| @grayLighter || #eee<br />
|-<br />
| @white || #fff<br />
|-<br />
| @blue || darken(#049cdb, 5%)<br />
|-<br />
| @blueDark || #0064cd<br />
|-<br />
| @blueLight || lighten(#049cdb, 25%)<br />
|-<br />
| @green || #1A8D1A<br />
|-<br />
| @greenLight || #92D050<br />
|-<br />
| @red || #cc0000<br />
|-<br />
| @yellow || #F8E400<br />
|-<br />
| @orange || #f89406<br />
|-<br />
| @pink || #E01CD9<br />
|-<br />
| @purple || #7E16CF<br />
|-<br />
|}<br />
<br />
==== Space ====<br />
<br />
{|<br />
! Variable || Default || Description<br />
|-<br />
| @paddingLarge || 11px 19px<br />
|-<br />
| @paddingSmall || 2px 10px<br />
|-<br />
| @paddingMini || 0 6px<br />
|-<br />
| @baseBorderRadius || 4px<br />
|-<br />
| @borderRadiusLarge || 6px<br />
|-<br />
| @borderRadiusSmall || 3px<br />
|}<br />
<br />
=== Pagination ===<br />
<br />
Used where pagination is done, for example in the Calendar weekview, each week is on one "page"; one can switch the week using a pagination widget styled with these variables.<br />
<br />
{|<br />
! Variable || Default || Description<br />
|-<br />
| @paginationBackground || #fff<br />
|-<br />
| @paginationBorder || #ddd<br />
|-<br />
| @paginationActiveBackground || #f5f5f5<br />
|}<br />
<br />
=== Buttons ===<br />
<br />
{|<br />
! Variable || Default || Description<br />
|-<br />
| @btnBackground || @white<br />
|-<br />
| @btnBackgroundHighlight || darken(@white, 10%)<br />
|-<br />
| @btnBorder || #bbb<br />
|-<br />
| @btnPrimaryBackground || @linkColor<br />
|-<br />
| @btnPrimaryBackgroundHighlight || spin(@btnPrimaryBackground, 20%)<br />
|-<br />
| @btnInfoBackground || #5bc0de<br />
|-<br />
| @btnInfoBackgroundHighlight || #2f96b4<br />
|-<br />
| @btnSuccessBackground || #62c462<br />
|-<br />
| @btnSuccessBackgroundHighlight || #51a351<br />
|-<br />
| @btnWarningBackground || lighten(@orange, 15%)<br />
|-<br />
| @btnWarningBackgroundHighlight || @orange<br />
|-<br />
| @btnDangerBackground || #ee5f5b<br />
|-<br />
| @btnDangerBackgroundHighlight || #bd362f<br />
|-<br />
| @btnInverseBackground || #444<br />
|-<br />
| @btnInverseBackgroundHighlight || @grayDarker<br />
|}<br />
<br />
=== Dropdowns ===<br />
<br />
{|<br />
! Variable || Default || Description<br />
|-<br />
| @dropdownBackground || @white<br />
|-<br />
| @dropdownBorder || rgba(0,0,0,.2)<br />
|-<br />
| @dropdownDividerTop || #e5e5e5<br />
|-<br />
| @dropdownDividerBottom || @white<br />
|-<br />
| @dropdownLinkColor || @grayDark<br />
|-<br />
| @dropdownLinkColorHover || @white<br />
|-<br />
| @dropdownLinkColorActive || @white<br />
|-<br />
| @dropdownLinkBackgroundActive || @linkColor<br />
|-<br />
| @dropdownLinkBackgroundHover || @dropdownLinkBackgroundActive<br />
|}<br />
<br />
=== Foldertree ===<br />
{|<br />
! Variable || Default || Description <br />
|-<br />
| @foldertreeSidepanelBackground || #333 ||<br />
|-<br />
| @foldertreeSectionTitleColor || #888 || Color for sectiontitles in foldertree (like "Public" folders)<br />
|-<br />
| @foldertreeActiveLabelColor || #ccc || ''Active'' means, user can perform an action on this item<br />
|-<br />
| @foldertreePassiveLabelColor || #ccc || ''Passive'' means, user can '''not''' perform any action with this item <br />
|-<br />
| @foldertreeHoverBackground || #888 ||<br />
|-<br />
| @foldertreeSelectedBackground || #222 ||<br />
|-<br />
| @foldertreeBadgeBackground || @bagdeBackground || see [[#Colors]] for definition of @badgeBackground<br />
|-<br />
| @foldertreeBadgeColor ||@badgeColor || see [[#Colors]] for definition of @badgeBackground<br />
|}<br />
<br />
=== Calendar ===<br />
==== Appointment ====<br />
{|<br />
! Variable || Default || Description <br />
|-<br />
| @appointmentReserved || #08c /* blue */ || Appointment status color<br />
|-<br />
| @appointmentTemporary || #ffbb00 /* yellow */ || Appointment status color<br />
|-<br />
| @appointmentAbsent || #913f3f /* red */ || Appointment status color<br />
|-<br />
| @appointmentFree || #8eb360 /* green */ || Appointment status color<br />
|-<br />
| @appointmentPrivate || #555 /* gray */ || Appointment status color<br />
|-<br />
| @appointmentDeclinedFont || #888 /* dark gray */|| Font color for declined Appointments<br />
|-<br />
| @appointmentUnconfirmedAlpha || 0.4 || Transparency value for unconfirmed Appointments<br />
|-<br />
| @appointmentDeclinedAlpha || 0.3 || Transparency value for declined Appointments<br />
|-<br />
| @appointmentHoverPct || 15% || Percentage increase of the dark pigment content on hover effect<br />
|}<br />
<br />
==== Week View ====<br />
{|<br />
! Variable || Default || Description <br />
|-<br />
| @weekviewAppointmentLasso || #aeaeff || Lasso frame color<br />
|-<br />
| @weekviewDayIn || #fff /* white */ || Default background color in week view<br />
|-<br />
| @weekviewDayOut || #e0e0e0 /* grey */ || Background color outside of the mean working time<br />
|-<br />
| @weekviewTimeline || #f00 /* red */ || Color of the Line indicating the current time<br />
|-<br />
| @weekviewTimeWith || 58px || With of the time labels on the left side<br />
|-<br />
| @calendarToolbarHeight || 41px || Height of the control toolbar <br />
|}<br />
<br />
==== Month View ====<br />
{|<br />
! Variable || Default || Description <br />
|-<br />
| @monthviewAppointmentOut || #aaa /* light gray */ || Color of appointments, which are not in focus<br />
|-<br />
| @monthviewToday || #daefff /* light blue */|| Background color of the current day<br />
|-<br />
| @calendarToolbarHeight || 41px || Height of the control toolbar<br />
|}<br />
<br />
== Area names ==<br />
<br />
The variables sometimes refer to common areas. To identify which area is located where, see the following annotated screenshots.<br />
<br />
[[File:Colors_mail.png|800px||Mail application]]<br />
<br />
[[File:Colors_launchpad.png|800px||Launchpad application]]<br />
<br />
== Replacing the logo ==<br />
<br />
One of the most common theme changes which requires editing <code>style.css</code> is changing the logo in the top right corner. The logo is displayed as the background image for an element with the ID <code>io-ox-top-logo-small</code>. A theme can therefore change the size and URL of the image:<br />
#io-ox-top-logo-small {<br />
width: 60px;<br />
height: 22px;<br />
margin: 8px 13px 0 13px;<br />
background-image: url(mylogo.png);<br />
}<br />
The file <code>mylogo.png</code> is expected to be in the same directory as <code>style.css</code>. If you want to place the image somewhere else, then use a relative path in <code>url()</code>.<br />
<br />
Remember that images in OX App Suite are served by the web server and not by the application server. This means that images need to be packaged separately (for dedicated web servers) and installed in <code>/var/www/appsuite/</code> (or similar, depending on the target platform) instead of <code>/opt/open-xchange/appsuite/</code>. Direct support for multiple packages is coming in version 7.4.1. Until then, use the build system from the <code>develop</code> branch to [[AppSuite:UI_build_system#init-packaging|initialize the packaging]] if your theme contains images.<br />
<br />
== Mixins ==<br />
In LESS, it is possible to include a bunch of properties from one ruleset into another ruleset. So say we have the following class:<br />
<br />
=== Sample ===<br />
<pre class="language-css"><br />
.border-radius(@radius: 0px) {<br />
-webkit-border-radius: @radius;<br />
-moz-border-radius: @radius;<br />
-ms-border-radius: @radius;<br />
border-radius: @radius;<br />
}<br />
<br />
#menu a {<br />
color: #111;<br />
.border-radius(5px);<br />
}<br />
</pre><br />
<br />
Read [http://www.lesscss.org/#-mixins LESS Mixins]<br />
<br />
=== global OX Mixins ===<br />
<br />
they can be found at [[#definitions.less | definitions.less]]<br />
<br />
{|<br />
! Mixin || Sample || Description <br />
|-<br />
| .box-sizing(@boxmodel) || .box-sizing(border-box) ||<br />
|-<br />
| .user-select(@select) || .user-select(none) ||<br />
|-<br />
| .border-radius(@radius) || .border-radius(3px) ||<br />
|-<br />
| .box-shadow(@shadow) || .box-shadow(3px) ||<br />
|-<br />
| .vertical-gradient(@startColor, @endColor) || .vertical-gradient(#888, #555) ||<br />
|-<br />
| .radial-gradient(@color1, @color2, @color3) || .radial-gradient(#111, #222, #333) ||<br />
|-<br />
| .transition(@transition) || .transition(background-color 0.2s linear) ||<br />
|-<br />
| .animation(@animation) || .animation(slidein 300ms) ||<br />
|-<br />
| .animation-name(@name) || .animation-name(slideright) ||<br />
|-<br />
| .ellipsis || .ellipsis ||<br />
|-<br />
| .overflow(@type) || .overflow(hidden) ||<br />
|-<br />
| .overflow-x(@type) || .overflow-x(hidden) ||<br />
|-<br />
| .overflow-y(@type) || .overflow-y(hidden) ||<br />
|-<br />
| .backface-visibility(@type) || .backface-visibility(hidden) ||<br />
|}<br />
<br />
== How to activate a theme during development ==<br />
<br />
When creating a new theme, you will want to test changes quickly without building packages reinstalling them. The trick is to use [[Appsuite:Appserver|appserver]].<br />
<br />
# First, you need to add the theme to the list of available themes on the backend. Simply create a new file in <code>/opt/open-xchange/etc/settings/</code> with the extension <code>.properties</code> and add a line for your theme to it: <pre&lt;noinclude&gt;&lt;/noinclude&gt;>io.ox/core/settingOptions//themes/<var>ID</var>=<var>Theme Name</var></pre&lt;noinclude&gt;&lt;/noinclude&gt;> Replace <var>ID</var> by the identifier (directory name) of your theme, and <var>Theme Name</var> by the human-readable name which should appear in the UI.<br />
# The server needs to be restarted to read the new settings.<br />
# Now, you can use <code>appserver</code> ([[AppSuite:appserver#Use_with_Apache|with a local web server]] if your theme includes images) to get your theme in combination with the UI which is already installed on the backend.<br />
# Finally, activate your theme the list in the <code>Settings -> Basic</code> view behind the option <code>Theme</code>.<br />
<br />
In case you also want to access the same backend without <code>appserver</code> while your theme is selected, that theme (or at least some empty <code>.less</code> files) should be also installed on the backend to avoid errors. To just use an empty theme, run the following as root:<br />
touch /opt/open-xchange/appsuite/apps/themes/<var>ID</var>/definitions.less<br />
touch /opt/open-xchange/appsuite/apps/themes/<var>ID</var>/style.less<br />
/opt/open-xchange/appsuite/share/update-themes.sh<br />
The value of <var>ID</var> here must be the same as in your <code>.properties</code> file.<br />
<br />
== Favicons and mobile homescreen icons ==<br />
'''Note''': This chapter is not about changing AppSuite icons which are used in the application like the brand on the upper right.<br />
<br />
'''This documentation applies for AppSuite v.7.4.2'''<br />
<br />
AppSuite ships with a standard set of icons containing a<br />
# favicon<br />
# set of touch icons which are mainly used by mobile Safari on iOS<br />
<br />
These icons are used as default for all devices and browsers as long as you don't deliver your own icons with your theme. <br />
<br />
=== Favicon ===<br />
All major browsers support the use of a favicon. The favicon is a pixel image with the size of 16x16 (32x32) and the "ico" file ending. (see [http://en.wikipedia.org/wiki/Favicon Wikipedia Favicon] for details).<br />
<br />
You should provide your custom favicon within your custom theme. If you do not add a custom favicon to your theme the global OX default will be used. The default icon is located under <tt>apps/themes/icons/default</tt> on the web server.<br />
<br />
=== Apple touch icons ===<br />
iOS devices (iPhone/iPad/iPod) support so called "Webclips". Webclips are bookmarks to websites or webapps which provide a App Icon that is shown on the iOS homescreen. AppSuite offers full support for Webclips by providing all needed App icons, splashscreens and full screen support. If a user uses the "Add to homescreen" button on his iOS device, a Webclip is created, taking the right icon for his current device. Most devices need custom resolutions of the Webclip icon in the '''png''' format.<br />
<br />
* iPhone 3: 57 x 57 px<br />
* iPhone 4 retina: 114x114 px<br />
* iPhone iPhone 5 retina: 120 x 120 px<br />
* iPad: 72 x 72 px<br />
* iPad (iOS 7): 76 x 76px<br />
* iPad retina: 144 x 144 px <br />
* iPad retina (iOS 7): 152 x 152 px <br />
<br />
Furthermore a fullscreen Webclip App will show a splashscreen, a jpg file that is displayed on startup during app load. There are currently three different resolutions as jpg files available. '''Note''': Splashscreens must be JPG files<br />
<br />
* iPhone: 320 x 460 px<br />
* iPhone 4: 640 x 920 px<br />
* iPhone 5: 640 x 1096 px<br />
<br />
'''Note''': We do not provide splashscreens for iPad<br />
<br />
This list may change with Apple's iOS updates. We recommend providing all of this resolutions when customizing the Webclip icons and splashscreens, even if some iOS devices use the next best resolution for an icon if a certain file is missing.<br />
<br />
=== Providing custom icons ===<br />
To provide custom Webclip icons locate the following path in your AppSuite installation:<br />
pathToAppSuite/apps/themes/icons/default<br />
<br />
This folder contains all OX default icons for Webclips icons and splashscreens. Use these as samples for your own versions.<br />
<br />
A clean installation will have all our default icons in the "default" directory. To customize the icons we recommend using our default icons as samples and save your customized version in your theme. '''Note''': The filename has to be the same as in the default folder. Otherwise the fallback will be applied and the default icons will be used. If more advanced rewriting is needed one should edit the contents of the <tt>.htaccess</tt> file located under <tt>apps/themes</tt><br />
<br />
== Theming the login page ==<br />
<br />
The login page is a little bit special. If you don’t use the [[Open-Xchange_servlet_for_external_login_masks|form login]] and provide your own login page, you might want to theme the login page, too. [[AppSuite:Theming the login page|Learn how to do this here]].<br />
<br />
=== Providing domain based login themes ===<br />
<br />
If you have a multibrand installation and you want to deliver not only custom themes but also custom login-themes this can be done via Apache mod_rewrite. You can do so by a domain-based rewrite rule to deliver custom themes to a user based on the URI he's using. The needed config file <tt>.htaccess</tt> is located under <tt>apps/themes</tt><br />
<br />
<pre><br />
# Sample config for domain based login theme<br />
RewriteCond %{HTTP_HOST} ^www\.domain\.com$<br />
RewriteCond %{REQUEST_FILENAME} -f<br />
RewriteRule ^login/(.*)$ domain_com_logintheme/$1 [L]<br />
</pre><br />
<br />
== Best practice ==<br />
<br />
To be really safe, it’s best to only define your own values for the variables shown above. If this really breaks anything, we consider this a bug, please report it [https://bugs.open-xchange.com/] in our bugzilla.<br />
<br />
Of course, using CSS in <code>style.less</code> file to define your own styles is also possible. Make sure to test your style in such cases more carefully. It is most likely safe to change minor things using this file, but if you plan to change any positions of larger elements, this might break the complete design. So please be careful when overwriting the default CSS rules.<br />
<br />
== Links ==<br />
[http://bradfrost.github.io/this-is-responsive/resources.html Responsive design]<br />
<br />
[http://lesscss.org/ LESS]<br />
<br />
== Caveats ==<br />
<br />
It is '''not''' recommended to change the size of elements or their position. If you really want to do so, please check on all devices and in all browsers and make sure you didn’t break anything. You even have to be careful when changing the font, because this might have effects on positioning, too.<br />
<br />
As mentioned before, changing colors should be safe.<br />
<br />
[[Category:AppSuite]]<br />
[[Category:UI]]</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:Date_and_time&diff=16637AppSuite:Date and time2013-12-03T16:31:15Z<p>Viktor.Pracht: Moved the introduction</p>
<hr />
<div>{{Stability-experimental}}<br />
<br />
<div class="title">Date and Time</div><br />
<br />
The handling of date and time is a complicated mess of historical conventions, which are still changed from time to time by governments around the world. To keep this away from day-to-day activities of developers, the OX App Suite platform provides the module date, which performs conversion between different time zones, formatting and parsing of date and time values.<br />
<br />
__TOC__<br />
<br />
The examples in this article use some global variables. For the examples to work the way they are intended, you will first need to load the [[AppSuite:I18n | gettext module]] and the date module and store them in variables <tt>gettext</tt> and <tt>date</tt>.<br />
<br />
<pre class="language-javascript"><br />
var gettext;<br />
var date;<br />
require(['gettext!example', 'io.ox/core/date']).done(function (gt, d) {<br />
gettext = gt;<br />
date = d;<br />
}); <br />
</pre><br />
<br />
In real code, you should not use global variables. Instead, you would use the <tt>gt</tt> and <tt>d</tt> parameters directly, without storing them in another variable.<br />
<br />
== Time Zones ==<br />
<br />
The built-in JavaScript class Date supports calculations using UTC and the operating system's local time zone. Unfortunately, this is not enough. Examples include using a time zone different from the time zone of the client system, or displaying times in multiple time zones at once.<br />
<br />
The class Local is almost a drop-in replacement for Date, with the main difference being that it operates in the default time zone of the OX App Suite user, even if it is different from the time zone of the browser's operating system. The following code displays the current date and time. It will show a different time when called after changing the user's time zone.<br />
<br />
<pre class="language-javascript"><br />
alert(new date.Local());<br />
</pre><br />
<br />
To work with other time zones, the function <tt>getTimeZone()</tt> can be used to create replacement classes similar to Local, which are all descendants of the private class LocalDate (for which all methods are documented below). Since the time zone definitions are loaded on-demand, the function returns a jQuery promise, which is resolved to the class constructor once the time zone definition is loaded. This class can then be used to e.g. convert between time zones.<br />
<br />
<pre class="language-javascript"><br />
date.getTimeZone('America/New_York').done(function (NewYork) {<br />
alert(gettext('New York celebrated New Year\'s at %1$s',<br />
new date.Local(new NewYork(2012, 0, 1))));<br />
});<br />
</pre><br />
<br />
The function getTimeZone() is memoized for performance reasons, i.e. multiple calls with the same argument will return the same promise and will therefore resolve to the same class object.<br />
<br />
== Formatting ==<br />
<br />
The default <tt>LocalDate.prototype.toString()</tt> method displays the full date and time, including the day of week and the time zone. To allow better control of the resulting string, the method <tt>LocalDate.prototype.format()</tt> accepts a set of format flags. The flags determine, which fields should be included in the output. Currently, there are four flags:<br />
<br />
<pre class="language-javascript"><br />
var d = new date.Local();<br />
alert(d.format(date.DATE));<br />
alert(d.format(date.TIME));<br />
alert(d.format(date.DAYOFWEEK));<br />
alert(d.format(date.TIMEZONE));<br />
</pre><br />
<br />
Multiple flags can be combined by adding them, or by using one of the predefined combination constants. Not all possible combinations produce unique results. When DAYOFWEEK is specified together with any other fields, DATE is automatically included in the output. Similarly, TIMEZONE implies TIME when used with other fields.<br />
<br />
<pre class="language-javascript"><br />
var d = new date.Local();<br />
assert(d.format(date.DAYOFWEEK + date.TIMEZONE) === d.format(date.FULL_DATE);<br />
</pre><br />
<br />
The format flags select one of several predefined format strings, which is stored in the current locale settings. This frees both the developers and the translators from having to remember arcane letter combinations.<br />
<br />
For the case that even finer control of the generated output is required, LocalDate.prototype.format() accepts a format string directly. The syntax of the format strings is a subset of CLDR date format patterns. Format specifiers which are not used in the Gregorian calendar will be implemented on-demand.<br />
<br />
<pre class="language-javascript"><br />
alert(new date.Local().format('EEEE'));<br />
</pre><br />
<br />
In general, if format strings are required, this indicates that the current date API should be extended. Feedback is always welcome.<br />
<br />
One situation where direct access to format strings is useful, is the manipulation of the localized format strings, e.g. to decorate individual fields in a displayed date with HTML markup. To achieve this, the localized format string is retrieved with getFormat(), and parts of it passed individually to LocalDate.prototype.format().<br />
<br />
<pre class="language-javascript"><br />
// Get the original format string.<br />
var fmt = date.getFormat(date.FULL_DATE);<br />
<br />
// Regular expression to parse the format string.<br />
// . . ( time zone )|quote|'quoted text'|rest<br />
var re = /(v+|V+|z+|Z+)|(?:''|'(?:[^']|'')*'|[^vVzZ'])+/g;<br />
<br />
// Appends a formatted date to a jQuery node and returns<br />
// the time zone as a separate node.<br />
function decorateTimeZone(d, parent) {<br />
var span;<br />
fmt.replace(re, function (match, tz) {<br />
if (tz) { // found the time zone field<br />
// Wrap the formatted time zone in a <span> element.<br />
span = $('<span>').text(d.format(match));<br />
parent.append(result);<br />
} else {<br />
// Append all other formatted text as plain text nodes.<br />
parent.append($.txt(d.format(match)));<br />
}<br />
});<br />
// Return the wrapped field for further customization.<br />
return span;<br />
}<br />
</pre><br />
<br />
''Does anybody want this use case as an API function?''<br />
<br />
== Intervals ==<br />
<br />
In addition to formatting individual dates, LocalDate instances can format intervals. The difference to simply inserting two dates into a translated string is that short intervals may have a compacter representation, e.g. 'Jan 1–10, 2012' instead of 'Jan 1, 2012 – Jan 10, 2012'.<br />
<br />
<pre class="language-javascript"><br />
var start = new date.Local(), end = new date.Local(start);<br />
end.add(date.DAY);<br />
alert(start.formatInterval(end, date.DATE));<br />
</pre><br />
<br />
The methods LocalDate.prototype.formatInterval() and LocalDate.prototype.getIntervalFormat() are used like LocalDate.prototype.format() and getFormat(), with two differences. First, the interval functions accept the end of the interval as first parameter before the format flags. And second, since the format string depends on the actual interval, LocalDate.prototype.getIntervalFormat() is a member function and requires the same end value as used later for LocalDate.prototype.formatInterval().<br />
<br />
== Parsing ==<br />
<br />
Parsing is the reverse of formatting, except that ideally, users should be able to enter almost anything, as long as it is not ambiguous. The practice looks a bit more restricted. The LocalDate.parse() function takes a format parameter like the formatting functions, and expects the parsed string to match it very closely.<br />
<br />
<pre class="language-javascript"><br />
var input = prompt(gettext('Please enter a date'), '');<br />
var d = date.Local.parse(input, date.DATE);<br />
alert(gettext('I understood %1$s', d);<br />
</pre><br />
<br />
If there is demand, we can implement some heuristics. There are a lot of abstract algorithm descriptions in the standards, which describe how to parse almost anything while using the format string only as disambiguation help.<br />
<br />
== Manipulation of LocalDate objects ==<br />
<br />
Since the LocalDate class is designed as a drop-in for the Date class, its instances support getter and setter methods for all fields of a date. They can be used to modify an existing LocalDate object, e. g. to round a date to the nearest day or hour.<br />
<br />
<pre class="language-javascript"><br />
var start = new date.Local(), end = new date.Local(start);<br />
start.setHours(0, 0, 0, 0);<br />
end.setHours(24, 0, 0, 0);<br />
alert(gettext('Today is %1$s', start.formatInterval(end)));<br />
</pre><br />
<br />
One manipulation, which is often needed in calendars, is iteration over time. This operation seems simple, at least for iteration steps with a constant duration like hours, days or weeks. One just needs to add the step duration to the timestamp. While there is a method to do exactly this, LocalDate.prototype.addUTC(), you will encounter problems as soon as the iteration transcends a daylight savings switch. First, days and weeks are not actually constant. And second, sometimes the iteration might need to follow the displayed 'wall clock' time instead of the physical time. For these cases, the method LocalDate.prototype.add() increments the local time instead of the UTC time. Both methods accept an increment value in milliseconds, which can also be negative. There are predefined constants for the most common (almost-)fixed-duration periods.<br />
<br />
<pre class="language-javascript"><br />
var d = new date.Local(2012, 2);<br />
for (; d.getMonth() < 3; d.add(date.DAY)) {<br />
// Display a day in a month view.<br />
}<br />
</pre><br />
<br />
Iteration with larger intervals like months and years has the additional difficulty, that a single numeric parameter like 30 * date.DAY cannot be interpreted as a month, because it might be just really 30 days. To solve this, there are separate methods for months and years: LocalDate.prototype.addMonths() and LocalDate.prototype.addYears(). They accept the number of months, respective years as parameter.<br />
<br />
<pre class="language-javascript"> <br />
var d = new date.Local(2012, 0);<br />
for (; g.getYear() < 2013; d.addMonths(1)) {<br />
// Display a month in a year view.<br />
}<br />
</pre><br />
<br />
Finally, most calendars default to displaying the current date, and therefore need to figure out the iteration range based on an arbitrary point inside that range. In most cases, the start can be computed by simply calling the appropriate setters with all zeros as parameters to find the start of the range, and adding the range duration to find the end. One exception is the week. There is no setter for the day of the week. Instead, the method LocalDate.prototype.setStartOfWeek() can be used to find the start of a week.<br />
<br />
<pre class="language-javascript"> <br />
// Find the start and the end of the current week<br />
var d = new date.Local().setStartOfWeek();<br />
var end = new date.Local(start).add(date.WEEK);<br />
// Iterate over the week<br />
for (; d < end; d.add(date.DAY)) {<br />
// Display a day in a week view.<br />
}<br />
</pre><br />
<br />
In addition to explicit method calls, the JavaScript standard method LocalDate.prototype.valueOf() allows native comparison, addition and subtraction operators to work on LocalDate objects. The result of LocalDate.prototype.valueOf(), and therefore of addition and subtraction, is a timestamp, which can be passed to the LocalDate constructor to get a LocalDate object again.<br />
<br />
<pre class="language-javascript"> <br />
var start = date.Local.parse(prompt(gettext('Start date'), ''));<br />
var end = date.Local.parse(prompt(gettext('End date'), ''));<br />
if (end < start) alert(gettext('Invalid date range!'));<br />
</pre><br />
<br />
== Differences between LocalDate and Date ==<br />
<br />
The LocalDate classes duplicate most of the Date API with a few exceptions:<br />
<br />
* The constructor can not be called as a function. The Date constructor does in this case nothing useful anyway.<br />
* The constructor always uses full years, it does not add 1900 for years 0 to 99.<br />
* Date.UTC() should not be necessary, but since it returns a numeric timestamp and has nothing to do with time zones, it can still be used directly.<br />
* Except for LocalDate.prototype.toString(), all to*String() methods are replaced by LocalDate.prototype.format().<br />
* There are no UTC variants of getters and setters. They should not be necessary. But just in case, you can still use a LocalDate class for the time zone 'UTC' instead.<br />
* The getter and setter for the year are called getYear and setYear instead of getFullYear and setFullYear since we have no legacy code with Y2K issues.<br />
* Setters return the modified object instead of the timestamp. This is useful for chaining of method calls.<br />
* Date.prototype.getTimeZoneOffset() should not be necessary, since hiding these details is the whole point of the date module. If still necessary, LocalDate.getTTInfo() can be used instead.<br />
<br />
== API Reference ==<br />
<br />
This section provides a short reference of the date API.<br />
<br />
=== Locale ===<br />
<br />
A locale describes the localization settings which usually depend not only on the language, but also on the region and optionally even on the personal preferences of the user. The locale object is loaded at startup and provides various settings and translations.<br />
<br />
Various arrays containing translations can be used directly without any other date function.<br />
<br />
locale.dayPeriods<br />
A map from an identifier of a day period to the corresponding translation. The members am and pm are used in the 12h time format, but other members may be useful for greetings. Is anyone interested in a function which returns the correct greeting period for a given time? If not, maybe remove everything except AM and PM?<br />
locale.days<br />
An array with translated full names of days of the week, starting with Sunday. CLDR context: "format", CLDR width: "wide".<br />
locale.daysShort<br />
An array with translated abbreviated names of days of the week, starting with Sunday. CLDR context: "format", CLDR width: "abbreviated".<br />
locale.daysStandalone<br />
An array with translated standalone names of days of the week, starting with Sunday. CLDR context: "standalone", CLDR width: "abbreviated".<br />
locale.eras<br />
An array with translated abbreviations for the two eras of the Gregorian calendar: BC and AD (in that order).<br />
locale.months<br />
An array with translated full names of months. CLDR context: "format", CLDR width: "wide".<br />
locale.monthsShort<br />
An array with translated abbreviated names of months. CLDR context: "format", CLDR width: "abbreviated".<br />
Diverse week-based calculations need to know on which day the week starts and how the first week of the year is defined.<br />
<br />
locale.daysInFirstWeek<br />
The lowest number of days of a week which must be in the new year for that week to be considered week number 1. Common values are<br />
* 1 if the week of January 1st is week number 1,<br />
* 4 if the first week which has most of its days in the new year is week number 1.<br />
* 7 if the first week which starts in the new year is week number 1.<br />
locale.weekStart<br />
First day of the week. Common values are<br />
* 0 for Sunday,<br />
* 1 for Monday.<br />
Deprecated and internal fields should not be used since they can change or disappear entirely without notice. They are still documented here for completeness.<br />
<br />
locale.date<br />
Deprecated, use DATE instead.<br />
locale.dateTime<br />
Deprecated, use DATE_TIME instead.<br />
locale.dateTimeFormat<br />
The default format used to combine a time (%1$s) and a date (%2$s). Not used yet, will probably disappear.<br />
locale.formats<br />
A map from various canonical sets of format fields to the corresponding localized format strings. Used mainly by getFormat(). Maybe remove it from the public interface after loading, since it's internal?<br />
locale.h12<br />
A boolean indicating whether the 12h format is used. WANTED: a better name.<br />
locale.intervals<br />
A map from various canonical sets of format fields to the corresponding formatting rules. A formatting rule is a map from the largest field, which is different between the start and end of the interval, to the corresponding localized formatting string. The field is specified as a single lower case letter. The formatting string is split at the first repeating field. The first part is formatted using the start of the interval, the second part is formatted using the end of the interval. Used mainly by LocalDate.prototype.getIntervalFormat(). Maybe remove it from the public interface after loading, since it's internal?<br />
locale.intervals.fallback<br />
The default format string to combine the start (%1$s) and end (%2$s) of an interval when none of the other members of locale.intervals apply. Maybe remove it from the public interface after loading, since it's internal?<br />
locale.time<br />
Deprecated, use TIME instead.<br />
getTimeZone<br />
<br />
The main entry points of the date API are the class Local which replaces Date for use with the user's default time zone and a function to generate similar classes for arbitrary time zones.<br />
<br />
getTimeZone(name)<br />
Creates a LocalDate class which operates in the specified time zone. Multiple calls with the same name will return the same object.<br />
name String - The name of the requested time zone. It must be one of the values returned by api/config/availableTimeZones.<br />
Returns Promise - A promise which resolves to a LocalDate class which uses the requested time zone.<br />
Local<br />
A convenience LocalDate class which uses the user's current time zone.<br />
<br />
=== LocalDate ===<br />
<br />
The core of the date API is the abstract class LocalDate which is the superclass of time zone specific classes. The class itself is not publically available, only its subclasses can be created by calling getTimeZone(). The subclasses and their instances are referred to as LocalDate classes and LocalDate objects.<br />
<br />
The constructor mimics the behavior of the Date class, but it can't be called as a function.<br />
<br />
<pre class="language-javascript"> <br />
new LocalDate()<br />
new LocalDate(timestamp)<br />
new LocalDate(year, month, date, hours, minutes, seconds, ms)<br />
</pre><br />
<br />
The constructor accepts the same parameters as the Date constructor.<br />
The entire functionality of the class is based on a few low level functions. They should not be necessary outside the date module itself, assuming the API is complete. If you find you need these functions, please let's extend the high level APIs instead.<br />
<br />
LocalDate.getTTInfo(t)<br />
Returns the GMT offset, daylight savings and the abbreviation of the time zone which are in effect at the specified time.<br />
t Timestamp - The timestamp.<br />
Returns { gmtoff, isdst, abbr } - An object with the GMT offset in milliseconds, whether daylight savings are in effect (0 or 1, not a real boolean) and the abbreviation like 'CET' (!isdst) or 'CEST' (!!isdst).<br />
LocalDate.getTTInfoLocal(t)<br />
* Returns the GMT offset, daylight savings and the abbreviation of the time zone which are in effect at the specified local time. If the local time is ambiguous or invalid, the same fallbacks as for LocalDate.utc() are used. (It is actually implemented as a wrapper for this function.)<br />
* t Number - The local time.<br />
* Returns { gmtoff, isdst, abbr } - An object with the GMT offset in milliseconds, whether daylight savings are in effect (0 or 1, not a real boolean) and the abbreviation like 'CET' (!isdst) or 'CEST' (!!isdst).<br />
<br />
LocalDate.localTime(t)<br />
* Converts a UTC timestamp to local time.<br />
* t Timestamp - The UTC timestamp to convert.<br />
* Returns Number - A local time which is used in computations of date and time components.<br />
<br />
LocalDate.utc(t)<br />
* Converts local time to a UTC timestamp. If the local time is ambiguous because of a DST switch, the local time is interpreted as before the switch. E.g. 02:30 at the end of DST is interpreted as DST. If the local time is invalid because of a DST switch, the local time is interpreted as if the switch already occurred. E.g. 02:30 at the start of DST returns the same timestamp as 01:30 before the switch.<br />
* t Number - The local time to convert.<br />
* Returns Timestamp - The corresponsing UTC timestamp.<br />
Metadata about a time zone is stored directly on the LocalDate object.<br />
<br />
LocalDate.id<br />
* Original name used to retrieve this time zone.<br />
<br />
LocalDate.displayName<br />
* A human-readable name of this time zone as provided by the config module under "availableTimeZones".<br />
* Parsing of date and time strings as entered by a user is done using format flags from Constants. The current implementation expects the string to match the corresponding localized format string pretty closely. Any difficulties with parsing common entered dates and times should be taken as an opportunity to extend the parsing heuristics.<br />
<br />
LocalDate.parse(string, format)<br />
* Parses a string using either the specified format string or localized version of one of predefined format strings selected by format flags.<br />
* string String - The string to parse.<br />
* format String or Number - Either a format string with the syntax of CLDR date format patterns, or one of the format flag constants. In the second case, the actual format string is localized for the current user's locale according to locale.formats.<br />
* Returns LocalDate or null - A new LocalDate object which represents the parsed date and time or null if the string could not be parsed.<br />
* Methods of LocalDate instances can be grouped into several categories. The first are the setters and getters for individual fields from Date. Since each LocalDate class has its own time zone, There are no UTC variants of each getter and setter. They all work with local time.<br />
<br />
<pre class="language-javascript"> <br />
LocalDate.prototype.getYear()<br />
LocalDate.prototype.getMonth()<br />
LocalDate.prototype.getDate()<br />
LocalDate.prototype.getHours()<br />
LocalDate.prototype.getMinutes()<br />
LocalDate.prototype.getSeconds()<br />
LocalDate.prototype.getMilliseconds()<br />
</pre><br />
* Return the corresponding field of the local date or time.<br />
* Returns Number - The requested field, as a number.<br />
<br />
<pre class="language-javascript"> <br />
LocalDate.prototype.setYear(year, month, date)<br />
LocalDate.prototype.setMonth(month, date)<br />
LocalDate.prototype.setDate(date)<br />
LocalDate.prototype.setHours(hour, min, sec, ms)<br />
LocalDate.prototype.setMinutes(min, sec, ms)<br />
LocalDate.prototype.setSeconds(sec, ms)<br />
LocalDate.prototype.setMilliseconds(ms)<br />
</pre><br />
* Set the specified date or time fields. Any unspecified fields retain their current value. Values outside of the specified ranges will result in overflow to the neighboring periods and can therefore be used for date arithmetic.<br />
** year Number - The year.<br />
** month Number - The month. Values range from 0 for January to 11 for December.<br />
** date Number - The date. Values range from 1 to 31.<br />
** hour Number - The hours. Values range from 0 to 23.<br />
** min Number - The minutes. Values range from 0 to 59.<br />
** sec Number - The seconds. Values range from 0 to 59.<br />
** ms Number - The milliseconds. Values range from 0 to 999.<br />
<br />
LocalDate.prototype.getDay()<br />
* Returns Number - The day of the week. Values range from 0 for Sunday to 6 for Saturday.<br />
<br />
LocalDate.prototype.getTimeZone()<br />
* This method is not present in Date. It returns the abbreviation of the specific time zone. The abbreviation indicate the GMT offset and is therefore different between daylight savings time and standard time.<br />
* Returns String - The abbreviation of the specific time zone.<br />
* Other getters and setters work with the entire timestamp and not just individual fields.<br />
<br />
LocalDate.prototype.getDays()<br />
* Returns the day number of this object. This may be useful to find the start of the same day (by multiplying the result with DAY).<br />
* Returns Number - The number of days since 1970-01-01 in this object's time zone.<br />
<br />
LocalDate.prototype.getTime()<br />
* Returns Timestamp - The UTC timestamp of this object.<br />
<br />
LocalDate.prototype.setTime(time)<br />
* Sets the UTC timestamp to a new value.<br />
* time Timestamp - The new UTC timestamp of this object.<br />
* While setters can be used to perform date arithmetic, LocalDate provides convenience functions for the most frequent cases of adding and subtracting a time period and finding the start of a week.<br />
<br />
LocalDate.prototype.add(time)<br />
* Adds or subtracts a time period in local time. The results may be invalid if the end result ends up in the middle of a daylight savings switch.<br />
* time Number - The time period to add, in milliseconds. Use negative values to subtract. See also Constants.<br />
* Returns this - This object for chaining.<br />
<br />
LocalDate.prototype.addUTC(time)<br />
* Adds or subtracts a physical time period, i.e. simply increments the timestamp.<br />
time Number - The time period to add, in milliseconds. Use negative values to subtract. See also Constants.<br />
* Returns this - This object for chaining.<br />
<br />
LocalDate.prototype.addMonths(months)<br />
* Adds or subtracts a number of months in local time. The results may be invalid if the end result ends up in the middle of a daylight savings switch.<br />
months Number - The number of months to add. Use negative values to subtract.<br />
Returns this - This object for chaining.<br />
<br />
LocalDate.prototype.addYears(years)<br />
* Adds or subtracts a number of years in local time. The results may be invalid if the end result ends up in the middle of a daylight savings switch.<br />
years Number - The number of years to add. Use negative values to subtract.<br />
* Returns this - This object for chaining.<br />
<br />
LocalDate.prototype.setStartOfWeek()<br />
* Sets the date to the start of the same week as determined by locale.weekStart. The time is reset to midnight.<br />
* Returns this - This object for chaining.<br />
* Formatting functions implement the conversion of dates and intervals into localized strings which are suitable for direct presentation to the user.<br />
<br />
LocalDate.prototype.format(format)<br />
* Formats the date according to the specified format flags or format string.<br />
* format String or Number - Either a format string with the syntax of CLDR date format patterns, or one of the format flag constants. In the second case, the actual format string is localized for the current user's locale according to locale.formats. The default value is DATE_TIME.<br />
* Returns String - This object formatted according to the specified format.<br />
<br />
LocalDate.prototype.getIntervalFormat(end, format)<br />
* Returns a format string for a time interval with this object as the start and another LocalDate object as the end.<br />
* end LocalDate - The end of the interval.<br />
* format String or Number - Either a format string with the syntax of CLDR date format patterns, or one of the format flag constants. In the second case, the actual format string is localized for the current user's locale according to locale.intervals and locale.formats. The default value is DATE_TIME.<br />
* Returns String - The format string for the interval accorging to the specified format.<br />
<br />
LocalDate.prototype.formatInterval(end, format)<br />
* Formats an interval with this object as the start and another LocalDate object as the end.<br />
end LocalDate - The end of the interval.<br />
format String or Number - Either a format string with the syntax of CLDR date format patterns, or one of the format flag constants. In the second case, the actual format string is localized for the current user's locale according to locale.intervals and locale.formats. The default value is DATE_TIME.<br />
* Returns String - The interval formatted accorging to the specified format.<br />
* Finally, the JavaScript standard conversion functions allow easy debugging and arithmetic on timestamps.<br />
<br />
LocalDate.prototype.toString()<br />
* Converts this object to a string using this.format(FULL_DATE).<br />
* Returns String - The string representation of this object.<br />
<br />
LocalDate.prototype.valueOf()<br />
* Converts this object to a primitive value by returning the UTC timestamp. This can be used for arithmetic directly on LocalDate objects and as the single parameter to new LocalDate().<br />
* Returns Timestamp - The UTC timestamp of this object.<br />
<br />
=== Constants ===<br />
<br />
All date classes operate on timestamps expressed as milliseconds since the UNIX epoch, 1970-01-01 00:00 UTC. The date module defines constants for common time intervals with a constant duration.<br />
<br />
SECOND<br />
Number of milliseconds in a second.<br />
MINUTE<br />
Number of milliseconds in a minute.<br />
HOUR<br />
Number of milliseconds in an hour.<br />
DAY<br />
Number of milliseconds in a day.<br />
WEEK<br />
Number of milliseconds in a week.<br />
<br />
Format flags for parsing and formatting functions are defined as constants. Multiple flags can be combined via addition or bitwise ORing.<br />
<br />
<pre class="language-javascript"> <br />
DAYOFWEEK<br />
Day of the week<br />
DATE<br />
Date<br />
TIME<br />
Time<br />
TIMEZONE<br />
Timezone<br />
</pre><br />
Valid format flag combinations have dedicated constants. In a combination, DAYOFWEEK implies DATE and TIMEZONE implies TIME.<br />
<br />
<pre class="language-javascript"> <br />
DAYOFWEEK_DATE<br />
DAYOFWEEK + DATE<br />
DATE_TIME<br />
DATE + TIME<br />
DAYOFWEEK_DATE_TIME<br />
DAYOFWEEK + DATE + TIME<br />
TIME_TIMEZONE<br />
TIME + TIMEZONE<br />
DATE_TIME_TIMEZONE<br />
DATE + TIME + TIMEZONE<br />
FULL_DATE<br />
DAYOFWEEK + DATE + TIME + TIMEZONE<br />
Miscellaneous<br />
</pre><br />
See [[#Formatting|Formatting]] for usage of this function.<br />
<br />
getFormat(format)<br />
* Returns the localized format string for the specified format flags.<br />
format String or Number - Either a format string with the syntax of CLDR date format patterns, or one of the format flag constants. In the second case, the actual format string is localized for the current user's locale according to locale.formats. The default value is DATE_TIME.<br />
* Returns String - The localized format string which corresponds to the specified format flags. If format is a string, that string is returned unmodified.<br />
<br />
[[Category:AppSuite]][[Category:UI]]</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=ConfigCascade&diff=16591ConfigCascade2013-11-29T11:16:12Z<p>Viktor.Pracht: /* UI Properties */</p>
<hr />
<div>= Introduction to the config cascade =<br />
<br />
The config cascade is a configuration system that allows administrators to selectively override configuration parameters on context and user level. This means a configuration option can vary between groups of contexts, specific contexts or users.<br />
<br />
== Who should read this document? ==<br />
<br />
If you are tasked with designing and maintaining the configuration of an OX server or cluster, information contained in this document will acquaint you with options in OX configuration design. <br />
<br />
== Core Concepts - Configuration Scope ==<br />
<br />
The config cascade differentiates between 4 scopes of configuration: '''Server''', '''ContextSet''', '''Context''' and '''User''', with the latter always overriding the configuration of the one before it. To determine the active value of a certain parameter, the config cascade looks whether the parameter is defined in a certain scope before falling back to the next scope to the left to determine if a value is defined there. This means, that a value in the '''User''' scope can override the more general value from the '''Context''' scope, which in turn overrides the value of a context set configuration, which itself overrides a server wide configuration.<br />
<br />
== Core Concepts - Context Taxonomy ==<br />
<br />
When deciding on configuration options it usually makes sense to group contexts according to a certain criterion. Typical uses would be to group contexts by offering ('''webmail''', '''groupware_standard''', '''groupware_plus'''), or country ('''de''', '''fr''', '''es''') or brand ('''coolhosting''', '''supremehosting''') or if they are part of a "friendly users" group you sometimes give access to features to deem whether they are appropriate for rollout ('''beta'''). You can then specify configuration options that only take effect if a context is part of one of these groups. For example, the default hostname varies by both country and brand, with the french coolhosting domain name being "coolhosting.fr", while the spanish one is "coolhosting.es", or, for the second brand "supremehosting.fr" or "supremehosting.es" respectively. How can you go about classifying a context?<br />
<br />
Using the command line tools you can specifiy the taxonomy/types parameter:<br />
<br />
'''createcontext ... -i 12 --taxonomy/types=webmail,coolhosting,de'''<br />
<br />
which would tag context 12 with the types webmail, coolhosting and de. This is also available in "'''changecontext'''". In RMI the equivalent is to call '''Context#setUserAttribute("taxonomy", "types", "webmail,coolhosting,de")'''. We will later see how configuration options can be specified for these types of contexts. <br />
<br />
== Specifying Configuration - Server Scope ==<br />
<br />
The most general scope is the '''Server''' scope. Every value that can be overridden along the config cascade should also be defined with a default value in the Server scope. This is done using the usual configuration methods of the server: .properties files in the config directory (usually /opt/openexchange/etc, or /opt/openexchange/etc/groupware in versions up to 6.20.7). Let's consider the properties "'''com.openexchange.messaging.facebook'''", which governs whether facebook messaging should be available in a given installation. Since we consider this to be a premium feature, we'll disable this on the server level:<br />
<br />
'''facebookmessaging.properties:'''<br />
com.openexchange.messaging.facebook=false<br />
<br />
Later we will see how to enable it for certain groups of contexts.<br />
<br />
== Specifying Configuration - Context Set Scope ==<br />
<br />
As we saw, you can classify contexts into groups. These groups will now be used to specify certain configuration options. Let's consider this setup:<br />
<br />
<br />
Context 12: webmail,de,beta<br />
Context 13: groupware_plus,es<br />
Context 14: groupware_plus,fr,beta<br />
<br />
<br />
Let's say, we want to roll out the facebook functionality to those contexts, that have the groupware_plus product and are part of our "friendly users". For this, you can specify a configuration that overrides the server setting like this:<br />
<br />
Create a file called '''/opt/openexchange/etc/contextSets/messaging.yml''' and add the following block:<br />
<br />
experimental_gw_plus:<br />
withTags: groupware_plus & beta<br />
com.openexchange.messaging.facebook: true<br />
<br />
Let's go through this line by line. The first line introduces a configuration block that will be used for certain contexts. The name doesn't matter, only insofar as that it may only be used once per file. Choose a good mnemonic here, so a future you or someone else can guess at what is going on in this configuration block. <br />
<br />
The second line specifies the criterion to use to find out whether a context belongs in this group of contexts. In this case, a context having both the groupware_plus and beta tags will be considered to be a part of this group. In the withTags expression you can use boolean logic (with & for and, | for or and brackets to group the expressions). It's best to not go overboard with this, though. If the boolean expressions here become too complex it's usually an indication that you could use another classification for the contexts. Which tags does a context have? Firstly, and most obviously, those specified as its taxonomy/types list. But that is not the whole story. The /users/ module access permissions are also transformed into tags and applied to the context (at runtime). So if a user has access to the tasks module and the infostore module, the context will be considered to be tagged with ucTask and ucInfostore as well. This is sometimes enough to determine if a context is part of a certain offering, but more explicit tagging of contexts according to the offering keeps things readable. Lastly the configuration parameter "com.openexchange.config.cascade.types" (which is itself config cascade enabled) adds its value to the tag list, so, for example:<br />
<br />
friendly_users:<br />
withTags: groupware_plus & beta<br />
com.openexchange.config.cascade.types: friendly_and_paying<br />
<br />
Would add the friendly_and_paying tag to all contexts already classified as groupware_plus and beta. Also since this value can also be specified on user level, you could classify users irrespective of their contexts, should the need arise. <br />
<br />
The third line then specifies the setting to override. You can specify all properties to override in this block, so if we wanted to enable both facebook and twitter messaging for these contexts, we'd use the following configuration:<br />
<br />
experimental_gw_plus:<br />
withTags: groupware_plus & beta<br />
com.openexchange.messaging.facebook: true<br />
com.openexchange.messaging.twitter: true<br />
<br />
Most configuration use cases can probably be handled with the context sets system. Only if a configuration is truly unique for just one context or user should the other options be pursued.<br />
<br />
== Specifying Configuration - Context Scope and User Scope ==<br />
<br />
Configuration options can be overridden on user and context level, using a dynamic property. For example:<br />
<br />
$ createcontext [...] --config/com.openexchange.messaging.facebook=true<br />
$ changecontext [...] --config/com.openexchange.messaging.facebook=true<br />
<br />
$ createuser [...] --config/com.openexchange.messaging.facebook=true<br />
$ changeuser [...] --config/com.openexchange.messaging.facebook=true<br />
<br />
Depending on the number of users and contexts in your system, this could pose a problem further down the road when you need to update this value for a large number of users.<br />
<br />
== UI Properties ==<br />
<br />
A common use case for the OX configuration system is to allow fine-tuning of the UI by providing configuration data on the backend. All properties defined in properties files below <tt>/opt/open-xchange/etc/groupware/settings</tt> are transported to the UI and are config cascade enabled. So every customization you can specify for the UI using these settings, can also be selectively overridden with the config cascade.<br />
<br />
Since the config cascade only overrides existing settings, whether a property is a UI property or a server property is automatically determined by the directory in which the corresponding <tt>.properties</tt> file is found. For example if <tt>/opt/open-xchange/etc/settings/appsuite.properties</tt> contains the setting<br />
<br />
io.ox/core//theme=default<br />
<br />
Then you can overwrite it for any context (or user, context set, etc.):<br />
<br />
$ changecontext [...] --config/io.ox/core//theme=org.example.theme<br />
<br />
== Further Reading ==<br />
<br />
[[ConfigCascadeCookbook]] - Collects typical configuration scenarios and how to handle them using the config cascade.</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=ConfigCascade&diff=16590ConfigCascade2013-11-29T11:14:08Z<p>Viktor.Pracht: /* UI Properties */ clarified syntax</p>
<hr />
<div>= Introduction to the config cascade =<br />
<br />
The config cascade is a configuration system that allows administrators to selectively override configuration parameters on context and user level. This means a configuration option can vary between groups of contexts, specific contexts or users.<br />
<br />
== Who should read this document? ==<br />
<br />
If you are tasked with designing and maintaining the configuration of an OX server or cluster, information contained in this document will acquaint you with options in OX configuration design. <br />
<br />
== Core Concepts - Configuration Scope ==<br />
<br />
The config cascade differentiates between 4 scopes of configuration: '''Server''', '''ContextSet''', '''Context''' and '''User''', with the latter always overriding the configuration of the one before it. To determine the active value of a certain parameter, the config cascade looks whether the parameter is defined in a certain scope before falling back to the next scope to the left to determine if a value is defined there. This means, that a value in the '''User''' scope can override the more general value from the '''Context''' scope, which in turn overrides the value of a context set configuration, which itself overrides a server wide configuration.<br />
<br />
== Core Concepts - Context Taxonomy ==<br />
<br />
When deciding on configuration options it usually makes sense to group contexts according to a certain criterion. Typical uses would be to group contexts by offering ('''webmail''', '''groupware_standard''', '''groupware_plus'''), or country ('''de''', '''fr''', '''es''') or brand ('''coolhosting''', '''supremehosting''') or if they are part of a "friendly users" group you sometimes give access to features to deem whether they are appropriate for rollout ('''beta'''). You can then specify configuration options that only take effect if a context is part of one of these groups. For example, the default hostname varies by both country and brand, with the french coolhosting domain name being "coolhosting.fr", while the spanish one is "coolhosting.es", or, for the second brand "supremehosting.fr" or "supremehosting.es" respectively. How can you go about classifying a context?<br />
<br />
Using the command line tools you can specifiy the taxonomy/types parameter:<br />
<br />
'''createcontext ... -i 12 --taxonomy/types=webmail,coolhosting,de'''<br />
<br />
which would tag context 12 with the types webmail, coolhosting and de. This is also available in "'''changecontext'''". In RMI the equivalent is to call '''Context#setUserAttribute("taxonomy", "types", "webmail,coolhosting,de")'''. We will later see how configuration options can be specified for these types of contexts. <br />
<br />
== Specifying Configuration - Server Scope ==<br />
<br />
The most general scope is the '''Server''' scope. Every value that can be overridden along the config cascade should also be defined with a default value in the Server scope. This is done using the usual configuration methods of the server: .properties files in the config directory (usually /opt/openexchange/etc, or /opt/openexchange/etc/groupware in versions up to 6.20.7). Let's consider the properties "'''com.openexchange.messaging.facebook'''", which governs whether facebook messaging should be available in a given installation. Since we consider this to be a premium feature, we'll disable this on the server level:<br />
<br />
'''facebookmessaging.properties:'''<br />
com.openexchange.messaging.facebook=false<br />
<br />
Later we will see how to enable it for certain groups of contexts.<br />
<br />
== Specifying Configuration - Context Set Scope ==<br />
<br />
As we saw, you can classify contexts into groups. These groups will now be used to specify certain configuration options. Let's consider this setup:<br />
<br />
<br />
Context 12: webmail,de,beta<br />
Context 13: groupware_plus,es<br />
Context 14: groupware_plus,fr,beta<br />
<br />
<br />
Let's say, we want to roll out the facebook functionality to those contexts, that have the groupware_plus product and are part of our "friendly users". For this, you can specify a configuration that overrides the server setting like this:<br />
<br />
Create a file called '''/opt/openexchange/etc/contextSets/messaging.yml''' and add the following block:<br />
<br />
experimental_gw_plus:<br />
withTags: groupware_plus & beta<br />
com.openexchange.messaging.facebook: true<br />
<br />
Let's go through this line by line. The first line introduces a configuration block that will be used for certain contexts. The name doesn't matter, only insofar as that it may only be used once per file. Choose a good mnemonic here, so a future you or someone else can guess at what is going on in this configuration block. <br />
<br />
The second line specifies the criterion to use to find out whether a context belongs in this group of contexts. In this case, a context having both the groupware_plus and beta tags will be considered to be a part of this group. In the withTags expression you can use boolean logic (with & for and, | for or and brackets to group the expressions). It's best to not go overboard with this, though. If the boolean expressions here become too complex it's usually an indication that you could use another classification for the contexts. Which tags does a context have? Firstly, and most obviously, those specified as its taxonomy/types list. But that is not the whole story. The /users/ module access permissions are also transformed into tags and applied to the context (at runtime). So if a user has access to the tasks module and the infostore module, the context will be considered to be tagged with ucTask and ucInfostore as well. This is sometimes enough to determine if a context is part of a certain offering, but more explicit tagging of contexts according to the offering keeps things readable. Lastly the configuration parameter "com.openexchange.config.cascade.types" (which is itself config cascade enabled) adds its value to the tag list, so, for example:<br />
<br />
friendly_users:<br />
withTags: groupware_plus & beta<br />
com.openexchange.config.cascade.types: friendly_and_paying<br />
<br />
Would add the friendly_and_paying tag to all contexts already classified as groupware_plus and beta. Also since this value can also be specified on user level, you could classify users irrespective of their contexts, should the need arise. <br />
<br />
The third line then specifies the setting to override. You can specify all properties to override in this block, so if we wanted to enable both facebook and twitter messaging for these contexts, we'd use the following configuration:<br />
<br />
experimental_gw_plus:<br />
withTags: groupware_plus & beta<br />
com.openexchange.messaging.facebook: true<br />
com.openexchange.messaging.twitter: true<br />
<br />
Most configuration use cases can probably be handled with the context sets system. Only if a configuration is truly unique for just one context or user should the other options be pursued.<br />
<br />
== Specifying Configuration - Context Scope and User Scope ==<br />
<br />
Configuration options can be overridden on user and context level, using a dynamic property. For example:<br />
<br />
$ createcontext [...] --config/com.openexchange.messaging.facebook=true<br />
$ changecontext [...] --config/com.openexchange.messaging.facebook=true<br />
<br />
$ createuser [...] --config/com.openexchange.messaging.facebook=true<br />
$ changeuser [...] --config/com.openexchange.messaging.facebook=true<br />
<br />
Depending on the number of users and contexts in your system, this could pose a problem further down the road when you need to update this value for a large number of users.<br />
<br />
== UI Properties ==<br />
<br />
A common use case for the OX configuration system is to allow fine-tuning of the UI by providing configuration data on the backend. All properties defined in properties files below <tt>/opt/open-xchange/etc/groupware/settings</tt> are transported to the UI and are config cascade enabled. So every customization you can specify for the UI using these settings, can also be selectively overridden with the config cascade.<br />
<br />
Since the config cascade only overrides existing settings, whether a property is a UI property or a server property is automatically determined by the directory in which the corresponding <tt>.properties</tt> file is found. For example if <tt>/opt/open-xchange/etc/settings/appsuite.properties</tt> contains the setting<br />
<br />
io.ox/core//theme=default<br />
<br />
Then you can overwrite it for any context (or user, context set, etc.):<br />
<br />
$ changecontext --config/io.ox/core//theme=org.example.theme<br />
<br />
== Further Reading ==<br />
<br />
[[ConfigCascadeCookbook]] - Collects typical configuration scenarios and how to handle them using the config cascade.</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:Date_and_time&diff=16559AppSuite:Date and time2013-11-26T14:55:39Z<p>Viktor.Pracht: /* Time Zones */</p>
<hr />
<div>{{Stability-experimental}}<br />
<br />
<div class="title">Date and Time</div><br />
<br />
The handling of date and time is a complicated mess of historical conventions, which are still changed from time to time by governments around the world. To keep this away from day-to-day activities of developers, the OX App Suite platform provides the module date, which performs conversion between different time zones, formatting and parsing of date and time values.<br />
<br />
== Time Zones ==<br />
<br />
The built-in JavaScript class Date supports calculations using UTC and the operating system's local time zone. Unfortunately, this is not enough. Examples include using a time zone different from the time zone of the client system, or displaying times in multiple time zones at once.<br />
<br />
The class Local is almost a drop-in replacement for Date, with the main difference being that it operates in the default time zone of the OX App Suite user, even if it is different from the time zone of the browser's operating system. The following code displays the current date and time. It will show a different time when called after changing the user's time zone.<br />
<br />
<pre class="language-javascript"><br />
alert(new date.Local());<br />
</pre><br />
<br />
To work with other time zones, the function <tt>getTimeZone()</tt> can be used to create replacement classes similar to Local, which are all descendants of the private class LocalDate (for which all methods are documented below). Since the time zone definitions are loaded on-demand, the function returns a jQuery promise, which is resolved to the class constructor once the time zone definition is loaded. This class can then be used to e.g. convert between time zones.<br />
<br />
<pre class="language-javascript"><br />
date.getTimeZone('America/New_York').done(function (NewYork) {<br />
alert(gettext('New York celebrated New Year\'s at %1$s',<br />
new date.Local(new NewYork(2012, 0, 1))));<br />
});<br />
</pre><br />
<br />
The function getTimeZone() is memoized for performance reasons, i.e. multiple calls with the same argument will return the same promise and will therefore resolve to the same class object.<br />
<br />
== Formatting ==<br />
<br />
The default <tt>LocalDate.prototype.toString()</tt> method displays the full date and time, including the day of week and the time zone. To allow better control of the resulting string, the method <tt>LocalDate.prototype.format()</tt> accepts a set of format flags. The flags determine, which fields should be included in the output. Currently, there are four flags:<br />
<br />
<pre class="language-javascript"><br />
var d = new date.Local();<br />
alert(d.format(date.DATE));<br />
alert(d.format(date.TIME));<br />
alert(d.format(date.DAYOFWEEK));<br />
alert(d.format(date.TIMEZONE));<br />
</pre><br />
<br />
Multiple flags can be combined by adding them, or by using one of the predefined combination constants. Not all possible combinations produce unique results. When DAYOFWEEK is specified together with any other fields, DATE is automatically included in the output. Similarly, TIMEZONE implies TIME when used with other fields.<br />
<br />
<pre class="language-javascript"><br />
var d = new date.Local();<br />
assert(d.format(date.DAYOFWEEK + date.TIMEZONE) === d.format(date.FULL_DATE);<br />
</pre><br />
<br />
The format flags select one of several predefined format strings, which is stored in the current locale settings. This frees both the developers and the translators from having to remember arcane letter combinations.<br />
<br />
For the case that even finer control of the generated output is required, LocalDate.prototype.format() accepts a format string directly. The syntax of the format strings is a subset of CLDR date format patterns. Format specifiers which are not used in the Gregorian calendar will be implemented on-demand.<br />
<br />
<pre class="language-javascript"><br />
alert(new date.Local().format('EEEE'));<br />
</pre><br />
<br />
In general, if format strings are required, this indicates that the current date API should be extended. Feedback is always welcome.<br />
<br />
One situation where direct access to format strings is useful, is the manipulation of the localized format strings, e.g. to decorate individual fields in a displayed date with HTML markup. To achieve this, the localized format string is retrieved with getFormat(), and parts of it passed individually to LocalDate.prototype.format().<br />
<br />
<pre class="language-javascript"><br />
// Get the original format string.<br />
var fmt = date.getFormat(date.FULL_DATE);<br />
<br />
// Regular expression to parse the format string.<br />
// . . ( time zone )|quote|'quoted text'|rest<br />
var re = /(v+|V+|z+|Z+)|(?:''|'(?:[^']|'')*'|[^vVzZ'])+/g;<br />
<br />
// Appends a formatted date to a jQuery node and returns<br />
// the time zone as a separate node.<br />
function decorateTimeZone(d, parent) {<br />
var span;<br />
fmt.replace(re, function (match, tz) {<br />
if (tz) { // found the time zone field<br />
// Wrap the formatted time zone in a <span> element.<br />
span = $('<span>').text(d.format(match));<br />
parent.append(result);<br />
} else {<br />
// Append all other formatted text as plain text nodes.<br />
parent.append($.txt(d.format(match)));<br />
}<br />
});<br />
// Return the wrapped field for further customization.<br />
return span;<br />
}<br />
</pre><br />
<br />
''Does anybody want this use case as an API function?''<br />
<br />
== Intervals ==<br />
<br />
In addition to formatting individual dates, LocalDate instances can format intervals. The difference to simply inserting two dates into a translated string is that short intervals may have a compacter representation, e.g. 'Jan 1–10, 2012' instead of 'Jan 1, 2012 – Jan 10, 2012'.<br />
<br />
<pre class="language-javascript"><br />
var start = new date.Local(), end = new date.Local(start);<br />
end.add(date.DAY);<br />
alert(start.formatInterval(end, date.DATE));<br />
</pre><br />
<br />
The methods LocalDate.prototype.formatInterval() and LocalDate.prototype.getIntervalFormat() are used like LocalDate.prototype.format() and getFormat(), with two differences. First, the interval functions accept the end of the interval as first parameter before the format flags. And second, since the format string depends on the actual interval, LocalDate.prototype.getIntervalFormat() is a member function and requires the same end value as used later for LocalDate.prototype.formatInterval().<br />
<br />
== Parsing ==<br />
<br />
Parsing is the reverse of formatting, except that ideally, users should be able to enter almost anything, as long as it is not ambiguous. The practice looks a bit more restricted. The LocalDate.parse() function takes a format parameter like the formatting functions, and expects the parsed string to match it very closely.<br />
<br />
<pre class="language-javascript"><br />
var input = prompt(gettext('Please enter a date'), '');<br />
var d = date.Local.parse(input, date.DATE);<br />
alert(gettext('I understood %1$s', d);<br />
</pre><br />
<br />
If there is demand, we can implement some heuristics. There are a lot of abstract algorithm descriptions in the standards, which describe how to parse almost anything while using the format string only as disambiguation help.<br />
<br />
== Manipulation of LocalDate objects ==<br />
<br />
Since the LocalDate class is designed as a drop-in for the Date class, its instances support getter and setter methods for all fields of a date. They can be used to modify an existing LocalDate object, e. g. to round a date to the nearest day or hour.<br />
<br />
<pre class="language-javascript"><br />
var start = new date.Local(), end = new date.Local(start);<br />
start.setHours(0, 0, 0, 0);<br />
end.setHours(24, 0, 0, 0);<br />
alert(gettext('Today is %1$s', start.formatInterval(end)));<br />
</pre><br />
<br />
One manipulation, which is often needed in calendars, is iteration over time. This operation seems simple, at least for iteration steps with a constant duration like hours, days or weeks. One just needs to add the step duration to the timestamp. While there is a method to do exactly this, LocalDate.prototype.addUTC(), you will encounter problems as soon as the iteration transcends a daylight savings switch. First, days and weeks are not actually constant. And second, sometimes the iteration might need to follow the displayed 'wall clock' time instead of the physical time. For these cases, the method LocalDate.prototype.add() increments the local time instead of the UTC time. Both methods accept an increment value in milliseconds, which can also be negative. There are predefined constants for the most common (almost-)fixed-duration periods.<br />
<br />
<pre class="language-javascript"><br />
var d = new date.Local(2012, 2);<br />
for (; d.getMonth() < 3; d.add(date.DAY)) {<br />
// Display a day in a month view.<br />
}<br />
</pre><br />
<br />
Iteration with larger intervals like months and years has the additional difficulty, that a single numeric parameter like 30 * date.DAY cannot be interpreted as a month, because it might be just really 30 days. To solve this, there are separate methods for months and years: LocalDate.prototype.addMonths() and LocalDate.prototype.addYears(). They accept the number of months, respective years as parameter.<br />
<br />
<pre class="language-javascript"> <br />
var d = new date.Local(2012, 0);<br />
for (; g.getYear() < 2013; d.addMonths(1)) {<br />
// Display a month in a year view.<br />
}<br />
</pre><br />
<br />
Finally, most calendars default to displaying the current date, and therefore need to figure out the iteration range based on an arbitrary point inside that range. In most cases, the start can be computed by simply calling the appropriate setters with all zeros as parameters to find the start of the range, and adding the range duration to find the end. One exception is the week. There is no setter for the day of the week. Instead, the method LocalDate.prototype.setStartOfWeek() can be used to find the start of a week.<br />
<br />
<pre class="language-javascript"> <br />
// Find the start and the end of the current week<br />
var d = new date.Local().setStartOfWeek();<br />
var end = new date.Local(start).add(date.WEEK);<br />
// Iterate over the week<br />
for (; d < end; d.add(date.DAY)) {<br />
// Display a day in a week view.<br />
}<br />
</pre><br />
<br />
In addition to explicit method calls, the JavaScript standard method LocalDate.prototype.valueOf() allows native comparison, addition and subtraction operators to work on LocalDate objects. The result of LocalDate.prototype.valueOf(), and therefore of addition and subtraction, is a timestamp, which can be passed to the LocalDate constructor to get a LocalDate object again.<br />
<br />
<pre class="language-javascript"> <br />
var start = date.Local.parse(prompt(gettext('Start date'), ''));<br />
var end = date.Local.parse(prompt(gettext('End date'), ''));<br />
if (end < start) alert(gettext('Invalid date range!'));<br />
</pre><br />
<br />
== Differences between LocalDate and Date ==<br />
<br />
The LocalDate classes duplicate most of the Date API with a few exceptions:<br />
<br />
* The constructor can not be called as a function. The Date constructor does in this case nothing useful anyway.<br />
* The constructor always uses full years, it does not add 1900 for years 0 to 99.<br />
* Date.UTC() should not be necessary, but since it returns a numeric timestamp and has nothing to do with time zones, it can still be used directly.<br />
* Except for LocalDate.prototype.toString(), all to*String() methods are replaced by LocalDate.prototype.format().<br />
* There are no UTC variants of getters and setters. They should not be necessary. But just in case, you can still use a LocalDate class for the time zone 'UTC' instead.<br />
* The getter and setter for the year are called getYear and setYear instead of getFullYear and setFullYear since we have no legacy code with Y2K issues.<br />
* Setters return the modified object instead of the timestamp. This is useful for chaining of method calls.<br />
* Date.prototype.getTimeZoneOffset() should not be necessary, since hiding these details is the whole point of the date module. If still necessary, LocalDate.getTTInfo() can be used instead.<br />
<br />
== API Reference ==<br />
<br />
This section provides a short reference of the date API.<br />
<br />
=== Locale ===<br />
<br />
A locale describes the localization settings which usually depend not only on thelanguage, but also on the region and optionally even on the personal preferences of the user. The locale object is loaded at startup and provides various settings and translations.<br />
<br />
Various arrays containing translations can be used directly without any other date function.<br />
<br />
locale.dayPeriods<br />
A map from an identifier of a day period to the corresponding translation. The members am and pm are used in the 12h time format, but other members may be useful for greetings. Is anyone interested in a function which returns the correct greeting period for a given time? If not, maybe remove everything except AM and PM?<br />
locale.days<br />
An array with translated full names of days of the week, starting with Sunday. CLDR context: "format", CLDR width: "wide".<br />
locale.daysShort<br />
An array with translated abbreviated names of days of the week, starting with Sunday. CLDR context: "format", CLDR width: "abbreviated".<br />
locale.daysStandalone<br />
An array with translated standalone names of days of the week, starting with Sunday. CLDR context: "standalone", CLDR width: "abbreviated".<br />
locale.eras<br />
An array with translated abbreviations for the two eras of the Gregorian calendar: BC and AD (in that order).<br />
locale.months<br />
An array with translated full names of months. CLDR context: "format", CLDR width: "wide".<br />
locale.monthsShort<br />
An array with translated abbreviated names of months. CLDR context: "format", CLDR width: "abbreviated".<br />
Diverse week-based calculations need to know on which day the week starts and how the first week of the year is defined.<br />
<br />
locale.daysInFirstWeek<br />
The lowest number of days of a week which must be in the new year for that week to be considered week number 1. Common values are<br />
* 1 if the week of January 1st is week number 1,<br />
* 4 if the first week which has most of its days in the new year is week number 1.<br />
* 7 if the first week which starts in the new year is week number 1.<br />
locale.weekStart<br />
First day of the week. Common values are<br />
* 0 for Sunday,<br />
* 1 for Monday.<br />
Deprecated and internal fields should not be used since they can change or disappear entirely without notice. They are still documented here for completeness.<br />
<br />
locale.date<br />
Deprecated, use DATE instead.<br />
locale.dateTime<br />
Deprecated, use DATE_TIMEinstead.<br />
locale.dateTimeFormat<br />
The default format used to combine a time (%1$s) and a date (%2$s). Not used yet, will probably disappear.<br />
locale.formats<br />
A map from various canonical sets of format fields to the corresponding localized format strings. Used mainly by getFormat(). Maybe remove it from the public interface after loading, since it's internal?<br />
locale.h12<br />
A boolean indicating whether the 12h format is used. WANTED: a better name.<br />
locale.intervals<br />
A map from various canonical sets of format fields to the corresponding formatting rules. A formatting rule is a map from the largest field, which is different between the start and end of the interval, to the corresponding localized formatting string. The field is specified as a single lower case letter. The formatting string is split at the first repeating field. The first part is formatted using the start of the interval, the second part is formatted using the end of the interval. Used mainly by LocalDate.prototype.getIntervalFormat(). Maybe remove it from the public interface after loading, since it's internal?<br />
locale.intervals.fallback<br />
The default format string to combine the start (%1$s) and end (%2$s) of an interval when none of the other members of locale.intervals apply. Maybe remove it from the public interface after loading, since it's internal?<br />
locale.time<br />
Deprecated, use TIME instead.<br />
getTimeZone<br />
<br />
The main entry points of the date API are the class Local which replaces Date for use with the user's default time zone and a function to generate similar classes for arbitrary time zones.<br />
<br />
getTimeZone(name)<br />
Creates a LocalDate class which operates in the specified time zone. Multiple calls with the same name will return the same object.<br />
name String - The name of the requested time zone. It must be one of the values returned by api/config/availableTimeZones.<br />
Returns Promise - A promise which resolves to a LocalDate class which uses the requested time zone.<br />
Local<br />
A convenience LocalDate class which uses the user's current time zone.<br />
<br />
=== LocalDate ===<br />
<br />
The core of the date API is the abstract class LocalDate which is the superclass of time zone specific classes. The class itself is not publically available, only its subclasses can be created by calling getTimeZone(). The subclasses and their instances are referred to as LocalDate classes and LocalDate objects.<br />
<br />
The constructor mimics the behavior of the Date class, but it can't be called as a function.<br />
<br />
<pre class="language-javascript"> <br />
new LocalDate()<br />
new LocalDate(timestamp)<br />
new LocalDate(year, month, date, hours, minutes, seconds, ms)<br />
</pre><br />
<br />
The constructor accepts the same parameters as the Date constructor.<br />
The entire functionality of the class is based on a few low level functions. They should not be necessary outside the date module itself, assuming the API is complete. If you find you need these functions, please let's extend the high level APIs instead.<br />
<br />
LocalDate.getTTInfo(t)<br />
Returns the GMT offset, daylight savings and the abbreviation of the time zone which are in effect at the specified time.<br />
t Timestamp - The timestamp.<br />
Returns { gmtoff, isdst, abbr } - An object with the GMT offset in milliseconds, whether daylight savings are in effect (0 or 1, not a real boolean) and the abbreviation like 'CET' (!isdst) or 'CEST' (!!isdst).<br />
LocalDate.getTTInfoLocal(t)<br />
* Returns the GMT offset, daylight savings and the abbreviation of the time zone which are in effect at the specified local time. If the local time is ambiguous or invalid, the same fallbacks as for LocalDate.utc() are used. (It is actually implemented as a wrapper for this function.)<br />
* t Number - The local time.<br />
* Returns { gmtoff, isdst, abbr } - An object with the GMT offset in milliseconds, whether daylight savings are in effect (0 or 1, not a real boolean) and the abbreviation like 'CET' (!isdst) or 'CEST' (!!isdst).<br />
<br />
LocalDate.localTime(t)<br />
* Converts a UTC timestamp to local time.<br />
* t Timestamp - The UTC timestamp to convert.<br />
* Returns Number - A local time which is used in computations of date and time components.<br />
<br />
LocalDate.utc(t)<br />
* Converts local time to a UTC timestamp. If the local time is ambiguous because of a DST switch, the local time is interpreted as before the switch. E.g. 02:30 at the end of DST is interpreted as DST. If the local time is invalid because of a DST switch, the local time is interpreted as if the switch already occurred. E.g. 02:30 at the start of DST returns the same timestamp as 01:30 before the switch.<br />
* t Number - The local time to convert.<br />
* Returns Timestamp - The corresponsing UTC timestamp.<br />
Metadata about a time zone is stored directly on the LocalDate object.<br />
<br />
LocalDate.id<br />
* Original name used to retrieve this time zone.<br />
<br />
LocalDate.displayName<br />
* A human-readable name of this time zone as provided by the config module under "availableTimeZones".<br />
* Parsing of date and time strings as entered by a user is done using format flags from Constants. The current implementation expects the string to match the corresponding localized format string pretty closely. Any difficulties with parsing common entered dates and times should be taken as an opportunity to extend the parsing heuristics.<br />
<br />
LocalDate.parse(string, format)<br />
* Parses a string using either the specified format string or localized version of one of predefined format strings selected by format flags.<br />
* string String - The string to parse.<br />
* format String or Number - Either a format string with the syntax of CLDR date format patterns, or one of the format flag constants. In the second case, the actual format string is localized for the current user's locale according to locale.formats.<br />
* Returns LocalDate or null - A new LocalDate object which represents the parsed date and time or null if the string could not be parsed.<br />
* Methods of LocalDate instances can be grouped into several categories. The first are the setters and getters for individual fields from Date. Since each LocalDate class has its own time zone, There are no UTC variants of each getter and setter. They all work with local time.<br />
<br />
<pre class="language-javascript"> <br />
LocalDate.prototype.getYear()<br />
LocalDate.prototype.getMonth()<br />
LocalDate.prototype.getDate()<br />
LocalDate.prototype.getHours()<br />
LocalDate.prototype.getMinutes()<br />
LocalDate.prototype.getSeconds()<br />
LocalDate.prototype.getMilliseconds()<br />
</pre><br />
* Return the corresponding field of the local date or time.<br />
* Returns Number - The requested field, as a number.<br />
<br />
<pre class="language-javascript"> <br />
LocalDate.prototype.setYear(year, month, date)<br />
LocalDate.prototype.setMonth(month, date)<br />
LocalDate.prototype.setDate(date)<br />
LocalDate.prototype.setHours(hour, min, sec, ms)<br />
LocalDate.prototype.setMinutes(min, sec, ms)<br />
LocalDate.prototype.setSeconds(sec, ms)<br />
LocalDate.prototype.setMilliseconds(ms)<br />
</pre><br />
* Set the specified date or time fields. Any unspecified fields retain their current value. Values outside of the specified ranges will result in overflow to the neighboring periods and can therefore be used for date arithmetic.<br />
** year Number - The year.<br />
** month Number - The month. Values range from 0 for January to 11 for December.<br />
** date Number - The date. Values range from 1 to 31.<br />
** hour Number - The hours. Values range from 0 to 23.<br />
** min Number - The minutes. Values range from 0 to 59.<br />
** sec Number - The seconds. Values range from 0 to 59.<br />
** ms Number - The milliseconds. Values range from 0 to 999.<br />
<br />
LocalDate.prototype.getDay()<br />
* Returns Number - The day of the week. Values range from 0 for Sunday to 6 for Saturday.<br />
<br />
LocalDate.prototype.getTimeZone()<br />
* This method is not present in Date. It returns the abbreviation of the specific time zone. The abbreviation indicate the GMT offset and is therefore different between daylight savings time and standard time.<br />
* Returns String - The abbreviation of the specific time zone.<br />
* Other getters and setters work with the entire timestamp and not just individual fields.<br />
<br />
LocalDate.prototype.getDays()<br />
* Returns the day number of this object. This may be useful to find the start of the same day (by multiplying the result with DAY).<br />
* Returns Number - The number of days since 1970-01-01 in this object's time zone.<br />
<br />
LocalDate.prototype.getTime()<br />
* Returns Timestamp - The UTC timestamp of this object.<br />
<br />
LocalDate.prototype.setTime(time)<br />
* Sets the UTC timestamp to a new value.<br />
* time Timestamp - The new UTC timestamp of this object.<br />
* While setters can be used to perform date arithmetic, LocalDate provides convenience functions for the most frequent cases of adding and subtracting a time period and finding the start of a week.<br />
<br />
LocalDate.prototype.add(time)<br />
* Adds or subtracts a time period in local time. The results may be invalid if the end result ends up in the middle of a daylight savings switch.<br />
* time Number - The time period to add, in milliseconds. Use negative values to subtract. See also Constants.<br />
* Returns this - This object for chaining.<br />
<br />
LocalDate.prototype.addUTC(time)<br />
* Adds or subtracts a physical time period, i.e. simply increments the timestamp.<br />
time Number - The time period to add, in milliseconds. Use negative values to subtract. See also Constants.<br />
* Returns this - This object for chaining.<br />
<br />
LocalDate.prototype.addMonths(months)<br />
* Adds or subtracts a number of months in local time. The results may be invalid if the end result ends up in the middle of a daylight savings switch.<br />
months Number - The number of months to add. Use negative values to subtract.<br />
Returns this - This object for chaining.<br />
<br />
LocalDate.prototype.addYears(years)<br />
* Adds or subtracts a number of years in local time. The results may be invalid if the end result ends up in the middle of a daylight savings switch.<br />
years Number - The number of years to add. Use negative values to subtract.<br />
* Returns this - This object for chaining.<br />
<br />
LocalDate.prototype.setStartOfWeek()<br />
* Sets the date to the start of the same week as determined by locale.weekStart. The time is reset to midnight.<br />
* Returns this - This object for chaining.<br />
* Formatting functions implement the conversion of dates and intervals into localized strings which are suitable for direct presentation to the user.<br />
<br />
LocalDate.prototype.format(format)<br />
* Formats the date according to the specified format flags or format string.<br />
* format String or Number - Either a format string with the syntax of CLDR date format patterns, or one of the format flag constants. In the second case, the actual format string is localized for the current user's locale according to locale.formats. The default value is DATE_TIME.<br />
* Returns String - This object formatted according to the specified format.<br />
<br />
LocalDate.prototype.getIntervalFormat(end, format)<br />
* Returns a format string for a time interval with this object as the start and another LocalDate object as the end.<br />
* end LocalDate - The end of the interval.<br />
* format String or Number - Either a format string with the syntax of CLDR date format patterns, or one of the format flag constants. In the second case, the actual format string is localized for the current user's locale according to locale.intervals and locale.formats. The default value is DATE_TIME.<br />
* Returns String - The format string for the interval accorging to the specified format.<br />
<br />
LocalDate.prototype.formatInterval(end, format)<br />
* Formats an interval with this object as the start and another LocalDate object as the end.<br />
end LocalDate - The end of the interval.<br />
format String or Number - Either a format string with the syntax of CLDR date format patterns, or one of the format flag constants. In the second case, the actual format string is localized for the current user's locale according to locale.intervals and locale.formats. The default value is DATE_TIME.<br />
* Returns String - The interval formatted accorging to the specified format.<br />
* Finally, the JavaScript standard conversion functions allow easy debugging and arithmetic on timestamps.<br />
<br />
LocalDate.prototype.toString()<br />
* Converts this object to a string using this.format(FULL_DATE).<br />
* Returns String - The string representation of this object.<br />
<br />
LocalDate.prototype.valueOf()<br />
* Converts this object to a primitive value by returning the UTC timestamp. This can be used for arithmetic directly on LocalDate objects and as the single parameter to new LocalDate().<br />
* Returns Timestamp - The UTC timestamp of this object.<br />
<br />
=== Constants ===<br />
<br />
All date classes operate on timestamps expressed as milliseconds since the UNIX epoch, 1970-01-01 00:00 UTC. The date module defines constants for common time intervals with a constant duration.<br />
<br />
SECOND<br />
Number of milliseconds in a second.<br />
MINUTE<br />
Number of milliseconds in a minute.<br />
HOUR<br />
Number of milliseconds in an hour.<br />
DAY<br />
Number of milliseconds in a day.<br />
WEEK<br />
Number of milliseconds in a week.<br />
<br />
Format flags for parsing and formatting functions are defined as constants. Multiple flags can be combined via addition or bitwise ORing.<br />
<br />
<pre class="language-javascript"> <br />
DAYOFWEEK<br />
Day of the week<br />
DATE<br />
Date<br />
TIME<br />
Time<br />
TIMEZONE<br />
Timezone<br />
</pre><br />
Valid format flag combinations have dedicated constants. In a combination, DAYOFWEEK implies DATE and TIMEZONE implies TIME.<br />
<br />
<pre class="language-javascript"> <br />
DAYOFWEEK_DATE<br />
DAYOFWEEK + DATE<br />
DATE_TIME<br />
DATE + TIME<br />
DAYOFWEEK_DATE_TIME<br />
DAYOFWEEK + DATE + TIME<br />
TIME_TIMEZONE<br />
TIME + TIMEZONE<br />
DATE_TIME_TIMEZONE<br />
DATE + TIME + TIMEZONE<br />
FULL_DATE<br />
DAYOFWEEK + DATE + TIME + TIMEZONE<br />
Miscellaneous<br />
</pre><br />
See [[#Formatting|Formatting]] for usage of this function.<br />
<br />
getFormat(format)<br />
* Returns the localized format string for the specified format flags.<br />
format String or Number - Either a format string with the syntax of CLDR date format patterns, or one of the format flag constants. In the second case, the actual format string is localized for the current user's locale according to locale.formats. The default value is DATE_TIME.<br />
* Returns String - The localized format string which corresponds to the specified format flags. If format is a string, that string is returned unmodified.<br />
<br />
[[Category:AppSuite]][[Category:UI]]</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:GettingStarted_7.4.2&diff=16544AppSuite:GettingStarted 7.4.22013-11-25T13:53:20Z<p>Viktor.Pracht: /* Installing the Development Tools */</p>
<hr />
<div><div class="title">Getting Started</div><br />
<br />
<div style="float:right; padding: 10px;">[[File:OX_AppSuite_UI_Development_Workflow.png]]</div><br />
<br />
__TOC__<br />
<br />
Hello and welcome to the world of OX App Suite development. This document is designed to get you started with developing your first app for OX App Suite as quickly and simply as possible. However, along the way we will also tempt you to learn more by linking to some more in-depth documentation about the various topics we cover. <br />
<br />
<div style="clear: both"></div><br />
<br />
== Installing the Development Tools ==<br />
<br />
First, you need to install some tools which are necessary for UI development. For now, the simplest way is to download the source of the OX App Suite UI. Since the source code is kept in a [http://git-scm.com/ Git] repository, you will need <tt>git</tt> to download it:<br />
<br />
$ git clone --depth 1 https://code.open-xchange.com/git/wd/frontend/web<br />
<br />
This downloads the latest version and unpacks it into a subdirectory called <tt>web</tt> in the current directory.<br />
<br />
The option <tt>--depth 1</tt> prevents the download of the entire history, and reduces the download size from hundreds of MB to less than 20MB.<br />
<br />
The tools which you will need are contained in the directory <tt>ui/bin</tt>. To simplify their use, you should add this directory to your <tt>$PATH</tt>:<br />
<br />
$ export PATH="$PATH:$(pwd)/web/ui/bin"<br />
<br />
== Create a Workspace ==<br />
<br />
All your app development can take place inside one working directory. The examples will assume you have created a directory named <tt>myapp</tt> inside your home directory:<br />
<br />
$ mkdir ~/myapp<br />
$ cd ~/myapp<br />
<br />
It doesn't need to be in your home directory, and the actual name should reflect the name of your app. The main point is that all commands will be executed in this directory and all paths will be relative to this directory from now on.<br />
<br />
The source code of your app will reside in the subfolder named <tt>apps</tt>. To avoid name collisions please pick a unique subfolder inside that. The easiest and recommended way is to use a domain name that you own. Typically, the domain elements are reversed, like in Java. <tt>example.com</tt> becomes <tt>com.example</tt>:<br />
<br />
$ mkdir -p apps/com.example<br />
<br />
== Writing an App ==<br />
<br />
As an example, let's create the smallest possible app and test it. It requires only two files: <tt>apps/com.example/register.js</tt> for the source code of the app:<br />
<br />
<pre class="language-javascript"><br />
define('com.example/register', function () {<br />
'use strict';<br />
alert('Hello, World!');<br />
});<br />
</pre><br />
<br />
and <tt>apps/com.example/manifest.json</tt> for the [[AppSuite:UI_manifests_explained | manifest]] which tells the UI that your app exists and what to do with it:<br />
<br />
<pre class="language-javascript">{ "namespace": "core" }</pre><br />
<br />
== Building an App ==<br />
<br />
The source code of your app can't be used by OX App Suite as it. It first has to be processed by the [[AppSuite:UI_build_system | build system]]. This step will check the source code for syntax errors, compress it, and depending on the structure of your code, many other things. The processed code is then written to a directory named <tt>build</tt> by default. Start the build with this command:<br />
<br />
$ build-appsuite app<br />
<br />
If your editor supports it, you can configure it to call the build system after every file save. Take care to call it from the top directory of your app's workspace, not from the directory of the saved file.<br />
<br />
== Testing an App ==<br />
<br />
The freshly built code can now be tested. Instead of uploading your code to an OX App Suite server, you can use the [[AppSuite:Appserver|appserver]] proxy to inject your code into the UI code of any existing OX App Suite installation. For example, start <tt>appserver</tt> using [http://ox.io/ ox.io] as the server:<br />
<br />
<nowiki>$ appserver --server=https://www.ox.io/appsuite/ build</nowiki><br />
<br />
This command will serve your app from the local directory <tt>build</tt>, and get everything else from the URL specified by the <tt>--server</tt> parameter. To serve multiple apps, you can specify multiple local directories separated by spaces.<br />
<br />
You should start <tt>appserver</tt> in a separate terminal, since it needs to run in the background. To stop <tt>appserver</tt>, press <tt>Ctrl+C</tt> in its terminal.<br />
<br />
Once appserver is running, you can access OX App Suite by opening your browser using this address:<br />
<br />
http://localhost:8337/appsuite<br />
<br />
After logging in, the app should be loaded and display the <tt>alert</tt> message.<br />
<br />
If you later add images or other files, which are not JavaScript, CSS or LessCSS, then you need to [[AppSuite:Appserver#Use_with_Apache | use a web server]] to serve them.<br />
<br />
=== Development cycle ===<br />
<br />
Once you are sure that your setup works, you can extend the example and write the actual code for your app. Keep in mind that after [[#Writing | writing your code]], you will always need to [[#Building | build the app]] and have your [[#Hosting the app | Appserver]] running in the background, but don't need to restart it after every build.<br />
<br />
While developing always keep in mind, that there is an [[AppSuite:Debugging_the_UI | article about debugging the user interface]] which helps you avoid and fix typical errors.<br />
<br />
== Packaging ==<br />
<br />
When your app is finished you will probably want to test it on a staging system, and later install it on a production system. To keep track of which installed files belong to which version of which app, you should use the native package manager of the Linux distribution of the target system. The packages can be easily created using the build system.<br />
<br />
=== Initialization ===<br />
First, you need to create several files describing how to package you app. Use the <tt>init-packaging</tt> task of the build system:<br />
<br />
$ build-appsuite init-packaging<br />
Node version: v0.10.21<br />
Build path: build<br />
Build version: 0.0.1-1.20131025.133931<br />
Package name: example-app<br />
Version [0.0.1]: <br />
Maintainer (Name <e-mail>): Maintainer <maintainer@example.com><br />
Copyright line [2013 Open-Xchange, Inc]: <br />
<br />
Known licenses for which you don't need to specify a file:<br />
APACHE-2, BSD-2-CLAUSE, BSD-3-CLAUSE, CC-BY-3, CC-BY-NC-3, CC-BY-NC-ND-3,<br />
CC-BY-NC-SA-3, CC-BY-ND-3, CC-BY-SA-3, CC0-1, EXPAT, GPL-2, GPL-3, LGPL-3<br />
<br />
License name [CC-BY-NC-SA-3.0]: BSD-3-Clause<br />
Short description: Example app<br />
<br />
The task presents a number of interactive prompts to get the necessary information about the generated packages. The default values are presented in square brackets ([...]) and can be selected by just pressing Enter. Otherwise, the entered values should follow the Debian Maintainers Guide. Debian tools are especially picky about the syntax of the maintainer name and email address.<br />
<br />
If none of the known licenses suit you, you can enter any other license name. Then you will be asked to enter the file name of your license text. It should be a plain text file using the UTF-8 encoding.<br />
<br />
Some or even all prompts can be skipped by explicitly specifying the information as a build variable. The list of variable names is available in the reference of the <tt>[[AppSuite:UI_build_system#init-packaging|init-packaging]]</tt> task.<br />
<br />
After answering all the questions, you can customize the generated files to account for any additional packaging requirements.<br />
<br />
=== Static Files ===<br />
If your app includes images (themes do most of the time), then you should check the generated packaging files for sections marked<br />
<br />
## Uncomment for multiple packages<br />
#...<br />
<br />
and remove the '#' at the start of each line in each block. This enables the creation of a second package, with a name ending in "<tt>-static</tt>". The images and any other files which are not JavaScript or CSS are served by the Apache web server, instead of the OX App Suite application server. These files are copied to a separate package for the case that the web server is on a dedicated system or maybe even has its own cluster. The default package is installed on the OX application server, and the second, "<tt>-static</tt>" package is installed on the web server.<br />
<br />
=== Building Packages ===<br />
Since the actual package format depends on the distribution it is built for, and there are already tools available to create packages from suitably arranged source code archives, the OX App Suite build system merely prepares such source archives. Using the <tt>dist</tt> task to create the archives:<br />
<br />
$ build-appsuite dist<br />
Node version: v0.10.21<br />
Build path: build<br />
Build version: 0.0.1-1.20131025.150034<br />
dpkg-source: info: using source format `3.0 (quilt)'<br />
dpkg-source: info: building example-app using existing ./example-app_0.0.1.orig.tar.bz2<br />
dpkg-source: info: building example-app in example-app_0.0.1-1.debian.tar.bz2<br />
dpkg-source: info: building example-app in example-app_0.0.1-1.dsc<br />
<br />
$ ls tmp/packaging/<br />
example-app-0.0.1 example-app_0.0.1-1.dsc<br />
example-app.spec example-app_0.0.1.orig.tar.bz2<br />
example-app_0.0.1-1.debian.tar.bz2<br />
<br />
The task creates a temporary directory and four files. The archive with the extension <tt>.orig.tar.bz2</tt> contains the source of your app. It is required to build both Debian and RPM packages. The files with extensions <tt>.debian.tar.bz2</tt> and <tt>.dsc</tt> are used together with the <tt>.orig.tar.bz2</tt> archive to build Debian packages. The file with the extension <tt>.spec</tt> is used together with the <tt>.orig.tar.bz2</tt> archive to build RPM packages.<br />
<br />
==== Building Debian Packages ====<br />
The Debian package can be built directly in the temporary directory created by the <tt>dist</tt> task:<br />
<br />
$ cd tmp/packaging/example-app-0.0.1/<br />
$ dpkg-buildpackage -b<br />
<br />
The package will be placed in <tt>tmp/packaging/</tt>.<br />
<br />
==== Building RPM Packages ====<br />
The RPM package build tool <tt>rpmbuild</tt> requires the files to be in a specific directory layout before building:<br />
<br />
$ mkdir -p ~/rpmbuild/{SOURCES,SPECS,BUILD,RPMS}<br />
$ cp tmp/packaging/*.orig.tar.bz2 ~/rpmbuild/SOURCES/<br />
$ cp tmp/packaging/*.spec ~/rpmbuild/SPECS/<br />
$ rpmbuild --define "_topdir $HOME/rpmbuild" -bb ~/rpmbuild/SPECS/*.spec<br />
<br />
The package will be placed in <tt>~/rpmbuild/RPMS/noarch/</tt>.<br />
<br />
The parameter <tt>--define "_topdir $HOME/rpmbuild"</tt> can also be specified in the file <tt>~/.rpmmacros</tt> or, on some distributions, is even unnecessary.<br />
<br />
== Further Reading ==<br />
* Congratulations you have just built your first app for OX App Suite, but please keep in mind that there are [[AppSuite:Developing for the UI#What_can_i_build.3F | quite a few options]] for developing for OX App Suite.<br />
* It's highly recommended that you read and understand all the benefits [[AppSuite:UI_build_system | the UI build system]] and [[AppSuite:Appserver|the Appserver]] provide you for OX App Suite development.<br />
* If you're stuck somewhere, the article about [[AppSuite:Debugging_the_UI | debugging the UI]] might help you.<br />
* You can read this to get a better overview of [[AppSuite:Developing for the UI | developing the user inferface]].</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:GettingStarted_7.4.2&diff=16401AppSuite:GettingStarted 7.4.22013-11-12T17:07:10Z<p>Viktor.Pracht: /* Testing */</p>
<hr />
<div><div class="title">Getting Started</div><br />
<br />
<div style="float:right; padding: 10px;">[[File:OX_AppSuite_UI_Development_Workflow.png]]</div><br />
<br />
__TOC__<br />
<br />
Hello and welcome to OX App Suite development. This document will get you started to develop your first own app for OX App Suite with a minimal setup. We will look at the steps necessary but will also tempt you to learn more by linking you to some more in-depth documentation about these topics. Depending on how you wound up reading this page, you will probably have already completed some of the steps below.<br />
<br />
<div style="clear: both"></div><br />
<br />
== Installing ==<br />
<br />
First, you need to install some tools which are necessary for UI development. For now, the simplest way is to download the source of the OX App Suite UI. Since the source code is kept in a [http://git-scm.com/ Git] repository, you will need <tt>git</tt> to download it:<br />
<br />
$ git clone --depth 1 -b release-7.4.1 https://code.open-xchange.com/git/wd/frontend/web<br />
<br />
This downloads the latest version and unpacks it into a subdirectory <tt>web</tt> in the current directory.<br />
<br />
The option <tt>--depth 1</tt> prevents the download of the entire history, and reduces the download size from hundreds of MB to less than 20MB. The option <tt>-b release-7.4.1</tt> specifies a git branch. The full functionality described in this article is only available in the branch <tt>release-7.4.1</tt> until 7.4.1 is released.<br />
<br />
The tools which you will need are contained in the directory <tt>ui/bin</tt>. To simplify their use, you should add this directory to your <tt>$PATH</tt>:<br />
<br />
$ export PATH="$PATH:$(pwd)/web/ui/bin"<br />
<br />
== Create Workspace ==<br />
<br />
Your entire work on an app can take place inside a working directory. The examples will assume you have created a directory named <tt>myapp</tt> inside your home directory:<br />
<br />
$ mkdir ~/myapp<br />
$ cd ~/myapp<br />
<br />
It doesn't need to be in your home directory, and the actual name should reflect the name of your app. The main point is that all commands will be executed in this directory and all relative paths will be relative to this directory from now on.<br />
<br />
The source code of your app will reside in the subfolder named <tt>apps</tt>. To avoid name collisions, pick a unique subfolder inside that. The easiest and recommended way is to use a domain name that you own. Typically, the domain element are reversed, like in Java. <tt>example.com</tt> becomes <tt>com.example</tt>:<br />
<br />
$ mkdir -p apps/com.example<br />
<br />
== Writing ==<br />
<br />
As an example, let's create the smallest possible app and test it. It requires only two files: <tt>apps/com.example/reigster.js</tt> for the source code of the app:<br />
<br />
<pre class="language-javascript"><br />
define('com.example/register', function () {<br />
'use strict';<br />
alert('Hello, World!');<br />
});<br />
</pre><br />
<br />
and <tt>apps/com.example/manifest.json</tt> for the [[AppSuite:UI_manifests_explained | manifest]] which tells the UI that your app exists and what to do with it:<br />
<br />
<pre class="language-javascript">{ "namespace": "core" }</pre><br />
<br />
== Building ==<br />
<br />
The source code of your app can't be used by OX App Suite as it. It has to be first processed by the [[AppSuite:UI_build_system | build system]]. This step will check the source code for syntax errors, compress it, and depending on the structure of your code, many other things. The processed code is then written to a directory named <tt>build</tt> by default. Start the build with this command:<br />
<br />
$ build-appsuite app<br />
<br />
If your editor supports it, you can configure it to call the build system after every file save. Take care to call it from the top directory of your app's workspace, not from the directory of the saved file.<br />
<br />
== Testing ==<br />
<br />
The freshly built code can now be tested. Instead of uploading your code to an OX App Suite server, you can use the [[AppSuite:Appserver|appserver]] proxy to inject your code into the UI code of any existing OX App Suite installation. For example, start <tt>appserver</tt> using [http://ox.io/ ox.io] as server:<br />
<br />
<nowiki>$ appserver --server=https://www.ox.io/appsuite/ build</nowiki><br />
<br />
This command will serve your app from the local directory <tt>build</tt>, and get everything else from the URL specified by the <tt>--server</tt> parameter. To serve multiple apps, you can specify multiple local directories separated by spaces.<br />
<br />
You should start <tt>appserver</tt> in a separate terminal, since it needs to run in the background. To stop <tt>appserver</tt>, press <tt>Ctrl+C</tt> in its terminal.<br />
<br />
Once appserver is running, you can access OX App Suite opening your browser with this address:<br />
<br />
http://localhost:8337/appsuite<br />
<br />
After logging in, the app should be loaded and display the <tt>alert</tt> message.<br />
<br />
If you later add images or other files, which are not JavaScript, CSS or LessCSS, then you need to [[AppSuite:Appserver#Use_with_Apache | use a web server]] to serve them.<br />
<br />
=== Development cycle ===<br />
<br />
Once you are sure that your setup works, you can extend the example and write the actual code of your app. Keep in mind that after [[#Writing | writing your code]], you will always need to [[#Building | build the app]] and have your [[#Hosting the app | Appserver]] running in the background, but don't need to restart it after every build.<br />
<br />
While developing always keep in mind, that there is an [[AppSuite:Debugging_the_UI | article about debugging the user interface]] which helps you avoiding and fixing typical errors.<br />
<br />
== Packaging ==<br />
<br />
When your app is done, you probably want to test it on a staging system, and later install it on a production system. To keep track of which installed files belong to which version of which app, you should use the native package manager of the Linux distribution of the target system. The packages can be easily created using the build system.<br />
<br />
=== Initialization ===<br />
First, you need to create several files describing how to package you app. Use the <tt>init-packaging</tt> task of the build system:<br />
<br />
$ build-appsuite init-packaging<br />
Node version: v0.10.21<br />
Build path: build<br />
Build version: 0.0.1-1.20131025.133931<br />
Package name: example-app<br />
Version [0.0.1]: <br />
Maintainer (Name <e-mail>): Maintainer <maintainer@example.com><br />
Copyright line [2013 Open-Xchange, Inc]: <br />
<br />
Known licenses for which you don't need to specify a file:<br />
APACHE-2, BSD-2-CLAUSE, BSD-3-CLAUSE, CC-BY-3, CC-BY-NC-3, CC-BY-NC-ND-3,<br />
CC-BY-NC-SA-3, CC-BY-ND-3, CC-BY-SA-3, CC0-1, EXPAT, GPL-2, GPL-3, LGPL-3<br />
<br />
License name [CC-BY-NC-SA-3.0]: BSD-3-Clause<br />
Short description: Example app<br />
<br />
The task presents a number of interactive prompts to get the necessary information about the generated packages. The default values are presented in square brackets ([...]) and can be selected by just pressing Enter. Otherwise, the entered values should follow the Debian Maintainer's Guide. Debian tools are especially picky about the syntax of the maintainer name and email address.<br />
<br />
If none of the known licenses suit you, you can enter any other license name. Then you will be asked to enter the file name of your license text. It should be a plain text file using the UTF-8 encoding.<br />
<br />
Some or even all prompts can be skipped by explicitly specifying the information as a build variable. The list of variable names is available in the reference of the <tt>[[AppSuite:UI_build_system#init-packaging|init-packaging]]</tt> task.<br />
<br />
After answering all the questions, you can customize the generated files to account for any additional packaging requirements.<br />
<br />
=== Static Files ===<br />
If your app includes images (e.g. themes do this most of the time), then you should check the generated packaging files for sections marked<br />
<br />
## Uncomment for multiple packages<br />
#...<br />
<br />
and remove the '#' at the start of each line in each block. This enables the creation of a second package, with a name ending in "<tt>-static</tt>". The images and any other files which are not JavaScript or CSS are served by the Apache web server, instead of the OX App Suite application server. These files are copied to a separate package for the case that the web server is on a dedicated system or maybe even has its own cluster. The default package is installed on the OX application server, and the second, "<tt>-static</tt>" package is installed on the web server.<br />
<br />
=== Building Packages ===<br />
Since the actual package format depends on the distribution it is built for, and there already exist tools to create packages from suitably arranged source code archives, the OX App Suite build system merely prepares such source archives. Using the <tt>dist</tt> task to create the archives:<br />
<br />
$ build-appsuite dist<br />
Node version: v0.10.21<br />
Build path: build<br />
Build version: 0.0.1-1.20131025.150034<br />
dpkg-source: info: using source format `3.0 (quilt)'<br />
dpkg-source: info: building example-app using existing ./example-app_0.0.1.orig.tar.bz2<br />
dpkg-source: info: building example-app in example-app_0.0.1-1.debian.tar.bz2<br />
dpkg-source: info: building example-app in example-app_0.0.1-1.dsc<br />
<br />
$ ls tmp/packaging/<br />
example-app-0.0.1 example-app_0.0.1-1.dsc<br />
example-app.spec example-app_0.0.1.orig.tar.bz2<br />
example-app_0.0.1-1.debian.tar.bz2<br />
<br />
The task creates a temporary directory and four files. The archive with the extension <tt>.orig.tar.bz2</tt> contains the source of your app. It is required to build both Debian and RPM packages. The files with extensions <tt>.debian.tar.bz2</tt> and <tt>.dsc</tt> are used together with the <tt>.orig.tar.bz2</tt> archive to build Debian packages. The file with the extension <tt>.spec</tt> is used together with the <tt>.orig.tar.bz2</tt> archive to build RPM packages.<br />
<br />
==== Building Debian Packages ====<br />
The Debian package can be built directly in the temporary directory created by the <tt>dist</tt> task:<br />
<br />
$ cd tmp/packaging/example-app-0.0.1/<br />
$ dpkg-buildpackage -b<br />
<br />
The package will be placed in <tt>tmp/packaging/</tt>.<br />
<br />
==== Building RPM Packages ====<br />
The RPM package build tool <tt>rpmbuild</tt> requires the files to be in a specific directory layout before building:<br />
<br />
$ mkdir -p ~/rpmbuild/{SOURCES,SPECS,BUILD,RPMS}<br />
$ cp tmp/packaging/*.orig.tar.bz2 ~/rpmbuild/SOURCES/<br />
$ cp tmp/packaging/*.spec ~/rpmbuild/SPECS/<br />
$ rpmbuild --define "_topdir $HOME/rpmbuild" -bb ~/rpmbuild/SPECS/*.spec<br />
<br />
The package will be placed in <tt>~/rpmbuild/RPMS/noarch/</tt>.<br />
<br />
The parameter <tt>--define "_topdir $HOME/rpmbuild"</tt> can also be specified in the file <tt>~/.rpmmacros</tt> or, on some distributions, is even unnecessary.<br />
<br />
== Further Reading ==<br />
* You just build your first app for OX App Suite, keep in mind that there [[AppSuite:Developing for the UI#What_can_i_build.3F | quite a few options]] how you can develop for OX App Suite.<br />
* It's highly recommended to gain more knowledge about all the benefits [[AppSuite:UI_build_system | the UI build system]] and [[AppSuite:Appserver|the Appserver]] are providing you for developing OX App Suite.<br />
* If you're stuck somewhere, the article about [[AppSuite:Debugging_the_UI | debugging the UI]] might help you.<br />
* Get a better overview about [[AppSuite:Developing for the UI | developing the user inferface]].</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:GettingStarted_7.4.2&diff=16400AppSuite:GettingStarted 7.4.22013-11-12T17:06:24Z<p>Viktor.Pracht: /* Testing */ added link to "Use with Apache"</p>
<hr />
<div><div class="title">Getting Started</div><br />
<br />
<div style="float:right; padding: 10px;">[[File:OX_AppSuite_UI_Development_Workflow.png]]</div><br />
<br />
__TOC__<br />
<br />
Hello and welcome to OX App Suite development. This document will get you started to develop your first own app for OX App Suite with a minimal setup. We will look at the steps necessary but will also tempt you to learn more by linking you to some more in-depth documentation about these topics. Depending on how you wound up reading this page, you will probably have already completed some of the steps below.<br />
<br />
<div style="clear: both"></div><br />
<br />
== Installing ==<br />
<br />
First, you need to install some tools which are necessary for UI development. For now, the simplest way is to download the source of the OX App Suite UI. Since the source code is kept in a [http://git-scm.com/ Git] repository, you will need <tt>git</tt> to download it:<br />
<br />
$ git clone --depth 1 -b release-7.4.1 https://code.open-xchange.com/git/wd/frontend/web<br />
<br />
This downloads the latest version and unpacks it into a subdirectory <tt>web</tt> in the current directory.<br />
<br />
The option <tt>--depth 1</tt> prevents the download of the entire history, and reduces the download size from hundreds of MB to less than 20MB. The option <tt>-b release-7.4.1</tt> specifies a git branch. The full functionality described in this article is only available in the branch <tt>release-7.4.1</tt> until 7.4.1 is released.<br />
<br />
The tools which you will need are contained in the directory <tt>ui/bin</tt>. To simplify their use, you should add this directory to your <tt>$PATH</tt>:<br />
<br />
$ export PATH="$PATH:$(pwd)/web/ui/bin"<br />
<br />
== Create Workspace ==<br />
<br />
Your entire work on an app can take place inside a working directory. The examples will assume you have created a directory named <tt>myapp</tt> inside your home directory:<br />
<br />
$ mkdir ~/myapp<br />
$ cd ~/myapp<br />
<br />
It doesn't need to be in your home directory, and the actual name should reflect the name of your app. The main point is that all commands will be executed in this directory and all relative paths will be relative to this directory from now on.<br />
<br />
The source code of your app will reside in the subfolder named <tt>apps</tt>. To avoid name collisions, pick a unique subfolder inside that. The easiest and recommended way is to use a domain name that you own. Typically, the domain element are reversed, like in Java. <tt>example.com</tt> becomes <tt>com.example</tt>:<br />
<br />
$ mkdir -p apps/com.example<br />
<br />
== Writing ==<br />
<br />
As an example, let's create the smallest possible app and test it. It requires only two files: <tt>apps/com.example/reigster.js</tt> for the source code of the app:<br />
<br />
<pre class="language-javascript"><br />
define('com.example/register', function () {<br />
'use strict';<br />
alert('Hello, World!');<br />
});<br />
</pre><br />
<br />
and <tt>apps/com.example/manifest.json</tt> for the [[AppSuite:UI_manifests_explained | manifest]] which tells the UI that your app exists and what to do with it:<br />
<br />
<pre class="language-javascript">{ "namespace": "core" }</pre><br />
<br />
== Building ==<br />
<br />
The source code of your app can't be used by OX App Suite as it. It has to be first processed by the [[AppSuite:UI_build_system | build system]]. This step will check the source code for syntax errors, compress it, and depending on the structure of your code, many other things. The processed code is then written to a directory named <tt>build</tt> by default. Start the build with this command:<br />
<br />
$ build-appsuite app<br />
<br />
If your editor supports it, you can configure it to call the build system after every file save. Take care to call it from the top directory of your app's workspace, not from the directory of the saved file.<br />
<br />
== Testing ==<br />
<br />
The freshly built code can now be tested. Instead of uploading your code to an OX App Suite server, you can use the [[AppSuite:Appserver|appserver]] proxy to inject your code into the UI code of any existing OX App Suite installation. For example, start <tt>appserver</tt> using [http://ox.io/ ox.io] as server:<br />
<br />
<nowiki>$ appserver --server=https://www.ox.io/appsuite/ build</nowiki><br />
<br />
This command will serve your app from the local directory <tt>build</tt>, and get everything else from the URL specified by the <tt>--server</tt> parameter. To serve multiple apps, you can specify multiple local directories separated by spaces.<br />
<br />
You should start <tt>appserver</tt> in a separate terminal, since it needs to run in the background. To stop <tt>appserver</tt>, press <tt>Ctrl+C</tt> in its terminal.<br />
<br />
Once appserver is running, you can access OX App Suite opening your browser with this address:<br />
<br />
http://localhost:8337/appsuite<br />
<br />
After logging in, the app should be loaded and display the <tt>alert</tt> message.<br />
<br />
If you have images or other files, which are not JavaScript, CSS or LessCSS, then you need to [[AppSuite:Appserver#Use_with_Apache | use a web server]] to serve them.<br />
<br />
=== Development cycle ===<br />
<br />
Once you are sure that your setup works, you can extend the example and write the actual code of your app. Keep in mind that after [[#Writing | writing your code]], you will always need to [[#Building | build the app]] and have your [[#Hosting the app | Appserver]] running in the background, but don't need to restart it after every build.<br />
<br />
While developing always keep in mind, that there is an [[AppSuite:Debugging_the_UI | article about debugging the user interface]] which helps you avoiding and fixing typical errors.<br />
<br />
== Packaging ==<br />
<br />
When your app is done, you probably want to test it on a staging system, and later install it on a production system. To keep track of which installed files belong to which version of which app, you should use the native package manager of the Linux distribution of the target system. The packages can be easily created using the build system.<br />
<br />
=== Initialization ===<br />
First, you need to create several files describing how to package you app. Use the <tt>init-packaging</tt> task of the build system:<br />
<br />
$ build-appsuite init-packaging<br />
Node version: v0.10.21<br />
Build path: build<br />
Build version: 0.0.1-1.20131025.133931<br />
Package name: example-app<br />
Version [0.0.1]: <br />
Maintainer (Name <e-mail>): Maintainer <maintainer@example.com><br />
Copyright line [2013 Open-Xchange, Inc]: <br />
<br />
Known licenses for which you don't need to specify a file:<br />
APACHE-2, BSD-2-CLAUSE, BSD-3-CLAUSE, CC-BY-3, CC-BY-NC-3, CC-BY-NC-ND-3,<br />
CC-BY-NC-SA-3, CC-BY-ND-3, CC-BY-SA-3, CC0-1, EXPAT, GPL-2, GPL-3, LGPL-3<br />
<br />
License name [CC-BY-NC-SA-3.0]: BSD-3-Clause<br />
Short description: Example app<br />
<br />
The task presents a number of interactive prompts to get the necessary information about the generated packages. The default values are presented in square brackets ([...]) and can be selected by just pressing Enter. Otherwise, the entered values should follow the Debian Maintainer's Guide. Debian tools are especially picky about the syntax of the maintainer name and email address.<br />
<br />
If none of the known licenses suit you, you can enter any other license name. Then you will be asked to enter the file name of your license text. It should be a plain text file using the UTF-8 encoding.<br />
<br />
Some or even all prompts can be skipped by explicitly specifying the information as a build variable. The list of variable names is available in the reference of the <tt>[[AppSuite:UI_build_system#init-packaging|init-packaging]]</tt> task.<br />
<br />
After answering all the questions, you can customize the generated files to account for any additional packaging requirements.<br />
<br />
=== Static Files ===<br />
If your app includes images (e.g. themes do this most of the time), then you should check the generated packaging files for sections marked<br />
<br />
## Uncomment for multiple packages<br />
#...<br />
<br />
and remove the '#' at the start of each line in each block. This enables the creation of a second package, with a name ending in "<tt>-static</tt>". The images and any other files which are not JavaScript or CSS are served by the Apache web server, instead of the OX App Suite application server. These files are copied to a separate package for the case that the web server is on a dedicated system or maybe even has its own cluster. The default package is installed on the OX application server, and the second, "<tt>-static</tt>" package is installed on the web server.<br />
<br />
=== Building Packages ===<br />
Since the actual package format depends on the distribution it is built for, and there already exist tools to create packages from suitably arranged source code archives, the OX App Suite build system merely prepares such source archives. Using the <tt>dist</tt> task to create the archives:<br />
<br />
$ build-appsuite dist<br />
Node version: v0.10.21<br />
Build path: build<br />
Build version: 0.0.1-1.20131025.150034<br />
dpkg-source: info: using source format `3.0 (quilt)'<br />
dpkg-source: info: building example-app using existing ./example-app_0.0.1.orig.tar.bz2<br />
dpkg-source: info: building example-app in example-app_0.0.1-1.debian.tar.bz2<br />
dpkg-source: info: building example-app in example-app_0.0.1-1.dsc<br />
<br />
$ ls tmp/packaging/<br />
example-app-0.0.1 example-app_0.0.1-1.dsc<br />
example-app.spec example-app_0.0.1.orig.tar.bz2<br />
example-app_0.0.1-1.debian.tar.bz2<br />
<br />
The task creates a temporary directory and four files. The archive with the extension <tt>.orig.tar.bz2</tt> contains the source of your app. It is required to build both Debian and RPM packages. The files with extensions <tt>.debian.tar.bz2</tt> and <tt>.dsc</tt> are used together with the <tt>.orig.tar.bz2</tt> archive to build Debian packages. The file with the extension <tt>.spec</tt> is used together with the <tt>.orig.tar.bz2</tt> archive to build RPM packages.<br />
<br />
==== Building Debian Packages ====<br />
The Debian package can be built directly in the temporary directory created by the <tt>dist</tt> task:<br />
<br />
$ cd tmp/packaging/example-app-0.0.1/<br />
$ dpkg-buildpackage -b<br />
<br />
The package will be placed in <tt>tmp/packaging/</tt>.<br />
<br />
==== Building RPM Packages ====<br />
The RPM package build tool <tt>rpmbuild</tt> requires the files to be in a specific directory layout before building:<br />
<br />
$ mkdir -p ~/rpmbuild/{SOURCES,SPECS,BUILD,RPMS}<br />
$ cp tmp/packaging/*.orig.tar.bz2 ~/rpmbuild/SOURCES/<br />
$ cp tmp/packaging/*.spec ~/rpmbuild/SPECS/<br />
$ rpmbuild --define "_topdir $HOME/rpmbuild" -bb ~/rpmbuild/SPECS/*.spec<br />
<br />
The package will be placed in <tt>~/rpmbuild/RPMS/noarch/</tt>.<br />
<br />
The parameter <tt>--define "_topdir $HOME/rpmbuild"</tt> can also be specified in the file <tt>~/.rpmmacros</tt> or, on some distributions, is even unnecessary.<br />
<br />
== Further Reading ==<br />
* You just build your first app for OX App Suite, keep in mind that there [[AppSuite:Developing for the UI#What_can_i_build.3F | quite a few options]] how you can develop for OX App Suite.<br />
* It's highly recommended to gain more knowledge about all the benefits [[AppSuite:UI_build_system | the UI build system]] and [[AppSuite:Appserver|the Appserver]] are providing you for developing OX App Suite.<br />
* If you're stuck somewhere, the article about [[AppSuite:Debugging_the_UI | debugging the UI]] might help you.<br />
* Get a better overview about [[AppSuite:Developing for the UI | developing the user inferface]].</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:GettingStarted_7.4.2&diff=16389AppSuite:GettingStarted 7.4.22013-11-11T15:48:17Z<p>Viktor.Pracht: /* Building */</p>
<hr />
<div><div class="title">Getting Started</div><br />
<br />
<div style="float:right; padding: 10px;">[[File:OX_AppSuite_UI_Development_Workflow.png]]</div><br />
<br />
__TOC__<br />
<br />
Hello and welcome to OX App Suite development. This document will get you started to develop your first own app for OX App Suite with a minimal setup. We will look at the steps necessary but will also tempt you to learn more by linking you to some more in-depth documentation about these topics. Depending on how you wound up reading this page, you will probably have already completed some of the steps below.<br />
<br />
<div style="clear: both"></div><br />
<br />
== Installing ==<br />
<br />
First, you need to install some tools which are necessary for UI development. For now, the simplest way is to download the source of the OX App Suite UI. Since the source code is kept in a [http://git-scm.com/ Git] repository, you will need <tt>git</tt> to download it:<br />
<br />
$ git clone --depth 1 -b release-7.4.1 https://code.open-xchange.com/git/wd/frontend/web<br />
<br />
This downloads the latest version and unpacks it into a subdirectory <tt>web</tt> in the current directory.<br />
<br />
The option <tt>--depth 1</tt> prevents the download of the entire history, and reduces the download size from hundreds of MB to less than 20MB. The option <tt>-b release-7.4.1</tt> specifies a git branch. The full functionality described in this article is only available in the branch <tt>release-7.4.1</tt> until 7.4.1 is released.<br />
<br />
The tools which you will need are contained in the directory <tt>ui/bin</tt>. To simplify their use, you should add this directory to your <tt>$PATH</tt>:<br />
<br />
$ export PATH="$PATH:$(pwd)/web/ui/bin"<br />
<br />
== Create Workspace ==<br />
<br />
Your entire work on an app can take place inside a working directory. The examples will assume you have created a directory named <tt>myapp</tt> inside your home directory:<br />
<br />
$ mkdir ~/myapp<br />
$ cd ~/myapp<br />
<br />
It doesn't need to be in your home directory, and the actual name should reflect the name of your app. The main point is that all commands will be executed in this directory and all relative paths will be relative to this directory from now on.<br />
<br />
The source code of your app will reside in the subfolder named <tt>apps</tt>. To avoid name collisions, pick a unique subfolder inside that. The easiest and recommended way is to use a domain name that you own. Typically, the domain element are reversed, like in Java. <tt>example.com</tt> becomes <tt>com.example</tt>:<br />
<br />
$ mkdir -p apps/com.example<br />
<br />
== Writing ==<br />
<br />
As an example, let's create the smallest possible app and test it. It requires only two files: <tt>apps/com.example/reigster.js</tt> for the source code of the app:<br />
<br />
<pre class="language-javascript"><br />
define('com.example/register', function () {<br />
'use strict';<br />
alert('Hello, World!');<br />
});<br />
</pre><br />
<br />
and <tt>apps/com.example/manifest.json</tt> for the [[AppSuite:UI_manifests_explained | manifest]] which tells the UI that your app exists and what to do with it:<br />
<br />
<pre class="language-javascript">{ "namespace": "core" }</pre><br />
<br />
== Building ==<br />
<br />
The source code of your app can't be used by OX App Suite as it. It has to be first processed by the [[AppSuite:UI_build_system | build system]]. This step will check the source code for syntax errors, compress it, and depending on the structure of your code, many other things. The processed code is then written to a directory named <tt>build</tt> by default. Start the build with this command:<br />
<br />
$ build-appsuite app<br />
<br />
If your editor supports it, you can configure it to call the build system after every file save. Take care to call it from the top directory of your app's workspace, not from the directory of the saved file.<br />
<br />
== Testing ==<br />
<br />
The freshly built code can now be tested. Instead of uploading your code to an OX App Suite server, you can use the [[AppSuite:Appserver|appserver]] proxy to inject your code into the UI code of any existing OX App Suite installation. For example, start <tt>appserver</tt> using [http://ox.io/ ox.io] as server:<br />
<br />
<nowiki>$ appserver --server=https://www.ox.io/appsuite/ build</nowiki><br />
<br />
This command will serve your app from the local directory <tt>build</tt>, and get everything else from the URL specified by the <tt>--server</tt> parameter. To serve multiple apps, you can specify multiple local directories separated by spaces.<br />
<br />
You should start <tt>appserver</tt> in a separate terminal, since it needs to run in the background. To stop <tt>appserver</tt>, press <tt>Ctrl+C</tt> in its terminal.<br />
<br />
Once appserver is running, you can access OX App Suite opening your browser with this address:<br />
<br />
http://localhost:8337/appsuite<br />
<br />
After logging in, the app should be loaded and display the <tt>alert</tt> message.<br />
<br />
=== Development cycle ===<br />
<br />
Once you are sure that your setup works, you can extend the example and write the actual code of your app. Keep in mind that after [[#Writing | writing your code]], you will always need to [[#Building | build the app]] and have your [[#Hosting the app | Appserver]] running in the background, but don't need to restart it after every build.<br />
<br />
While developing always keep in mind, that there is an [[AppSuite:Debugging_the_UI | article about debugging the user interface]] which helps you avoiding and fixing typical errors.<br />
<br />
== Packaging ==<br />
<br />
When your app is done, you probably want to test it on a staging system, and later install it on a production system. To keep track of which installed files belong to which version of which app, you should use the native package manager of the Linux distribution of the target system. The packages can be easily created using the build system.<br />
<br />
=== Initialization ===<br />
First, you need to create several files describing how to package you app. Use the <tt>init-packaging</tt> task of the build system:<br />
<br />
$ build-appsuite init-packaging<br />
Node version: v0.10.21<br />
Build path: build<br />
Build version: 0.0.1-1.20131025.133931<br />
Package name: example-app<br />
Version [0.0.1]: <br />
Maintainer (Name <e-mail>): Maintainer <maintainer@example.com><br />
Copyright line [2013 Open-Xchange, Inc]: <br />
<br />
Known licenses for which you don't need to specify a file:<br />
APACHE-2, BSD-2-CLAUSE, BSD-3-CLAUSE, CC-BY-3, CC-BY-NC-3, CC-BY-NC-ND-3,<br />
CC-BY-NC-SA-3, CC-BY-ND-3, CC-BY-SA-3, CC0-1, EXPAT, GPL-2, GPL-3, LGPL-3<br />
<br />
License name [CC-BY-NC-SA-3.0]: BSD-3-Clause<br />
Short description: Example app<br />
<br />
The task presents a number of interactive prompts to get the necessary information about the generated packages. The default values are presented in square brackets ([...]) and can be selected by just pressing Enter. Otherwise, the entered values should follow the Debian Maintainer's Guide. Debian tools are especially picky about the syntax of the maintainer name and email address.<br />
<br />
If none of the known licenses suit you, you can enter any other license name. Then you will be asked to enter the file name of your license text. It should be a plain text file using the UTF-8 encoding.<br />
<br />
Some or even all prompts can be skipped by explicitly specifying the information as a build variable. The list of variable names is available in the reference of the <tt>[[AppSuite:UI_build_system#init-packaging|init-packaging]]</tt> task.<br />
<br />
After answering all the questions, you can customize the generated files to account for any additional packaging requirements.<br />
<br />
=== Static Files ===<br />
If your app includes images (e.g. themes do this most of the time), then you should check the generated packaging files for sections marked<br />
<br />
## Uncomment for multiple packages<br />
#...<br />
<br />
and remove the '#' at the start of each line in each block. This enables the creation of a second package, with a name ending in "<tt>-static</tt>". The images and any other files which are not JavaScript or CSS are served by the Apache web server, instead of the OX App Suite application server. These files are copied to a separate package for the case that the web server is on a dedicated system or maybe even has its own cluster. The default package is installed on the OX application server, and the second, "<tt>-static</tt>" package is installed on the web server.<br />
<br />
=== Building Packages ===<br />
Since the actual package format depends on the distribution it is built for, and there already exist tools to create packages from suitably arranged source code archives, the OX App Suite build system merely prepares such source archives. Using the <tt>dist</tt> task to create the archives:<br />
<br />
$ build-appsuite dist<br />
Node version: v0.10.21<br />
Build path: build<br />
Build version: 0.0.1-1.20131025.150034<br />
dpkg-source: info: using source format `3.0 (quilt)'<br />
dpkg-source: info: building example-app using existing ./example-app_0.0.1.orig.tar.bz2<br />
dpkg-source: info: building example-app in example-app_0.0.1-1.debian.tar.bz2<br />
dpkg-source: info: building example-app in example-app_0.0.1-1.dsc<br />
<br />
$ ls tmp/packaging/<br />
example-app-0.0.1 example-app_0.0.1-1.dsc<br />
example-app.spec example-app_0.0.1.orig.tar.bz2<br />
example-app_0.0.1-1.debian.tar.bz2<br />
<br />
The task creates a temporary directory and four files. The archive with the extension <tt>.orig.tar.bz2</tt> contains the source of your app. It is required to build both Debian and RPM packages. The files with extensions <tt>.debian.tar.bz2</tt> and <tt>.dsc</tt> are used together with the <tt>.orig.tar.bz2</tt> archive to build Debian packages. The file with the extension <tt>.spec</tt> is used together with the <tt>.orig.tar.bz2</tt> archive to build RPM packages.<br />
<br />
==== Building Debian Packages ====<br />
The Debian package can be built directly in the temporary directory created by the <tt>dist</tt> task:<br />
<br />
$ cd tmp/packaging/example-app-0.0.1/<br />
$ dpkg-buildpackage -b<br />
<br />
The package will be placed in <tt>tmp/packaging/</tt>.<br />
<br />
==== Building RPM Packages ====<br />
The RPM package build tool <tt>rpmbuild</tt> requires the files to be in a specific directory layout before building:<br />
<br />
$ mkdir -p ~/rpmbuild/{SOURCES,SPECS,BUILD,RPMS}<br />
$ cp tmp/packaging/*.orig.tar.bz2 ~/rpmbuild/SOURCES/<br />
$ cp tmp/packaging/*.spec ~/rpmbuild/SPECS/<br />
$ rpmbuild --define "_topdir $HOME/rpmbuild" -bb ~/rpmbuild/SPECS/*.spec<br />
<br />
The package will be placed in <tt>~/rpmbuild/RPMS/noarch/</tt>.<br />
<br />
The parameter <tt>--define "_topdir $HOME/rpmbuild"</tt> can also be specified in the file <tt>~/.rpmmacros</tt> or, on some distributions, is even unnecessary.<br />
<br />
== Further Reading ==<br />
* You just build your first app for OX App Suite, keep in mind that there [[AppSuite:Developing for the UI#What_can_i_build.3F | quite a few options]] how you can develop for OX App Suite.<br />
* It's highly recommended to gain more knowledge about all the benefits [[AppSuite:UI_build_system | the UI build system]] and [[AppSuite:Appserver|the Appserver]] are providing you for developing OX App Suite.<br />
* If you're stuck somewhere, the article about [[AppSuite:Debugging_the_UI | debugging the UI]] might help you.<br />
* Get a better overview about [[AppSuite:Developing for the UI | developing the user inferface]].</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:GettingStarted_7.4.2&diff=16387AppSuite:GettingStarted 7.4.22013-11-11T15:18:28Z<p>Viktor.Pracht: /* Building */</p>
<hr />
<div><div class="title">Getting Started</div><br />
<br />
<div style="float:right; padding: 10px;">[[File:OX_AppSuite_UI_Development_Workflow.png]]</div><br />
<br />
__TOC__<br />
<br />
Hello and welcome to OX App Suite development. This document will get you started to develop your first own app for OX App Suite with a minimal setup. We will look at the steps necessary but will also tempt you to learn more by linking you to some more in-depth documentation about these topics. Depending on how you wound up reading this page, you will probably have already completed some of the steps below.<br />
<br />
<div style="clear: both"></div><br />
<br />
== Installing ==<br />
<br />
First, you need to install some tools which are necessary for UI development. For now, the simplest way is to download the source of the OX App Suite UI. Since the source code is kept in a [http://git-scm.com/ Git] repository, you will need <tt>git</tt> to download it:<br />
<br />
$ git clone --depth 1 -b release-7.4.1 https://code.open-xchange.com/git/wd/frontend/web<br />
<br />
This downloads the latest version and unpacks it into a subdirectory <tt>web</tt> in the current directory.<br />
<br />
The option <tt>--depth 1</tt> prevents the download of the entire history, and reduces the download size from hundreds of MB to less than 20MB. The option <tt>-b release-7.4.1</tt> specifies a git branch. The full functionality described in this article is only available in the branch <tt>release-7.4.1</tt> until 7.4.1 is released.<br />
<br />
The tools which you will need are contained in the directory <tt>ui/bin</tt>. To simplify their use, you should add this directory to your <tt>$PATH</tt>:<br />
<br />
$ export PATH="$PATH:$(pwd)/web/ui/bin"<br />
<br />
== Create Workspace ==<br />
<br />
Your entire work on an app can take place inside a working directory. The examples will assume you have created a directory named <tt>myapp</tt> inside your home directory:<br />
<br />
$ mkdir ~/myapp<br />
$ cd ~/myapp<br />
<br />
It doesn't need to be in your home directory, and the actual name should reflect the name of your app. The main point is that all commands will be executed in this directory and all relative paths will be relative to this directory from now on.<br />
<br />
The source code of your app will reside in the subfolder named <tt>apps</tt>. To avoid name collisions, pick a unique subfolder inside that. The easiest and recommended way is to use a domain name that you own. Typically, the domain element are reversed, like in Java. <tt>example.com</tt> becomes <tt>com.example</tt>:<br />
<br />
$ mkdir -p apps/com.example<br />
<br />
== Writing ==<br />
<br />
As an example, let's create the smallest possible app and test it. It requires only two files: <tt>apps/com.example/reigster.js</tt> for the source code of the app:<br />
<br />
<pre class="language-javascript"><br />
define('com.example/register', function () {<br />
'use strict';<br />
alert('Hello, World!');<br />
});<br />
</pre><br />
<br />
and <tt>apps/com.example/manifest.json</tt> for the [[AppSuite:UI_manifests_explained | manifest]] which tells the UI that your app exists and what to do with it:<br />
<br />
<pre class="language-javascript">{ "namespace": "core" }</pre><br />
<br />
== Building ==<br />
<br />
The source code of your app can't be used by OX App Suite as it. It has to be first processed by the [[AppSuite:UI_build_system | build system]]. This step will check the source code for syntax errors, compress it, and depending on the structure of your code, many other things. The processed code is then written to a directory named <tt>build</tt> by default. Start the build with this command:<br />
<br />
$ build-appsuite app<br />
<br />
If your editor supports it, you can configure it to call the build system after every file save. Take care to call it from the top directory of your app, not from the directory of the saved file.<br />
<br />
== Testing ==<br />
<br />
The freshly built code can now be tested. Instead of uploading your code to an OX App Suite server, you can use the [[AppSuite:Appserver|appserver]] proxy to inject your code into the UI code of any existing OX App Suite installation. For example, start <tt>appserver</tt> using [http://ox.io/ ox.io] as server:<br />
<br />
<nowiki>$ appserver --server=https://www.ox.io/appsuite/ build</nowiki><br />
<br />
This command will serve your app from the local directory <tt>build</tt>, and get everything else from the URL specified by the <tt>--server</tt> parameter. To serve multiple apps, you can specify multiple local directories separated by spaces.<br />
<br />
You should start <tt>appserver</tt> in a separate terminal, since it needs to run in the background. To stop <tt>appserver</tt>, press <tt>Ctrl+C</tt> in its terminal.<br />
<br />
Once appserver is running, you can access OX App Suite opening your browser with this address:<br />
<br />
http://localhost:8337/appsuite<br />
<br />
After logging in, the app should be loaded and display the <tt>alert</tt> message.<br />
<br />
=== Development cycle ===<br />
<br />
Once you are sure that your setup works, you can extend the example and write the actual code of your app. Keep in mind that after [[#Writing | writing your code]], you will always need to [[#Building | build the app]] and have your [[#Hosting the app | Appserver]] running in the background, but don't need to restart it after every build.<br />
<br />
While developing always keep in mind, that there is an [[AppSuite:Debugging_the_UI | article about debugging the user interface]] which helps you avoiding and fixing typical errors.<br />
<br />
== Packaging ==<br />
<br />
When your app is done, you probably want to test it on a staging system, and later install it on a production system. To keep track of which installed files belong to which version of which app, you should use the native package manager of the Linux distribution of the target system. The packages can be easily created using the build system.<br />
<br />
=== Initialization ===<br />
First, you need to create several files describing how to package you app. Use the <tt>init-packaging</tt> task of the build system:<br />
<br />
$ build-appsuite init-packaging<br />
Node version: v0.10.21<br />
Build path: build<br />
Build version: 0.0.1-1.20131025.133931<br />
Package name: example-app<br />
Version [0.0.1]: <br />
Maintainer (Name <e-mail>): Maintainer <maintainer@example.com><br />
Copyright line [2013 Open-Xchange, Inc]: <br />
<br />
Known licenses for which you don't need to specify a file:<br />
APACHE-2, BSD-2-CLAUSE, BSD-3-CLAUSE, CC-BY-3, CC-BY-NC-3, CC-BY-NC-ND-3,<br />
CC-BY-NC-SA-3, CC-BY-ND-3, CC-BY-SA-3, CC0-1, EXPAT, GPL-2, GPL-3, LGPL-3<br />
<br />
License name [CC-BY-NC-SA-3.0]: BSD-3-Clause<br />
Short description: Example app<br />
<br />
The task presents a number of interactive prompts to get the necessary information about the generated packages. The default values are presented in square brackets ([...]) and can be selected by just pressing Enter. Otherwise, the entered values should follow the Debian Maintainer's Guide. Debian tools are especially picky about the syntax of the maintainer name and email address.<br />
<br />
If none of the known licenses suit you, you can enter any other license name. Then you will be asked to enter the file name of your license text. It should be a plain text file using the UTF-8 encoding.<br />
<br />
Some or even all prompts can be skipped by explicitly specifying the information as a build variable. The list of variable names is available in the reference of the <tt>[[AppSuite:UI_build_system#init-packaging|init-packaging]]</tt> task.<br />
<br />
After answering all the questions, you can customize the generated files to account for any additional packaging requirements.<br />
<br />
=== Static Files ===<br />
If your app includes images (e.g. themes do this most of the time), then you should check the generated packaging files for sections marked<br />
<br />
## Uncomment for multiple packages<br />
#...<br />
<br />
and remove the '#' at the start of each line in each block. This enables the creation of a second package, with a name ending in "<tt>-static</tt>". The images and any other files which are not JavaScript or CSS are served by the Apache web server, instead of the OX App Suite application server. These files are copied to a separate package for the case that the web server is on a dedicated system or maybe even has its own cluster. The default package is installed on the OX application server, and the second, "<tt>-static</tt>" package is installed on the web server.<br />
<br />
=== Building Packages ===<br />
Since the actual package format depends on the distribution it is built for, and there already exist tools to create packages from suitably arranged source code archives, the OX App Suite build system merely prepares such source archives. Using the <tt>dist</tt> task to create the archives:<br />
<br />
$ build-appsuite dist<br />
Node version: v0.10.21<br />
Build path: build<br />
Build version: 0.0.1-1.20131025.150034<br />
dpkg-source: info: using source format `3.0 (quilt)'<br />
dpkg-source: info: building example-app using existing ./example-app_0.0.1.orig.tar.bz2<br />
dpkg-source: info: building example-app in example-app_0.0.1-1.debian.tar.bz2<br />
dpkg-source: info: building example-app in example-app_0.0.1-1.dsc<br />
<br />
$ ls tmp/packaging/<br />
example-app-0.0.1 example-app_0.0.1-1.dsc<br />
example-app.spec example-app_0.0.1.orig.tar.bz2<br />
example-app_0.0.1-1.debian.tar.bz2<br />
<br />
The task creates a temporary directory and four files. The archive with the extension <tt>.orig.tar.bz2</tt> contains the source of your app. It is required to build both Debian and RPM packages. The files with extensions <tt>.debian.tar.bz2</tt> and <tt>.dsc</tt> are used together with the <tt>.orig.tar.bz2</tt> archive to build Debian packages. The file with the extension <tt>.spec</tt> is used together with the <tt>.orig.tar.bz2</tt> archive to build RPM packages.<br />
<br />
==== Building Debian Packages ====<br />
The Debian package can be built directly in the temporary directory created by the <tt>dist</tt> task:<br />
<br />
$ cd tmp/packaging/example-app-0.0.1/<br />
$ dpkg-buildpackage -b<br />
<br />
The package will be placed in <tt>tmp/packaging/</tt>.<br />
<br />
==== Building RPM Packages ====<br />
The RPM package build tool <tt>rpmbuild</tt> requires the files to be in a specific directory layout before building:<br />
<br />
$ mkdir -p ~/rpmbuild/{SOURCES,SPECS,BUILD,RPMS}<br />
$ cp tmp/packaging/*.orig.tar.bz2 ~/rpmbuild/SOURCES/<br />
$ cp tmp/packaging/*.spec ~/rpmbuild/SPECS/<br />
$ rpmbuild --define "_topdir $HOME/rpmbuild" -bb ~/rpmbuild/SPECS/*.spec<br />
<br />
The package will be placed in <tt>~/rpmbuild/RPMS/noarch/</tt>.<br />
<br />
The parameter <tt>--define "_topdir $HOME/rpmbuild"</tt> can also be specified in the file <tt>~/.rpmmacros</tt> or, on some distributions, is even unnecessary.<br />
<br />
== Further Reading ==<br />
* You just build your first app for OX App Suite, keep in mind that there [[AppSuite:Developing for the UI#What_can_i_build.3F | quite a few options]] how you can develop for OX App Suite.<br />
* It's highly recommended to gain more knowledge about all the benefits [[AppSuite:UI_build_system | the UI build system]] and [[AppSuite:Appserver|the Appserver]] are providing you for developing OX App Suite.<br />
* If you're stuck somewhere, the article about [[AppSuite:Debugging_the_UI | debugging the UI]] might help you.<br />
* Get a better overview about [[AppSuite:Developing for the UI | developing the user inferface]].</div>Viktor.Prachthttps://oxpedia.org/wiki/index.php?title=AppSuite:GettingStarted_7.4.2&diff=16383AppSuite:GettingStarted 7.4.22013-11-11T15:00:00Z<p>Viktor.Pracht: /* Building */</p>
<hr />
<div><div class="title">Getting Started</div><br />
<br />
<div style="float:right; padding: 10px;">[[File:OX_AppSuite_UI_Development_Workflow.png]]</div><br />
<br />
__TOC__<br />
<br />
Hello and welcome to OX App Suite development. This document will get you started to develop your first own app for OX App Suite with a minimal setup. We will look at the steps necessary but will also tempt you to learn more by linking you to some more in-depth documentation about these topics. Depending on how you wound up reading this page, you will probably have already completed some of the steps below.<br />
<br />
<div style="clear: both"></div><br />
<br />
== Installing ==<br />
<br />
First, you need to install some tools which are necessary for UI development. For now, the simplest way is to download the source of the OX App Suite UI. Since the source code is kept in a [http://git-scm.com/ Git] repository, you will need <tt>git</tt> to download it:<br />
<br />
$ git clone --depth 1 -b release-7.4.1 https://code.open-xchange.com/git/wd/frontend/web<br />
<br />
This downloads the latest version and unpacks it into a subdirectory <tt>web</tt> in the current directory.<br />
<br />
The option <tt>--depth 1</tt> prevents the download of the entire history, and reduces the download size from hundreds of MB to less than 20MB. The option <tt>-b release-7.4.1</tt> specifies a git branch. The full functionality described in this article is only available in the branch <tt>release-7.4.1</tt> until 7.4.1 is released.<br />
<br />
The tools which you will need are contained in the directory <tt>ui/bin</tt>. To simplify their use, you should add this directory to your <tt>$PATH</tt>:<br />
<br />
$ export PATH="$PATH:$(pwd)/web/ui/bin"<br />
<br />
== Create Workspace ==<br />
<br />
Your entire work on an app can take place inside a working directory. The examples will assume you have created a directory named <tt>myapp</tt> inside your home directory:<br />
<br />
$ mkdir ~/myapp<br />
$ cd ~/myapp<br />
<br />
It doesn't need to be in your home directory, and the actual name should reflect the name of your app. The main point is that all commands will be executed in this directory and all relative paths will be relative to this directory from now on.<br />
<br />
The source code of your app will reside in the subfolder named <tt>apps</tt>. To avoid name collisions, pick a unique subfolder inside that. The easiest and recommended way is to use a domain name that you own. Typically, the domain element are reversed, like in Java. <tt>example.com</tt> becomes <tt>com.example</tt>:<br />
<br />
$ mkdir -p apps/com.example<br />
<br />
== Writing ==<br />
<br />
As an example, let's create the smallest possible app and test it. It requires only two files: <tt>apps/com.example/reigster.js</tt> for the source code of the app:<br />
<br />
<pre class="language-javascript"><br />
define('com.example/register', function () {<br />
'use strict';<br />
alert('Hello, World!');<br />
});<br />
</pre><br />
<br />
and <tt>apps/com.example/manifest.json</tt> for the [[AppSuite:UI_manifests_explained | manifest]] which tells the UI that your app exists and what to do with it:<br />
<br />
<pre class="language-javascript">{ "namespace": "core" }</pre><br />
<br />
== Building ==<br />
<br />
This step will process your app, checking the source code for syntax errors and compressing it, to make it run error-free and fast. Calling this command will write the processed source to a subdirectory called <tt>build</tt>.<br />
<br />
Using the [[AppSuite:UI_build_system | the UI Build System]] makes building the app is as easy as calling:<br />
<br />
$ build-appsuite app<br />
<br />
== Testing ==<br />
<br />
The freshly built code can now be tested. Instead of uploading your code to an OX App Suite server, you can use the [[AppSuite:Appserver|appserver]] proxy to inject your code into the UI code of any existing OX App Suite installation. For example, start <tt>appserver</tt> using [http://ox.io/ ox.io] as server:<br />
<br />
<nowiki>$ appserver --server=https://www.ox.io/appsuite/ build</nowiki><br />
<br />
This command will serve your app from the local directory <tt>build</tt>, and get everything else from the URL specified by the <tt>--server</tt> parameter. To serve multiple apps, you can specify multiple local directories separated by spaces.<br />
<br />
You should start <tt>appserver</tt> in a separate terminal, since it needs to run in the background. To stop <tt>appserver</tt>, press <tt>Ctrl+C</tt> in its terminal.<br />
<br />
Once appserver is running, you can access OX App Suite opening your browser with this address:<br />
<br />
http://localhost:8337/appsuite<br />
<br />
After logging in, the app should be loaded and display the <tt>alert</tt> message.<br />
<br />
=== Development cycle ===<br />
<br />
Once you are sure that your setup works, you can extend the example and write the actual code of your app. Keep in mind that after [[#Writing | writing your code]], you will always need to [[#Building | build the app]] and have your [[#Hosting the app | Appserver]] running in the background, but don't need to restart it after every build.<br />
<br />
While developing always keep in mind, that there is an [[AppSuite:Debugging_the_UI | article about debugging the user interface]] which helps you avoiding and fixing typical errors.<br />
<br />
== Packaging ==<br />
<br />
When your app is done, you probably want to test it on a staging system, and later install it on a production system. To keep track of which installed files belong to which version of which app, you should use the native package manager of the Linux distribution of the target system. The packages can be easily created using the build system.<br />
<br />
=== Initialization ===<br />
First, you need to create several files describing how to package you app. Use the <tt>init-packaging</tt> task of the build system:<br />
<br />
$ build-appsuite init-packaging<br />
Node version: v0.10.21<br />
Build path: build<br />
Build version: 0.0.1-1.20131025.133931<br />
Package name: example-app<br />
Version [0.0.1]: <br />
Maintainer (Name <e-mail>): Maintainer <maintainer@example.com><br />
Copyright line [2013 Open-Xchange, Inc]: <br />
<br />
Known licenses for which you don't need to specify a file:<br />
APACHE-2, BSD-2-CLAUSE, BSD-3-CLAUSE, CC-BY-3, CC-BY-NC-3, CC-BY-NC-ND-3,<br />
CC-BY-NC-SA-3, CC-BY-ND-3, CC-BY-SA-3, CC0-1, EXPAT, GPL-2, GPL-3, LGPL-3<br />
<br />
License name [CC-BY-NC-SA-3.0]: BSD-3-Clause<br />
Short description: Example app<br />
<br />
The task presents a number of interactive prompts to get the necessary information about the generated packages. The default values are presented in square brackets ([...]) and can be selected by just pressing Enter. Otherwise, the entered values should follow the Debian Maintainer's Guide. Debian tools are especially picky about the syntax of the maintainer name and email address.<br />
<br />
If none of the known licenses suit you, you can enter any other license name. Then you will be asked to enter the file name of your license text. It should be a plain text file using the UTF-8 encoding.<br />
<br />
Some or even all prompts can be skipped by explicitly specifying the information as a build variable. The list of variable names is available in the reference of the <tt>[[AppSuite:UI_build_system#init-packaging|init-packaging]]</tt> task.<br />
<br />
After answering all the questions, you can customize the generated files to account for any additional packaging requirements.<br />
<br />
=== Static Files ===<br />
If your app includes images (e.g. themes do this most of the time), then you should check the generated packaging files for sections marked<br />
<br />
## Uncomment for multiple packages<br />
#...<br />
<br />
and remove the '#' at the start of each line in each block. This enables the creation of a second package, with a name ending in "<tt>-static</tt>". The images and any other files which are not JavaScript or CSS are served by the Apache web server, instead of the OX App Suite application server. These files are copied to a separate package for the case that the web server is on a dedicated system or maybe even has its own cluster. The default package is installed on the OX application server, and the second, "<tt>-static</tt>" package is installed on the web server.<br />
<br />
=== Building Packages ===<br />
Since the actual package format depends on the distribution it is built for, and there already exist tools to create packages from suitably arranged source code archives, the OX App Suite build system merely prepares such source archives. Using the <tt>dist</tt> task to create the archives:<br />
<br />
$ build-appsuite dist<br />
Node version: v0.10.21<br />
Build path: build<br />
Build version: 0.0.1-1.20131025.150034<br />
dpkg-source: info: using source format `3.0 (quilt)'<br />
dpkg-source: info: building example-app using existing ./example-app_0.0.1.orig.tar.bz2<br />
dpkg-source: info: building example-app in example-app_0.0.1-1.debian.tar.bz2<br />
dpkg-source: info: building example-app in example-app_0.0.1-1.dsc<br />
<br />
$ ls tmp/packaging/<br />
example-app-0.0.1 example-app_0.0.1-1.dsc<br />
example-app.spec example-app_0.0.1.orig.tar.bz2<br />
example-app_0.0.1-1.debian.tar.bz2<br />
<br />
The task creates a temporary directory and four files. The archive with the extension <tt>.orig.tar.bz2</tt> contains the source of your app. It is required to build both Debian and RPM packages. The files with extensions <tt>.debian.tar.bz2</tt> and <tt>.dsc</tt> are used together with the <tt>.orig.tar.bz2</tt> archive to build Debian packages. The file with the extension <tt>.spec</tt> is used together with the <tt>.orig.tar.bz2</tt> archive to build RPM packages.<br />
<br />
==== Building Debian Packages ====<br />
The Debian package can be built directly in the temporary directory created by the <tt>dist</tt> task:<br />
<br />
$ cd tmp/packaging/example-app-0.0.1/<br />
$ dpkg-buildpackage -b<br />
<br />
The package will be placed in <tt>tmp/packaging/</tt>.<br />
<br />
==== Building RPM Packages ====<br />
The RPM package build tool <tt>rpmbuild</tt> requires the files to be in a specific directory layout before building:<br />
<br />
$ mkdir -p ~/rpmbuild/{SOURCES,SPECS,BUILD,RPMS}<br />
$ cp tmp/packaging/*.orig.tar.bz2 ~/rpmbuild/SOURCES/<br />
$ cp tmp/packaging/*.spec ~/rpmbuild/SPECS/<br />
$ rpmbuild --define "_topdir $HOME/rpmbuild" -bb ~/rpmbuild/SPECS/*.spec<br />
<br />
The package will be placed in <tt>~/rpmbuild/RPMS/noarch/</tt>.<br />
<br />
The parameter <tt>--define "_topdir $HOME/rpmbuild"</tt> can also be specified in the file <tt>~/.rpmmacros</tt> or, on some distributions, is even unnecessary.<br />
<br />
== Further Reading ==<br />
* You just build your first app for OX App Suite, keep in mind that there [[AppSuite:Developing for the UI#What_can_i_build.3F | quite a few options]] how you can develop for OX App Suite.<br />
* It's highly recommended to gain more knowledge about all the benefits [[AppSuite:UI_build_system | the UI build system]] and [[AppSuite:Appserver|the Appserver]] are providing you for developing OX App Suite.<br />
* If you're stuck somewhere, the article about [[AppSuite:Debugging_the_UI | debugging the UI]] might help you.<br />
* Get a better overview about [[AppSuite:Developing for the UI | developing the user inferface]].</div>Viktor.Pracht