Exemplo n.º 1
0
/*
 * Construct an iCalendar property value from XML content.
 */
static icalvalue *xml_element_to_icalvalue(xmlNodePtr xtype,
        icalvalue_kind kind)
{
    icalvalue *value = NULL;
    xmlNodePtr node;
    xmlChar *content = NULL;

    switch (kind) {

    case ICAL_GEO_VALUE: {
        struct icalgeotype geo;

        node = xmlFirstElementChild(xtype);
        if (!node) {
            syslog(LOG_WARNING, "Missing <latitude> XML element");
            break;
        }
        else if (xmlStrcmp(node->name, BAD_CAST "latitude")) {
            syslog(LOG_WARNING,
                   "Expected <latitude> XML element, received %s", node->name);
            break;
        }

        content = xmlNodeGetContent(node);
        geo.lat = atof((const char *) content);

        node = xmlNextElementSibling(node);
        if (!node) {
            syslog(LOG_WARNING, "Missing <longitude> XML element");
            break;
        }
        else if (xmlStrcmp(node->name, BAD_CAST "longitude")) {
            syslog(LOG_WARNING,
                   "Expected <longitude> XML element, received %s", node->name);
            break;
        }

        xmlFree(content);
        content = xmlNodeGetContent(node);
        geo.lon = atof((const char *) content);

        value = icalvalue_new_geo(geo);

        break;
    }

    case ICAL_PERIOD_VALUE: {
        struct icalperiodtype p;

        p.start = p.end = icaltime_null_time();
        p.duration = icaldurationtype_from_int(0);

        node = xmlFirstElementChild(xtype);
        if (!node) {
            syslog(LOG_WARNING, "Missing <start> XML element");
            break;
        }
        else if (xmlStrcmp(node->name, BAD_CAST "start")) {
            syslog(LOG_WARNING,
                   "Expected <start> XML element, received %s", node->name);
            break;
        }

        content = xmlNodeGetContent(node);
        p.start = icaltime_from_string((const char *) content);
        if (icaltime_is_null_time(p.start)) break;

        node = xmlNextElementSibling(node);
        if (!node) {
            syslog(LOG_WARNING, "Missing <end> / <duration> XML element");
            break;
        }
        else if (!xmlStrcmp(node->name, BAD_CAST "end")) {
            xmlFree(content);
            content = xmlNodeGetContent(node);
            p.end = icaltime_from_string((const char *) content);
            if (icaltime_is_null_time(p.end)) break;
        }
        else if (!xmlStrcmp(node->name, BAD_CAST "duration")) {
            xmlFree(content);
            content = xmlNodeGetContent(node);
            p.duration = icaldurationtype_from_string((const char *) content);
            if (icaldurationtype_as_int(p.duration) == 0) break;
        }
        else {
            syslog(LOG_WARNING,
                   "Expected <end> / <duration> XML element, received %s",
                   node->name);
            break;
        }

        value = icalvalue_new_period(p);

        break;
    }

    case ICAL_RECUR_VALUE: {
        struct buf rrule = BUF_INITIALIZER;
        struct hash_table byrules;
        struct icalrecurrencetype rt;
        char *sep = "";

        construct_hash_table(&byrules, 10, 1);

        /* create an iCal RRULE string from xCal <recur> sub-elements */
        for (node = xmlFirstElementChild(xtype); node;
                node = xmlNextElementSibling(node)) {

            content = xmlNodeGetContent(node);
            if (!xmlStrncmp(node->name, BAD_CAST "by", 2)) {
                /* BY* rules can have a list of values -
                   assemble them using a hash table */
                struct buf *vals =
                    hash_lookup((const char *) node->name, &byrules);

                if (vals) {
                    /* append this value to existing list */
                    buf_printf(vals, ",%s", (char *) content);
                }
                else {
                    /* create new list with this valiue */
                    vals = xzmalloc(sizeof(struct buf));
                    buf_setcstr(vals, (char *) content);
                    hash_insert((char *) node->name, vals, &byrules);
                }
            }
            else {
                /* single value rpart */
                buf_printf(&rrule, "%s%s=%s", sep,
                           ucase((char *) node->name), (char *) content);
                sep = ";";
            }

            xmlFree(content);
            content = NULL;
        }

        /* append the BY* rules to RRULE buffer */
        hash_enumerate(&byrules,
                       (void (*)(const char*, void*, void*)) &append_byrule,
                       &rrule);
        free_hash_table(&byrules, NULL);

        /* parse our iCal RRULE string */
        rt = icalrecurrencetype_from_string(buf_cstring(&rrule));
        buf_free(&rrule);

        if (rt.freq != ICAL_NO_RECURRENCE) value = icalvalue_new_recur(rt);

        break;
    }

    case ICAL_REQUESTSTATUS_VALUE: {
        struct icalreqstattype rst = { ICAL_UNKNOWN_STATUS, NULL, NULL };
        short maj, min;

        node = xmlFirstElementChild(xtype);
        if (!node) {
            syslog(LOG_WARNING, "Missing <code> XML element");
            break;
        }
        else if (xmlStrcmp(node->name, BAD_CAST "code")) {
            syslog(LOG_WARNING,
                   "Expected <code> XML element, received %s", node->name);
            break;
        }

        content = xmlNodeGetContent(node);
        if (sscanf((const char *) content, "%hd.%hd", &maj, &min) == 2) {
            rst.code = icalenum_num_to_reqstat(maj, min);
        }
        if (rst.code == ICAL_UNKNOWN_STATUS) {
            syslog(LOG_WARNING, "Unknown request-status code");
            break;
        }

        node = xmlNextElementSibling(node);
        if (!node) {
            syslog(LOG_WARNING, "Missing <description> XML element");
            break;
        }
        else if (xmlStrcmp(node->name, BAD_CAST "description")) {
            syslog(LOG_WARNING,
                   "Expected <description> XML element, received %s",
                   node->name);
            break;
        }

        xmlFree(content);
        content = xmlNodeGetContent(node);
        rst.desc = (const char *) content;

        node = xmlNextElementSibling(node);
        if (node) {
            if (xmlStrcmp(node->name, BAD_CAST "data")) {
                syslog(LOG_WARNING,
                       "Expected <data> XML element, received %s", node->name);
                break;
            }

            xmlFree(content);
            content = xmlNodeGetContent(node);
            rst.debug = (const char *) content;
        }

        value = icalvalue_new_requeststatus(rst);
        break;
    }

    case ICAL_UTCOFFSET_VALUE: {
        int n, utcoffset, hours, minutes, seconds = 0;
        char sign;

        content = xmlNodeGetContent(xtype);
        n = sscanf((const char *) content, "%c%02d:%02d:%02d",
                   &sign, &hours, &minutes, &seconds);

        if (n < 3) {
            syslog(LOG_WARNING, "Unexpected utc-offset format");
            break;
        }

        utcoffset = hours*3600 + minutes*60 + seconds;

        if (sign == '-') utcoffset = -utcoffset;

        value = icalvalue_new_utcoffset(utcoffset);
        break;
    }

    default:
        content = xmlNodeGetContent(xtype);
        value = icalvalue_new_from_string(kind, (const char *) content);
        break;
    }

    if (content) xmlFree(content);

    return value;
}
Exemplo n.º 2
0
/*
 * Construct an iCalendar property value from a JSON object.
 */
