------------------------------------------------------------
GOALS/CONCEPTS
------------------------------------------------------------
0) we have too many ways of getting at data (content, ical, rss, etc), we have:

  get an attachment: 

    http://{server}/service/content/get?id=544&part=2

  get the calendar as ical: 

    http://{server}/service/ical/cal.ics  

  get an RSS feed ("is:unread inbox" by default):

    http://{server}/service/rss/index.rss[?query=...]

  get the contacts (all contacts not in trash):

    http://{server}/service/csv/contacts.csv

  We'll also be adding calendar free/busy and public folders/documents.

  We should unify all these into a single access mechanism with consistent naming.

  When you toss in the ability to request that for another account as well things
  get ugly.

1) everything item should be addressable using a clean, REST URL format

2) Should have user-friendly URLs for humans consumption, as well 
   as low-level ID-driven URLs for use within programs (web client references to
   attachemnts, etc).

3) Should be able to request different "flavors" for content. i.e., XML, JSON,
   ICS, RSS/ATOM, RDF, HTML, CSV, microformats, etc. The flavor will be based 
   on the "fmt" query param. "flavor" is a term used in articles on REST, 
   and basically means MIME content-type. If an explicit flavor is not requested,
   then the default for a given type will be used.

   folders in our system have a "hint" for which view to use to display the folder's
   contents. We should use that hint to determine the default flavor for a folder.

4) all items should minimally have an XML and JSON repsentation, ideally using 
   our existing formats, though we might want to re-examine them and/or have different
   views for those types.

5) we should design this with "publishing" and "public" folders/wiki in mind

