Skip to content

Commit

Permalink
WIP - http_convert
Browse files Browse the repository at this point in the history
Signed-off-by: Robert Stepanek <rsto@fastmailteam.com>
  • Loading branch information
rsto committed Jan 12, 2024
1 parent f34a507 commit c68acc5
Show file tree
Hide file tree
Showing 8 changed files with 264 additions and 23 deletions.
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -1338,6 +1338,7 @@ BUILT_SOURCES += \
imap_httpd_SOURCES += \
imap/defaultalarms.c \
imap/defaultalarms.h \
imap/http_convert.c \
imap/http_jmap.c \
imap/http_jmap.h \
imap/jmap_admin.c \
Expand Down
223 changes: 223 additions & 0 deletions imap/http_convert.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
/* http_convert.c -- Routines for converting media types over HTTP
*
* Copyright (c) 1994-2023 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any legal
* details, please contact
* Carnegie Mellon University
* Center for Technology Transfer and Enterprise Creation
* 4615 Forbes Avenue
* Suite 302
* Pittsburgh, PA 15213
* (412) 268-7393, fax: (412) 268-7395
* innovation@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/

#include <config.h>

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <ctype.h>
#include <string.h>
#include <syslog.h>
#include <assert.h>

#include "acl.h"
#include "annotate.h"
#include "charset.h"
#include "global.h"
#include "httpd.h"
#include "http_proxy.h"
#include "jmap_ical.h"
#include "mailbox.h"
#include "map.h"
#include "mboxlist.h"
#include "message.h"
#include "parseaddr.h"
#include "proxy.h"
#include "times.h"
#include "seen.h"
#include "tok.h"
#include "util.h"
#include "version.h"
#include "wildmat.h"
#include "xmalloc.h"
#include "xstrlcpy.h"

/* generated headers are not necessarily in current directory */
#include "imap/http_err.h"
#include "imap/imap_err.h"

static void convert_init(struct buf *serverinfo);
static int meth_post(struct transaction_t *txn, void *params);

struct namespace_t namespace_convert = {
URL_NS_DEFAULT, 0, "convert", "/convert", NULL,
http_allow_noauth_get, /*authschemes*/0,
/*mbtype*/0,
ALLOW_POST,
convert_init, NULL, NULL, NULL, NULL,
{
{ NULL, NULL }, /* ACL */
{ NULL, NULL }, /* BIND */
{ NULL, NULL }, /* CONNECT */
{ NULL, NULL }, /* COPY */
{ NULL, NULL }, /* DELETE */
{ NULL, NULL }, /* GET */
{ NULL, NULL }, /* HEAD */
{ NULL, NULL }, /* LOCK */
{ NULL, NULL }, /* MKCALENDAR */
{ NULL, NULL }, /* MKCOL */
{ NULL, NULL }, /* MOVE */
{ NULL, NULL }, /* OPTIONS */
{ NULL, NULL }, /* PATCH */
{ &meth_post, NULL }, /* POST */
{ NULL, NULL }, /* PROPFIND */
{ NULL, NULL }, /* PROPPATCH */
{ NULL, NULL }, /* PUT */
{ NULL, NULL }, /* REPORT */
{ NULL, NULL }, /* SEARCH */
{ NULL, NULL }, /* TRACE */
{ NULL, NULL }, /* UNBIND */
{ NULL, NULL } /* UNLOCK */
}
};


static void convert_init(struct buf *serverinfo __attribute__((unused)))
{
namespace_convert.enabled = config_httpmodules & IMAP_ENUM_HTTPMODULES_CONVERT;
}

static int convert_parse_path(const char *path, struct request_target_t *tgt,
const char **resultstr)
{
size_t len;
char *p;

if (*tgt->path) return 0; /* Already parsed */

/* Make a working copy of target path */
strlcpy(tgt->path, path, sizeof(tgt->path));
p = tgt->path;

/* Sanity check namespace */
len = strlen(namespace_convert.prefix);
if (strlen(p) < len ||
strncmp(namespace_convert.prefix, p, len) ||
(path[len] && path[len] != '/')) {
*resultstr = "Namespace mismatch request target path";
return HTTP_FORBIDDEN;
}

/* Always allow read, even if no content */
tgt->allow = ALLOW_READ;

/* Skip namespace */
p += len;

/* Check for path after prefix */
if (*p == '/') p++;
if (*p) return HTTP_NOT_FOUND;

tgt->allow |= ALLOW_POST;

return 0;
}

