summaryrefslogtreecommitdiffstats
path: root/comm/calendar/base/src/CalItipItem.jsm
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--comm/calendar/base/src/CalItipItem.jsm212
1 files changed, 212 insertions, 0 deletions
diff --git a/comm/calendar/base/src/CalItipItem.jsm b/comm/calendar/base/src/CalItipItem.jsm
new file mode 100644
index 0000000000..aecf8671a1
--- /dev/null
+++ b/comm/calendar/base/src/CalItipItem.jsm
@@ -0,0 +1,212 @@
+/* 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/. */
+
+var EXPORTED_SYMBOLS = ["CalItipItem"];
+
+var { cal } = ChromeUtils.import("resource:///modules/calendar/calUtils.jsm");
+
+function CalItipItem() {
+ this.wrappedJSObject = this;
+ this.mCurrentItemIndex = 0;
+}
+CalItipItem.prototype = {
+ QueryInterface: ChromeUtils.generateQI(["calIItipItem"]),
+ classID: Components.ID("{f41392ab-dcad-4bad-818f-b3d1631c4d93}"),
+
+ mIsInitialized: false,
+
+ mSender: null,
+ get sender() {
+ return this.mSender;
+ },
+ set sender(aValue) {
+ this.mSender = aValue;
+ },
+
+ mIsSend: false,
+ get isSend() {
+ return this.mIsSend;
+ },
+ set isSend(aValue) {
+ this.mIsSend = aValue;
+ },
+
+ mReceivedMethod: "REQUEST",
+ get receivedMethod() {
+ return this.mReceivedMethod;
+ },
+ set receivedMethod(aMethod) {
+ this.mReceivedMethod = aMethod.toUpperCase();
+ },
+
+ mResponseMethod: "REPLY",
+ get responseMethod() {
+ if (!this.mIsInitialized) {
+ throw Components.Exception("", Cr.NS_ERROR_NOT_INITIALIZED);
+ }
+ return this.mResponseMethod;
+ },
+ set responseMethod(aMethod) {
+ this.mResponseMethod = aMethod.toUpperCase();
+ },
+
+ mAutoResponse: null,
+ get autoResponse() {
+ return this.mAutoResponse;
+ },
+ set autoResponse(aValue) {
+ this.mAutoResponse = aValue;
+ },
+
+ mTargetCalendar: null,
+ get targetCalendar() {
+ return this.mTargetCalendar;
+ },
+ set targetCalendar(aValue) {
+ this.mTargetCalendar = aValue;
+ },
+
+ mIdentity: null,
+ get identity() {
+ return this.mIdentity;
+ },
+ set identity(aValue) {
+ this.mIdentity = aValue;
+ },
+
+ mLocalStatus: null,
+ get localStatus() {
+ return this.mLocalStatus;
+ },
+ set localStatus(aValue) {
+ this.mLocalStatus = aValue;
+ },
+
+ mItemList: {},
+
+ init(aIcalString) {
+ let parser = Cc["@mozilla.org/calendar/ics-parser;1"].createInstance(Ci.calIIcsParser);
+ parser.parseString(aIcalString);
+
+ // - User specific alarms as well as X-MOZ- properties are irrelevant w.r.t. iTIP messages,
+ // should not be sent out and should not be relevant for incoming messages
+ // - faked master items
+ // so clean them out:
+
+ function cleanItem(item) {
+ // the following changes will bump LAST-MODIFIED/DTSTAMP, we want to preserve the originals:
+ let stamp = item.stampTime;
+ let lastModified = item.lastModifiedTime;
+ item.clearAlarms();
+ item.alarmLastAck = null;
+ item.deleteProperty("RECEIVED-SEQUENCE");
+ item.deleteProperty("RECEIVED-DTSTAMP");
+ for (let [name] of item.properties) {
+ if (name != "X-MOZ-FAKED-MASTER" && name.substr(0, "X-MOZ-".length) == "X-MOZ-") {
+ item.deleteProperty(name);
+ }
+ }
+ // never publish an organizer's RECEIVED params:
+ item.getAttendees().forEach(att => {
+ att.deleteProperty("RECEIVED-SEQUENCE");
+ att.deleteProperty("RECEIVED-DTSTAMP");
+ });
+
+ // according to RfC 6638, the following items must not be exposed in client side
+ // email scheduling messages, so let's remove it if present
+ let removeSchedulingParams = aCalUser => {
+ aCalUser.deleteProperty("SCHEDULE-AGENT");
+ aCalUser.deleteProperty("SCHEDULE-FORCE-SEND");
+ aCalUser.deleteProperty("SCHEDULE-STATUS");
+ };
+ item.getAttendees().forEach(removeSchedulingParams);
+ // we're graceful here as some PUBLISHed events may violate RfC by having no organizer
+ if (item.organizer) {
+ removeSchedulingParams(item.organizer);
+ }
+
+ item.setProperty("DTSTAMP", stamp);
+ item.setProperty("LAST-MODIFIED", lastModified); // need to be last to undirty the item
+ }
+
+ this.mItemList = [];
+ for (let item of cal.iterate.items(parser.getItems())) {
+ cleanItem(item);
+ // only push non-faked master items or
+ // the overridden instances of faked master items
+ // to the list:
+ if (item == item.parentItem) {
+ if (!item.hasProperty("X-MOZ-FAKED-MASTER")) {
+ this.mItemList.push(item);
+ }
+ } else if (item.parentItem.hasProperty("X-MOZ-FAKED-MASTER")) {
+ this.mItemList.push(item);
+ }
+ }
+
+ // We set both methods now for safety's sake. It's the ItipProcessor's
+ // responsibility to properly ascertain what the correct response
+ // method is (using user feedback, prefs, etc.) for the given
+ // receivedMethod. The RFC tells us to treat items without a METHOD
+ // as if they were METHOD:REQUEST.
+ for (let prop of parser.getProperties()) {
+ if (prop.propertyName == "METHOD") {
+ this.mReceivedMethod = prop.value;
+ this.mResponseMethod = prop.value;
+ break;
+ }
+ }
+
+ this.mIsInitialized = true;
+ },
+
+ clone() {
+ let newItem = new CalItipItem();
+ newItem.mItemList = this.mItemList.map(item => item.clone());
+ newItem.mReceivedMethod = this.mReceivedMethod;
+ newItem.mResponseMethod = this.mResponseMethod;
+ newItem.mAutoResponse = this.mAutoResponse;
+ newItem.mTargetCalendar = this.mTargetCalendar;
+ newItem.mIdentity = this.mIdentity;
+ newItem.mLocalStatus = this.mLocalStatus;
+ newItem.mSender = this.mSender;
+ newItem.mIsSend = this.mIsSend;
+ newItem.mIsInitialized = this.mIsInitialized;
+ return newItem;
+ },
+
+ /**
+ * This returns both the array and the number of items. An easy way to
+ * call it is: let itemArray = itipItem.getItemList();
+ */
+ getItemList() {
+ if (!this.mIsInitialized) {
+ throw Components.Exception("", Cr.NS_ERROR_NOT_INITIALIZED);
+ }
+ return this.mItemList;
+ },
+
+ /**
+ * Note that this code forces the user to respond to all items in the same
+ * way, which is a current limitation of the spec.
+ */
+ setAttendeeStatus(aAttendeeId, aStatus) {
+ // Append "mailto:" to the attendee if it is missing it.
+ if (!aAttendeeId.match(/^mailto:/i)) {
+ aAttendeeId = "mailto:" + aAttendeeId;
+ }
+
+ for (let item of this.mItemList) {
+ let attendee = item.getAttendeeById(aAttendeeId);
+ if (attendee) {
+ // Replies should not have the RSVP property.
+ // XXX BUG 351589: workaround for updating an attendee
+ item.removeAttendee(attendee);
+ attendee = attendee.clone();
+ attendee.rsvp = null;
+ item.addAttendee(attendee);
+ }
+ }
+ },
+};