------------------------------------------------------------
URL
------------------------------------------------------------

   http://server/home/[~][{username}]/[{folder}]?[{query-params}]
          fmt={ics, csv, ldif, netscapeldif etc}
          id={item-id}
          list={item-id}*[,{item-id}]
          imap_id={item-imap-id}  (must also specify folder)
          part={mime-part}
          query={search-query}
          types={types} // when searching
          start={date-specifier}
          end={date-specifier}
          auth={auth-types}
          disp=i|a

          {disp} = i - means "inline" and the browser will open up the attachment inline
                   a - means "attachment" and the browser will put up a download window

          {types}   = comma-separated list.  Legal values are:
                      conversation|message|contact|appointment|note
                      (default is "conversation")

          {date-specifier} = mm/dd/yyyy | yyyy/dd/mm | \d+ (milliseconds) | [mp+-]?([0-9]+)([mhdwy][a-z]*)

              absolute dates:
  
              mm/dd/yyyy (i.e., 12/25/1998)
              yyyy/dd/mm (i.e., 1989/12/25)
              \d+       (num milliseconds, i.e., 1132276598000)   
  
             relative dates:
  
             [mp+-]?([0-9]+)([mhdwy][a-z]*)?g

             p/+/{not-specified}   current time plus an offset (p and '' are supported for use in query params)
             m/-                   current time minus an offset
 
             ([mhdwy][a-z]*)  units, everything after the first character is ignored (except for "mi" case):

             m(onths)
             mi(nutes)
             d(ays)
             w(eeks)
             h(ours)
             y(ears)
     
             examples:
               1day     1 day from now
              +2days    2 days from now 
              p1day     1 day from now
              -2days     2 days ago
              +60mi     60 minutes from now
              +1week    1 week from now
              +6mon     6 months from now 
              1year     1 year from now

          {auth-types} = comma-separated list. Legal values are:
              co     cookie
              ba     basic auth (same as nsc after bug 42782)
              nsc    basic auth, and do not set a cookie when using basic auth
              sc     basic auth, and set a cookie when using basic auth
              (default is "co,nsc", i.e. check both)

          fmt="sync" -- requests that the server return additional metadata in
              response as X-Zimbra-* HTTP headers
              (query param "nohdr=1" puts the headers only in HTTP; otherwise,
              they're also inlined in the response body)

          fmt="tar", "tgz", "zip" -- stream multiple items in an archive format.
              These forms are a superset of most other REST formatters

              Download options: export item data in raw or interchange format

              body=0 only include msg headers, not bodies

              charset=name character set for tar file and directory names as
                  well as ical or vcard text. UTF-8 is default

              emptyname=name filename to set in content-disposition header if
                  no data items are found in query instead of returning HTTP
                  204 error

              file=name filename to set in content-disposition header

              lock=1 lock mailbox before running query to assure a complete,
                  consistent snapshot

              meta=0 data items saved in common interchange formats including
                  eml for mail, ical for appointments and vcard for contacts.
                  Briefcase files saved unmodified

              meta=1 (default) item metadata from the DB is JSON encoded as
                  .meta files. Associated data blobs follow immediately after

              Upload options: POST to the original folder or a subfolder in raw
                  or MIME encoded data stream. If .meta files are included,
                  data will be imported with original details. Otherwise, eml,
                  ics and vcards are imported the same as with other formatters
                  and all other files are imported to the briefcase

              callback=name name of javascript function used to return status
                  when doing a direct browser upload.
                  window.parent.name("exception string", "exception class name",
                  exception_code) is called when the upload completes.
                  plain html is returned by default if callback unspecified

              charset=name character set for archive file and directory names as
                  well as ical or vcard text

              resolve=[modfy|replace|reset|skip] how to handle duplicate data
                  conflicts
                  modify   modify old item in place
                  replace  delete old item and recreate
                  reset    reset folder by deleting all item before importing
                  skip (default) skip duplicate items completely

              subfolder=name create subfolder under the destination to import
                  items into

              timestamp=0 do not use the archive entry date as the received
                  date for msgs or the creation date for documents. Msg dates
                  will be inferred from the Date header if available

              timeout=mscec update brower client with a text newline to prevent
                  upload timeouts
                 
              nohierarchy=1 do not include the target folder's parent hierarchy 

------------------------------------------------------------
EXAMPLES
------------------------------------------------------------

There are two primary formats, one using a folder, and one using a mail item id.

http://server/home/[~]{account-name}/{folder-path}    // path to a folder 
http://server/home/[~]{account-name}/?id={item-id}    // a mail item id

A single ~ is allowed and references the authenticated user accessing the data. 

Some examples:

/home/roland/inbox.rss                    // RSS feed of inbox
/home/roland/inbox.xml                    // Zimbra XML representation of inbox
/home/roland/inbox.zip                    // A ZIP file of all messages in the inbox folder

/home/roland/contacts                     // CSV view of contacts folder
/home/roland/contacts?fmt=json            // JSON view of contacts folder

/home/roland/calendars                    // ICS view of calendar
/home/janie/holidays                      // Janie's holidays calendar
/home/roland/calendar/project.html        // html view of calendar/projects calendar
/home/roland/calendar.atom                // atom feed of calendar  (-7/+7 days by default)
/home/roland/calendar.atom?start=0day&end=+2weeks    // atom feed of calendar for next two weeks

The second format is used to reference something by its mail item id:

/home/roland/?id=10                       // ICS view of calendar, referenced via ID
/home/roland/?id=945&fmt=vcf              // contact formatted as a vcard
/home/roland/?id=100&part=2.3             // mime part 2.3 from message with id 100
/home/roland/?id=100&part=1,4,5&fmt=zip   // zipfile containing mime parts 1, 4, and 5 from message with id 100
/home/roland/?id=100&part=2&view=text     // Used for show original of a message attachment (part 2 in this case)
                                          // To avoid problems with browsers, given Content-Type: text/plain
                                          // instead of message/rfc822

When we support documents in a folder, we'd use the document's name as you'd expect:

/home/smith/work/partner/authentication.doc

We should of course be able to convert attachments to HTML (via Verity) with this
syntax:

/home/roland/?id=564&part=4&view=html   // part 4 (which could be a word doc) in html

A list of files in a zip package:

/home/smith/?fmt=zip&list=12345,22453    // a zip file containing two mail items

------------------------------------------------------------
CALENDAR OPTIONS
------------------------------------------------------------
tz=timezone
date=YYYYMMDD
view=day|workWeek|week|month
notoolbar=1
skin={skin-name}
color=defaultColor(0),
        blue(1),
        cyan(2),
        green(3),
        purple(4),
        red(5),
        yellow(6),
        pink(7),
        gray(8),
        orange(9);


------------------------------------------------------------
SEARCHING
------------------------------------------------------------

Since search is a big part of Zimbra, all item URLs should generally allow a search
query to either gather all results, or constrain them. For example:

/home/roland/inbox.rss

This would give back a simple RSS feed of all items in the inbox. To send back only
unread, you'd do:

/home/roland/inbox.rss?query="is:unread"

or:

/home/roland/?fmt=rss&query="in:inbox is:unread"

We probably want to allow the same params that the SearchRequest soap command allows,
to allow for paging, restricting what types of items are returned, etc:

 types="{types}" (done)
 
 [limit="..."] 
 [offset="..."]
 [sortBy="{sort-by}"]
 [groupBy="{group-by}"] 

 [cursorId="prevId"]

------------------------------------------------------------
ACCESSING DATA ACROSS Zimbra DOMAINs
------------------------------------------------------------

1. Intra-domain (authoratative domains within a Zimbra install)

to access items across domains within a Zimra install, specify an @ in the mailbox
name:

/home/schemers@zimbra.com/calendar
/home/joer@zombo.com/calendar

Both zimbra.com and zombo.com are part of the same Zimbra install, and thus accounts
and mailbox locations on both can be resolved internally.

2. Inter-domain

To access items across domains that span Zimbra installations, use the
exact same naming convention.

For example, if companyA installs Zimbra, and companyB installs Zimbra, someone at
companyA should be able to reference an item from companyB using the same syntax:

/home/john.smith@companyB.com/shared/contacts

this can be accomplished with DNS SRV records. For example, companyB.com could
publish a SRV record for _zimbra._tcp:

_zimbra._tcp.companyB.com. SRV   10  5   80      zimbra.companyB.com

The Zimbra proxy at companyA can then detect that companyB.com is not a local Zimbra
domain, and do a DNS lookup for:

_zimbra._tcp.companyB.com

And get back "zimbra.companyB.com" as the name of the Zimbra sever to
direct the request to. It would then do the equivalent of:

http://zimbra.companyB.com/home/john.smith@companyB.com/shared/contacts

------------------------------------------------------------
ISSUES/NOTES
------------------------------------------------------------

1. how do you specify a folder and all sub folders recursively?

  For example, I can see wanting to specify:

  /home/roland/sales?fmt=zip                 // the sales folder only
  /home/roland/sales?fmt=zip?recursive=1     // sales folder and all recursive
  /home/roland/sales/*?fmt=zip               // all folders in sales (not including sales)
  /home/roland/sales/*?fmt=zip?recursive=1   //  same as previous, but recursive

2. user-friendly item "ids"? It would be nice to have user-friendly names 
   for items inside of a folder, such as (+ is url-encoded form of a space):

  /home/roland/calendar/Staff+Meeting
  /home/roland/contacts/Roland+Schemers
  /home/roland/inbox/Important+Meeting

  Exchange allows this type of naming, need to determine how/if we'd want to do
  this, and how to deal with collisions like it does. 
  
  Might need to come up with a per-item query-param string, or use search:
  
  /home/roland/contacts/?query="Roland Schemers"

3. there will probably by mail-item specific query params, like duration for 
   calendars, picking alternate views for .html flavors, etc. Should try and
   standardize where possible. For exmaple:

   /home/roland/calendar?start=20051225&fmt=hmtl&view=week

4. calendar free/busy chould also be exported via this mechanism:

   /home/schemers/?fmt=vfb

   specifying it on the "root" folder would get the free/busy for all calendars that
   are marked to be included in free/busy.

5. initially we might not support things like:

   /home/roland/inbox?fmt=csv

   but ideally we'd emit a simple CSV format. We could define to be something like a
   separate column for each header, and specially named columns for the "body" 
   and/or mime parts of the message. The mime body parts would not be incuded, 
   just a URL referencing them.

6. We should have an extension mechanism to allow people to plug in the their own
   formats. The plugin would get a context containing the query params, the path 
   (resolve/unresovled parts), and the target mail item.

7. When using the extension-style format syntax:

   /home/roland/inbox.rss
   
   vs:
   
   /home/roland/inbox?fmt=rss

  If there is a folder/document that is actually named "inbox.rss", then it takes precedence
  over the "inbox" folder. So you'll have to explicitly use the fmt query parameter to 
  disambiguate between the two:

   /home/roland/inbox?fmt=rss
   /home/roland/inbox.rss?fmt=zip
   
------------------------------------------------------------
REFERENCES
------------------------------------------------------------
REST (Representational State Transfer)

  http://www.xfront.com/REST.html

Building Web Services the REST Way

  http://www.xfront.com/REST-Web-Services.html

Meerkat: An Open Service API

  http://www.oreillynet.com/pub/a/rss/2000/05/09/meerkat_api.html

REST and the Real World
 
  http://webservices.xml.com/pub/a/ws/2002/02/20/rest.html?page=1

Microformats

  http://microformats.org/

Hula URLs

  http://www.hula-project.org/Hula_URLs

------------------------------------------------------------
APPENDIX A: URL forms
------------------------------------------------------------
Here various ways to access john.doe@zimbra.com's calendar:

shortcut to yourself: 
  /home/~/calendar
  /home/~/?id=10       // id 10 is always the calendar folder

explicit account: 
   /~john.doe/calendar
   /home/john.doe/calendar
   /home/john.doe/?id=10
   /home/john.doe@zimbra.com/calendar
   /home/34cc4086-801e-42a0-a67a-ea93c1590c4e/?id=10
   
------------------------------------------------------------
APPENDIX B: POST Data with CSRF token
------------------------------------------------------------
For POST request which is currently supported for Import in ZWC the CSRF token is expected 
as a HTTP header
X-Zimbra-Csrf-Token
or as a form field
csrfToken

------Example with Form field ---
Content-Disposition: form-data; name="csrfToken"
0_2f9a602552d8be83930b8e061718a5b56eabbc87

----Example with Http Header----
Referer http://localhost:7070/
X-Zimbra-Csrf-Token 0_b9c88c641becf7943e7c9af7e569ea911cf8b7a0

---------------------------------------------------
Profile configuration files
This rest api will allow user to download his/her profile configuration file to configure account on mac/iphone.
---------------------------------------------------
/home/<user_email>/?fmt=mobileconfig&configType=<config_type>
supported config types
    1. caldav
    2. carddav
    3. imap
    4. dav (caldav and carddav)
    5. all (caldav, carddav and imap)
