DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (c4a371f2ce99)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

Components.utils.import("resource://calendar/modules/calUtils.jsm");

var EXPORTED_SYMBOLS = [
    "CAL_ITEM_FLAG",
    "getInUtcOrKeepFloating",
    "dateToText",
    "textToDate",
    "calStorageTimezone",
    "getTimezone",
    "newDateTime"
];

// Storage flags. These are used in the Database |flags| column to give
// information about the item's features. For example, if the item has
// attachments, the HAS_ATTACHMENTS flag is added to the flags column.
var CAL_ITEM_FLAG = {
    PRIVATE: 1,
    HAS_ATTENDEES: 2,
    HAS_PROPERTIES: 4,
    EVENT_ALLDAY: 8,
    HAS_RECURRENCE: 16,
    HAS_EXCEPTIONS: 32,
    HAS_ATTACHMENTS: 64,
    HAS_RELATIONS: 128,
    HAS_ALARMS: 256,
    RECURRENCE_ID_ALLDAY: 512
};

// The cache of foreign timezones
var gForeignTimezonesCache = {};

/**
 * Returns the passed date in UTC, unless it is floating. In this case, it is
 * kept floating.
 *
 * @param dt        The calIDateTime to convert.
 * @return          The possibly converted calIDateTime.
 */
function getInUtcOrKeepFloating(dt) {
    let tz = dt.timezone;
    if (tz.isFloating || tz.isUTC) {
        return dt;
    } else {
        return dt.getInTimezone(cal.UTC());
    }
}

/**
 * Transforms a date object to a text which is suitable for the database
 *
 * @param d     The calIDateTime to transform.
 * @return      The string representation of the date object.
 */
function dateToText(d) {
    let datestr;
    let tz = null;

    datestr = (d.timezone.isFloating ? "L" :
                 (d.timezone.isUTC ? "U" : "Z")) +
              (d.isDate ? "D" : "T") + d.nativeTime;
    if (!d.timezone.isFloating && ! d.timezone.isUTC) {
        datestr += ":" + d.timezone.tzid.replace(/%/g, "%%").replace(/:/g, "%:");
    }
    return datestr;
}

/**
 * Transforms the text representation of this date object to a calIDateTime
 * object.
 *
 * @param d     The text to transform.
 * @return      The resulting calIDateTime.
 */
function textToDate(d) {
    let dval;
    let tz = "UTC";

    if (d[0] == 'Z') {
        let strs = d.substr(2).split(":");
        dval = parseInt(strs[0]);
        tz = strs[1].replace(/%:/g, ":").replace(/%%/g, "%");
    } else {
        dval = parseInt(d.substr(2));
    }

    let date;
    if (d[0] == 'U' || d[0] == 'Z') {
        date = newDateTime(dval, tz);
    } else if (d[0] == 'L') {
        // is local time
        date = newDateTime(dval, "floating");
    }

    if (d[1] == 'D')
        date.isDate = true;
    return date;
}

//
// other helpers
//

/**
 * Prototype definition for foreign timezone.
 */
function calStorageTimezone(comp) {
    this.wrappedJSObject = this;
    this.provider = null;
    this.icalComponent = comp;
    this.tzid = comp.getFirstProperty("TZID").value;
    this.displayName = null;
    this.isUTC = false;
    this.isFloating = false;
    this.latitude = null;
    this.longitude = null;
}
calStorageTimezone.prototype = {
    toString: function() {
        return this.icalComponent.toString();
    }
};

/**
 * Gets the timezone for the given definition or identifier
 *
 * @param aTimezone     The timezone data
 * @return              The calITimezone object
 */
function getTimezone(aTimezone) {
    let tz = null;
    if (aTimezone.indexOf("BEGIN:VTIMEZONE") == 0) {
        tz = gForeignTimezonesCache[aTimezone]; // using full definition as key
        if (!tz) {
            try {
                // cannot cope without parent VCALENDAR:
                let comp = cal.getIcsService().parseICS("BEGIN:VCALENDAR\n" + aTimezone + "\nEND:VCALENDAR", null);
                tz = new calStorageTimezone(comp.getFirstSubcomponent("VTIMEZONE"));
                gForeignTimezonesCache[aTimezone] = tz;
            } catch (e) {
                cal.ASSERT(false, e);
            }
        }
    } else {
        tz = cal.getTimezoneService().getTimezone(aTimezone);
    }
    return tz;
}

/**
 * Creates a new calIDateTime from the given native time and optionally
 * the passed timezone. The timezone can either be the TZID of the timezone (in
 * this case the timezone service will be asked for the definition), or a string
 * representation of the timezone component (i.e a VTIMEZONE component).
 *
 * @param aNativeTime       The native time, in microseconds
 * @param aTimezone         The timezone identifier or definition.
 */
function newDateTime(aNativeTime, aTimezone) {
    let t = cal.createDateTime();

    // Bug 751821 - Dates before 1970 were incorrectly stored with an unsigned nativeTime value, we need to
    // convert back to a negative value
    if (aNativeTime > 0x7fffffffffffffff) {
        cal.WARN("[calStorageCalendar] Converting invalid native time value: " + aNativeTime);
        aNativeTime = -0x7fffffffffffffff + (aNativeTime - 0x7fffffffffffffff);
        // Round to nearest second to fix microsecond rounding errors
        aNativeTime = Math.round(aNativeTime / 1000000) * 1000000;
    }

    t.nativeTime = aNativeTime;
    if (aTimezone) {
        let tz = getTimezone(aTimezone);
        if (tz) {
            t = t.getInTimezone(tz);
        } else {
            cal.ASSERT(false, "Timezone not available: " + aTimezone);
        }
    } else {
        t.timezone = cal.floating();
    }
    return t;
}