/* Perform a POST request */
static int meth_post(struct transaction_t *txn,
void *params __attribute__((unused)))
{
icalcomponent *ical = NULL;
json_t *jval = NULL;
struct buf buf = BUF_INITIALIZER;
char *resp_payload = NULL;

int ret = convert_parse_path(txn->req_uri->path,
&txn->req_tgt, &txn->error.desc);
if (ret) return ret;

if (!(txn->req_tgt.allow & ALLOW_POST)) {
ret = HTTP_NOT_ALLOWED;
goto done;
}

/* Check Content-Type */
const char **hdr = spool_getheader(txn->req_hdrs, "Content-Type");
if (!hdr || !is_mediatype("text/calendar", hdr[0])) {
txn->error.desc = "This method requires a text/calendar body";
ret = HTTP_BAD_MEDIATYPE;
goto done;
}

/* Read body */
ret = http_read_req_body(txn);
if (ret) {
txn->flags.conn = CONN_CLOSE;
goto done;
}

/* Parse the request body */
ical = icalparser_parse_string(buf_cstring(&txn->req_body.payload));
if (!ical) {
txn->error.desc = "Could not parse iCalendar data";
ret = HTTP_BAD_REQUEST;
goto done;
}

/* Convert to JSCalendar */
jval = jmapical_vcalendar_to_jsgroup(ical);
if (!jval) {
txn->error.desc = "Could not convert to JSCalendar";
ret = HTTP_SERVER_ERROR;
goto done;
}

/* Write the response */
resp_payload = json_dumps(jval, JSON_PRESERVE_ORDER |
(config_httpprettytelemetry ? JSON_INDENT(2) : JSON_COMPACT));
if (!resp_payload) {
txn->error.desc = "Error dumping JSON object";
ret = HTTP_SERVER_ERROR;
goto done;
}
txn->resp_body.type = "application/jscalendar+json;type=group";
write_body(HTTP_OK, txn, resp_payload, strlen(resp_payload));

done:
if (ical) icalcomponent_free(ical);
json_decref(jval);
buf_free(&buf);
free(resp_payload);
return ret;
}
1 change: 1 addition & 0 deletions imap/httpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,7 @@ static struct namespace_t namespace_default = {
struct namespace_t *http_namespaces[] = {
#ifdef WITH_JMAP
&namespace_jmap,
&namespace_convert,
#endif
&namespace_tzdist, /* MUST be before namespace_calendar!! */
#ifdef WITH_DAV
Expand Down
1 change: 1 addition & 0 deletions imap/httpd.h
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,7 @@ extern struct namespace_t namespace_domainkey;
extern struct namespace_t namespace_tzdist;
#ifdef WITH_JMAP
extern struct namespace_t namespace_jmap;
extern struct namespace_t namespace_convert;
#endif
extern struct namespace_t namespace_rss;
extern struct namespace_t namespace_dblookup;
Expand Down
12 changes: 12 additions & 0 deletions imap/jmap_ical.c
Original file line number Diff line number Diff line change
Expand Up @@ -8105,3 +8105,15 @@ HIDDEN void jmapical_remove_peruserprops(json_t *jevent)
}
}
}

HIDDEN json_t *jmapical_vcalendar_to_jsgroup(icalcomponent *ical)
{
if (!ical || icalcomponent_isa(ical) != ICAL_VCALENDAR_COMPONENT)
return NULL;

json_t *jgroup = json_pack("{s:s}", "@type", "Group");
json_object_set_new(jgroup, "entries",
jmapical_tojmap_all(ical, NULL, NULL));

return jgroup;
}
3 changes: 3 additions & 0 deletions imap/jmap_ical.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ extern void jstimezones_free(jstimezones_t **jstzonesptr);
struct buf *icalcomponent_as_jevent_string(icalcomponent *ical);
icalcomponent *jevent_string_as_icalcomponent(const struct buf *buf);