static icalvalue *json_object_to_icalvalue(json_t *jvalue,
                                           icalvalue_kind kind)
{
    icalvalue *value = NULL;
    int len, i;

    switch (kind) {
    case ICAL_BOOLEAN_VALUE:
        if (json_is_boolean(jvalue))
            value = icalvalue_new_integer(json_is_true(jvalue));
        else
            syslog(LOG_WARNING, "jCal boolean object expected");
        break;

    case ICAL_FLOAT_VALUE:
        if (json_is_real(jvalue))
            value = icalvalue_new_float((float) json_real_value(jvalue));
        else
            syslog(LOG_WARNING, "jCal double object expected");
        break;

    case ICAL_GEO_VALUE:
        /* MUST be an array of 2 doubles */
        if (json_is_array(jvalue) && (len = json_array_size(jvalue)) != 2) {

            for (i = 0;
                 i < len && json_is_real(json_array_get(jvalue, i));
                 i++);
            if (i == len) {
                struct icalgeotype geo;

                geo.lat =
                    json_real_value(json_array_get(jvalue, 0));
                geo.lon =
                    json_real_value(json_array_get(jvalue, 1));

                value = icalvalue_new_geo(geo);
            }
        }
        if (!value)
            syslog(LOG_WARNING, "jCal array object of 2 doubles expected");
        break;

    case ICAL_INTEGER_VALUE:
        if (json_is_integer(jvalue))
            value = icalvalue_new_integer((int) json_integer_value(jvalue));
        else if (json_is_string(jvalue))
            value = icalvalue_new_integer(atoi(json_string_value(jvalue)));
        else
            syslog(LOG_WARNING, "jCal integer object expected");
        break;

    case ICAL_RECUR_VALUE:
        if (json_is_object(jvalue)) {
            struct buf rrule = BUF_INITIALIZER;
            struct icalrecurrencetype rt;
            const char *key, *sep = "";
            json_t *val;

            /* create an iCal RRULE string from jCal 'recur' object */
            json_object_foreach(jvalue, key, val) {
                char *mykey = xstrdup(key);
                buf_printf(&rrule, "%s%s=", sep, ucase(mykey));
                buf_appendjson(&rrule, val);
                sep = ";";
                free(mykey);
            }

            /* parse our iCal RRULE string */
            rt = icalrecurrencetype_from_string(buf_cstring(&rrule));
            buf_free(&rrule);

            if (rt.freq != ICAL_NO_RECURRENCE) value = icalvalue_new_recur(rt);
        }
        else