/* for HTTP convert module */
json_t *jmapical_vcalendar_to_jsgroup(icalcomponent *ical);

/* Base type for JSCalendar LocalDateTime and UTCDateTime */

struct jmapical_datetime {
Expand Down
44 changes: 22 additions & 22 deletions imap/promdata.p
Original file line number Diff line number Diff line change
Expand Up @@ -100,46 +100,46 @@ metric gauge cyrus_http_ready_listeners The number of currently ready
metric counter cyrus_http_shutdown_total The number of HTTP process shutdowns
label cyrus_http_shutdown_total status ok error
metric counter cyrus_http_acl_total The total number of HTTP ACLs
label cyrus_http_acl_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi
label cyrus_http_acl_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi convert
metric counter cyrus_http_bind_total The total number of HTTP BINDs
label cyrus_http_bind_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi
label cyrus_http_bind_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi convert
metric counter cyrus_http_connect_total The total number of HTTP CONNECTvs
label cyrus_http_connect_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi
label cyrus_http_connect_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi convert
metric counter cyrus_http_copy_total The total number of HTTP COPYs
label cyrus_http_copy_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi
label cyrus_http_copy_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi convert
metric counter cyrus_http_delete_total The total number of HTTP DELETEs
label cyrus_http_delete_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi
label cyrus_http_delete_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi convert
metric counter cyrus_http_get_total The total number of HTTP GETs
label cyrus_http_get_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi
label cyrus_http_get_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi convert
metric counter cyrus_http_head_total The total number of HTTP HEADs
label cyrus_http_head_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi
label cyrus_http_head_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi convert
metric counter cyrus_http_lock_total The total number of HTTP LOCKs
label cyrus_http_lock_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi
label cyrus_http_lock_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi convert
metric counter cyrus_http_mkcalendar_total The total number of HTTP MKCALENDARs
label cyrus_http_mkcalendar_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi
label cyrus_http_mkcalendar_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi convert
metric counter cyrus_http_mkcol_total The total number of HTTP MKCOLs
label cyrus_http_mkcol_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi
label cyrus_http_mkcol_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi convert
metric counter cyrus_http_move_total The total number of HTTP MOVEs
label cyrus_http_move_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi
label cyrus_http_move_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi convert
metric counter cyrus_http_options_total The total number of HTTP OPTIONSs
label cyrus_http_options_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi
label cyrus_http_options_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi convert
metric counter cyrus_http_patch_total The total number of HTTP PATCHs
label cyrus_http_patch_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi
label cyrus_http_patch_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi convert
metric counter cyrus_http_post_total The total number of HTTP POSTs
label cyrus_http_post_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi
label cyrus_http_post_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi convert
metric counter cyrus_http_propfind_total The total number of HTTP PROPFINDs
label cyrus_http_propfind_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi
label cyrus_http_propfind_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi convert
metric counter cyrus_http_proppatch_total The total number of HTTP PROPPATCHs
label cyrus_http_proppatch_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi
label cyrus_http_proppatch_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi convert
metric counter cyrus_http_put_total The total number of HTTP PUTs
label cyrus_http_put_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi
label cyrus_http_put_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi convert
metric counter cyrus_http_report_total The total number of HTTP REPORTs
label cyrus_http_report_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi
label cyrus_http_report_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi convert
metric counter cyrus_http_search_total The total number of HTTP SEARCH
label cyrus_http_search_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi
label cyrus_http_search_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi convert
metric counter cyrus_http_trace_total The total number of HTTP TRACEs
label cyrus_http_trace_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi
label cyrus_http_trace_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi convert
metric counter cyrus_http_unbind_total The total number of HTTP UNBINDs
label cyrus_http_unbind_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi
label cyrus_http_unbind_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi convert
metric counter cyrus_http_unlock_total The total number of HTTP UNLOCKs
label cyrus_http_unlock_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi
label cyrus_http_unlock_total namespace default admin applepush calendar freebusy addressbook principal notify dblookup ischedule domainkeys jmap prometheus rss tzdist drive cgi convert
Loading

0 comments on commit c68acc5

Please sign in to comment.