Bug 340949: error handling, refresh, startup opt, search for calendars, alarm defaults, minor cleanup

This commit is contained in:
daniel.boelzle%sun.com 2006-11-22 09:43:14 +00:00
parent 2e43231ce7
commit 1e1cf66de1
10 changed files with 381 additions and 171 deletions

View File

@ -37,9 +37,9 @@
*
* ***** END LICENSE BLOCK ***** */
function createWcapCalendar( calId, session )
function createWcapCalendar( calId, session, /*optional*/calProps )
{
var cal = new calWcapCalendar( calId, session );
var cal = new calWcapCalendar( calId, session, calProps );
switch (CACHE) {
case "memory":
case "storage":
@ -52,10 +52,11 @@ function createWcapCalendar( calId, session )
return cal;
}
function calWcapCalendar( calId, session ) {
function calWcapCalendar( calId, session, /*optional*/calProps ) {
this.wrappedJSObject = this;
this.m_calId = calId;
this.m_session = session;
this.m_calProps = calProps;
this.m_bSuppressAlarms = SUPPRESS_ALARMS;
// init queued calls:
@ -71,6 +72,14 @@ function calWcapCalendar( calId, session ) {
this, this.getItems_queued);
this.syncChangesTo = makeQueuedCall(this.session.asyncQueue,
this, this.syncChangesTo_queued);
if (LOG_LEVEL > 0 && this.m_calProps) {
if (this.m_calId != this.getCalendarProperties(
"X-NSCP-CALPROPS-RELATIVE_CALID", {})[0]) {
this.notifyError("calId mismatch: " + this.m_calId +
" vs. " + ar[0]);
}
}
}
calWcapCalendar.prototype = {
m_ifaces: [ Components.interfaces.calIWcapCalendar,
@ -182,10 +191,14 @@ calWcapCalendar.prototype = {
// calICalendar:
get name() {
return getCalendarManager().getCalendarPref( this, "NAME" );
// xxx todo: mismatch
if (this.session.isLoggedIn)
return this.displayName;
else
return getCalendarManager().getCalendarPref(this, "NAME");
},
set name( name ) {
getCalendarManager().setCalendarPref( this, "NAME", name );
getCalendarManager().setCalendarPref(this, "NAME", name);
},
get type() { return "wcap"; },
@ -216,12 +229,29 @@ calWcapCalendar.prototype = {
}
},
// xxx todo: will potentially vanish from calICalendar:
get uri() { return this.session.uri; },
set uri( thatUri ) {
this.session.uri = thatUri;
resetCalProps:
function()
{
this.m_calProps = null;
},
get uri() {
if (this.m_calId) {
var ret = this.session.uri.clone();
if (LOG_LEVEL == 42) { // xxx todo: interims hack for tbe
ret.path += ("?calid=" + encodeURIComponent(this.m_calId));
}
return ret;
}
else
return this.session.uri;
},
set uri( thatUri ) {
this.session.uri = thatUri;
// uri changes, but calId stays constant:
this.resetCalProps();
},
notifyObservers:
function( func, args ) {
this.session.notifyObservers( func, args );
@ -258,10 +288,14 @@ calWcapCalendar.prototype = {
this.m_bSuppressAlarms = bSuppressAlarms;
},
get canRefresh() { return false; },
refresh: function() {
// no-op
this.log("refresh()");
get canRefresh() { return true; },
refresh:
function() {
// refresh session ticket immedidately, not queued:
this.log("refresh!");
this.session.logout();
// logout sufficient, there is an upcoming getItems() call:
// this.session.login();
},
getCommandUrl:
@ -275,7 +309,11 @@ calWcapCalendar.prototype = {
// calIWcapCalendar:
m_session: null,
get session() { return this.m_session; },
get session() {
if (this.m_session)
return this.m_session;
throw new Components.Exception("Disconnected from session!");
},
// xxx todo: for now to make subscriptions context menu work,
// will vanish when UI has been revised and every subscribed
@ -286,7 +324,7 @@ calWcapCalendar.prototype = {
get calId() {
if (this.m_calId)
return this.m_calId;
this.session.assureLoggedIn();
// this.session.assureLoggedIn();
return this.session.defaultCalId;
},
set calId( id ) {
@ -298,7 +336,7 @@ calWcapCalendar.prototype = {
get ownerId() {
var ar = this.getCalendarProperties("X-NSCP-CALPROPS-PRIMARY-OWNER",{});
if (ar.length < 1 || ar[0].length == 0) {
if (ar.length == 0) {
var calId = this.calId;
this.logError(
"cannot determine primary owner of calendar " + calId );
@ -313,7 +351,7 @@ calWcapCalendar.prototype = {
get description() {
var ar = this.getCalendarProperties("X-NSCP-CALPROPS-DESCRIPTION", {});
if (ar.length < 1 || ar[0].length == 0) {
if (ar.length == 0) {
// fallback to display name:
return this.displayName;
}
@ -322,11 +360,11 @@ calWcapCalendar.prototype = {
get displayName() {
var ar = this.getCalendarProperties("X-NSCP-CALPROPS-NAME", {});
if (ar.length < 1 || ar[0].length == 0) {
if (ar.length == 0) {
// fallback to common name:
ar = this.getCalendarProperties(
"X-S1CS-CALPROPS-COMMON-NAME", {});
if (ar.length < 1) {
if (ar.length == 0) {
return this.calId;
}
}
@ -340,14 +378,8 @@ calWcapCalendar.prototype = {
getCalendarProperties:
function( propName, out_count )
{
var ret = [];
var calProps = this.getCalProps_(false /* !async: waits for response*/);
if (calProps != null) {
var nodeList = calProps.getElementsByTagName(propName);
for ( var i = 0; i < nodeList.length; ++i ) {
ret.push( trimString(nodeList.item(i).textContent) );
}
}
var ret = filterCalProps(
propName, this.getCalProps_(false /* !async: waits for response*/));
out_count.value = ret.length;
return ret;
},
@ -355,7 +387,7 @@ calWcapCalendar.prototype = {
getCalProps_:
function( bAsync, bRefresh )
{
this.session.assureLoggedIn();
// this.session.assureLoggedIn();
try {
if (bRefresh || !this.m_calProps) {
var url = this.getCommandUrl( "get_calprops" );
@ -369,10 +401,10 @@ calWcapCalendar.prototype = {
this_.m_calProps = xml;
}
catch (exc) {
// patch to read-only here, because error notification
// call the readOnly attribute, thus we would run into
// endless recursion here:
this_.m_bReadOnly = true;
// // patch to read-only here, because error notification
// // call the readOnly attribute, thus we would run into
// // endless recursion here:
// this_.m_bReadOnly = true;
// just logging here, because user may have dangling
// users referred in his subscription list:
this_.logError( exc );
@ -387,9 +419,9 @@ calWcapCalendar.prototype = {
}
}
catch (exc) {
// patch to read-only here, because error notification call the
// readOnly attribute, thus we would run into endless recursion here
this.m_bReadOnly = true;
// // patch to read-only here, because error notification call the
// // readOnly attribute, thus we would run into endless recursion here
// this.m_bReadOnly = true;
this.logError( exc );
if (!bAsync)
throw exc;
@ -399,8 +431,9 @@ calWcapCalendar.prototype = {
get defaultTimezone() {
var tzid = this.getCalendarProperties("X-NSCP-CALPROPS-TZID", {});
if (tzid.length < 1 || tzid[0].length == 0) {
this.logError( "cannot get X-NSCP-CALPROPS-TZID!" );
if (tzid.length == 0) {
this.logError("cannot get X-NSCP-CALPROPS-TZID!",
"defaultTimezone");
return "UTC"; // fallback
}
return tzid[0];

View File

@ -437,40 +437,20 @@ calWcapCalendar.prototype.storeItem = function( item, oldItem, receiverFunc )
} // else only dtend is set
}
}
// else {
// var ar = this.session.getUserPreferences(
// "X-NSCP-WCAP-PREF-ceDefaultAlarmStart", {});
// if (ar.length > 0 && ar[0].length > 0) {
// // workarounding cs duration bug, missing "T":
// var dur = ar[0].replace(/(^P)(\d+[HMS]$)/, "$1T$2");
// alarmStart = new CalDuration();
// alarmStart.icalString = dur;
// alarmStart.isNegative = !alarmStart.isNegative;
// this.log( "setting default alarm start: " + alarmStart.icalString );
// }
// }
if (alarmStart) {
// minimal alarm server support: Alarms are currently off by default,
// so let server at least send reminder eMails...
var emails = "";
if (item.hasProperty("alarmEmailAddress"))
emails = encodeURIComponent(item.getProperty("alarmEmailAddress"));
else {
var ar = this.session.getUserPreferences(
"X-NSCP-WCAP-PREF-ceDefaultAlarmEmail", {});
if (ar.length > 0 && ar[0].length > 0) {
for each ( var i in ar ) {
var ars = i.split(/[;,]/);
for each ( var j in ars ) {
j = trimString(j);
if (j.length > 0) {
if (emails.length > 0)
emails += ";";
emails += encodeURIComponent(j);
}
}
}
}
// minimal alarm server support:
// Alarms are currently off by default,
// so let server at least send reminder eMails...
this.session.getDefaultAlarmEmails({}).forEach(
function(email) {
if (emails.length > 0)
emails += ";";
emails += encodeURIComponent(email);
} );
}
url += ("&alarmStart=" + alarmStart.icalString);
url += ("&alarmEmails=" + emails);

View File

@ -254,14 +254,10 @@ var calWcapCalendarModule = { // nsIModule:
return { // nsIFactory:
lockFactory: function( lock ) {},
createInstance: function( outer, iid ) {
if (outer != null)
if (outer)
throw Components.results.NS_ERROR_NO_AGGREGATION;
var session = new calWcapSession();
var cal = createWcapCalendar(
null /* calId: null indicates default calendar */,
session );
session.defaultCalendar = cal;
return cal.QueryInterface( iid );
return session.defaultCalendar.QueryInterface(iid);
}
};
},

View File

@ -205,7 +205,7 @@ function issueSyncRequest( url, receiverFunc, bLogging )
url, "" /* charset */, null /* baseURI */ );
channel.loadFlags |= Components.interfaces.nsIRequest.LOAD_BYPASS_CACHE;
var stream = channel.open();
var stream = channel.open();
var status = channel.status;
if (status == Components.results.NS_OK) {
var charset = channel.contentCharset;

View File

@ -49,8 +49,10 @@ function calWcapSession() {
this.m_calPropsTimer = new Timer();
// init queued calls:
this.getFreeBusyTimes = makeQueuedCall(this.asyncQueue,
this, this.getFreeBusyTimes_queued);
this.getFreeBusyTimes = makeQueuedCall(
this.asyncQueue, this, this.getFreeBusyTimes_queued);
this.searchForCalendars = makeQueuedCall(
this.asyncQueue, this, this.searchForCalendars_queued);
// listen for shutdown, being logged out:
// network:offline-about-to-go-offline will be fired for
@ -305,7 +307,7 @@ calWcapSession.prototype = {
try {
this.m_sessionId = null;
if (timedOutSessionId) {
this.log( "session timeout; prompting to reconnect." );
this.log( "prompting to reconnect.", "session timeout" );
var prompt = getWindowWatcher().getNewPrompter(null);
var bundle = getWcapBundle();
if (!prompt.confirm(
@ -324,7 +326,7 @@ calWcapSession.prototype = {
var sessionUri = this.uri.clone();
sessionUri.userPass = "";
if (sessionUri.scheme.toLowerCase() != "https" &&
if (!sessionUri.schemeIs("https") &&
sessionUri.port == -1 /* no port specified */)
{
// silently probe for https support:
@ -356,11 +358,9 @@ calWcapSession.prototype = {
if (!timedOutSessionId) // timezones don't change that frequently
this.getSupportedTimezones(true /* refresh */);
// invalidate calprops of all calendars:
var cals = this.getSubscribedCalendars({});
for each ( cal in cals ) {
cal.m_calProps = null;
}
// reset calprops of all subscribed calendars before:
this.getSubscribedCalendars({}).forEach(
function(cal) { cal.resetCalProps(); } );
this.m_calPropsTimer.initWithCallback(
{ // nsITimerCallback:
@ -369,10 +369,12 @@ calWcapSession.prototype = {
notify: function(timer_) {
var cals = this.m_session.getSubscribedCalendars({});
var c = (cals.length - this.m_pos);
if (c > 5)
c = 5;
while (c--)
cals[this.m_pos++].getCalProps_(true /*async*/);
if (c > 0) {
if (c > 5)
c = 5;
while (c--)
cals[this.m_pos++].getCalProps_(true /*async*/);
}
if (this.m_pos >= cals.length)
timer_.cancel();
}
@ -392,7 +394,7 @@ calWcapSession.prototype = {
assureSecureLogin:
function( sessionUri )
{
if (sessionUri.scheme.toLowerCase() != "https" &&
if (!sessionUri.schemeIs("https") &&
!confirmInsecureLogin(sessionUri)) {
this.log( "user rejected insecure login on " + sessionUri.spec );
throw new Components.Exception(
@ -725,14 +727,18 @@ calWcapSession.prototype = {
login:
function()
{
this.logout(); // assure being logged out
this.getSessionId();
this.log("login");
this.getSessionId(); // does *not* assure that ticket is valid
},
logout:
function()
{
if (this.m_sessionId != null) {
this.log("logout");
this.m_calPropsTimer.cancel(); // stop any timed calprops getters
this.asyncQueue.reset(); // stop any queued actions
if (this.m_sessionId) {
this.log( "attempting to log out..." );
// although io service's offline flag is already
// set BEFORE notification (about to go offline, nsIOService.cpp).
@ -751,6 +757,7 @@ calWcapSession.prototype = {
}
this.m_sessionId = null;
}
this.m_sessionUri = null;
this.m_userId = null;
this.m_userPrefs = null; // reread prefs
@ -764,38 +771,39 @@ calWcapSession.prototype = {
return wcapErrorToString(rc);
},
m_defaultCalendar: null,
get defaultCalendar() {
return this.getCalendarByCalId(null);
},
set defaultCalendar(cal) {
this.m_defaultCalendar = cal;
if (!this.m_defaultCalendar) {
this.m_defaultCalendar = createWcapCalendar(
null /* calId: null indicates default calendar */, this);
}
return this.m_defaultCalendar;
},
m_defaultCalendar: null,
m_calIdToCalendar: {},
getCalendarByCalId:
function( calId )
getCalendarByCalId_:
function( calId, bCreate )
{
var ret;
// xxx todo: for now the default calendar (calId=null)
// is separated (own instance) from subscribed calendars
if (calId == null /*|| this.userId == calId*/) {
if (this.m_defaultCalendar == null) {
this.m_defaultCalendar = createWcapCalendar(
null/*this.userId*/, this);
}
ret = this.m_defaultCalendar;
var ret = null;
if (!calId || (LOG_LEVEL == 42 && // xxx todo: temp tbe hack
this.defaultCalId == calId)) {
ret = this.defaultCalendar;
}
else {
var key = encodeURIComponent(calId);
ret = this.m_calIdToCalendar[key];
if (!ret) {
if (!ret && bCreate) {
ret = createWcapCalendar(calId, this);
this.m_calIdToCalendar[key] = ret;
}
}
return ret;
},
getCalendarByCalId:
function( calId )
{
return this.getCalendarByCalId_(calId, true/*bCreate*/);
},
getCalendars:
function( out_count, bGetOwnedCals )
@ -830,21 +838,19 @@ calWcapSession.prototype = {
},
createCalendar:
function( calId, name, bAllowDoubleBooking, bSetCalProps, bAddToSubscribed )
function( calId, name )
{
try {
this.assureLoggedIn();
var url = this.getCommandUrl( "createcalendar" );
url += ("&allowdoublebook=" + (bAllowDoubleBooking ? "1" : "0"));
url += ("&set_calprops=" + (bSetCalProps ? "1" : "0"));
url += ("&subscribe=" + (bAddToSubscribed ? "1" : "0"));
// this.assureLoggedIn();
var url = this.getCommandUrl("createcalendar");
url += "&allowdoublebook=1&set_calprops=1&subscribe=1";
url += ("&calid=" + encodeURIComponent(calId));
// xxx todo: name undocumented!
url += ("&name=" + encodeURIComponent(name));
// xxx todo: what about categories param???
this.issueSyncRequest( url + "&fmt-out=text%2Fxml", stringToXml );
this.issueSyncRequest(url + "&fmt-out=text%2Fxml", stringToXml);
this.m_userPrefs = null; // reread prefs
return this.getCalendarByCalId( this.userId + ":" + calId );
return this.getCalendarByCalId(this.userId + ":" + calId);
}
catch (exc) {
this.logError( exc );
@ -853,39 +859,53 @@ calWcapSession.prototype = {
},
deleteCalendar:
function( calId, bRemoveFromSubscribed )
function( cal )
{
try {
this.assureLoggedIn();
var url = this.getCommandUrl( "deletecalendar" );
url += ("&unsubscribe=" + (bRemoveFromSubscribed ? "1" : "0"));
// this.assureLoggedIn();
var calId = cal.calId;
var url = this.getCommandUrl("deletecalendar");
url += ("&calid=" + encodeURIComponent(calId));
this.issueSyncRequest( url + "&fmt-out=text%2Fxml", stringToXml );
url += "&unsubscribe=1&fmt-out=text%2Fxml";
this.issueSyncRequest(url, stringToXml);
this.m_userPrefs = null; // reread prefs
// xxx todo: delete here?
this.m_calIdToCalendar[encodeURIComponent(calId)] = null;
cal.readOnly = true;
}
catch (exc) {
this.logError( exc );
this.logError(exc);
throw exc;
}
},
},
modifyCalendarSubscriptions:
function( calIds, bSubscribe )
function( cals, bSubscribe )
{
try {
this.assureLoggedIn();
// this.assureLoggedIn();
var url = this.getCommandUrl(
bSubscribe ? "subscribe_calendars" : "unsubscribe_calendars" );
var calId = "";
for ( var i = 0; i < calIds.length; ++i ) {
if (i > 0)
for each ( var cal in cals ) {
if (calId.length > 0)
calId += ";";
calId += encodeURIComponent(calIds[i]);
calId += encodeURIComponent(cal.calId);
}
url += ("&calid=" + encodeURIComponent(calId));
this.issueSyncRequest( url + "&fmt-out=text%2Fxml", stringToXml );
url += ("&calid=" + calId);
this.issueSyncRequest(url + "&fmt-out=text%2Fxml", stringToXml);
this.m_userPrefs = null; // reread prefs
for each ( cal in cals ) {
if (bSubscribe) {
this.m_calIdToCalendar[
encodeURIComponent(cal.calId)] = cal;
}
else { // remove from cached instances
// xxx todo: delete here?
this.m_calIdToCalendar[
encodeURIComponent(cal.calId)] = null;
}
}
}
catch (exc) {
this.logError( exc );
@ -894,15 +914,15 @@ calWcapSession.prototype = {
},
subscribeToCalendars:
function( count, calIds )
function( count, cals )
{
this.modifyCalendarSubscriptions( calIds, true );
this.modifyCalendarSubscriptions(cals, true/*bSubscribe*/);
},
unsubscribeFromCalendars:
function( count, calIds )
{
this.modifyCalendarSubscriptions( calIds, false );
this.modifyCalendarSubscriptions(cals, false/*!bSubscribe*/);
},
m_userPrefs: null,
@ -910,8 +930,8 @@ calWcapSession.prototype = {
function( prefName, out_count )
{
try {
if (this.m_userPrefs == null) {
this.assureLoggedIn();
if (!this.m_userPrefs) {
// this.assureLoggedIn();
var url = this.getCommandUrl( "get_userprefs" );
url += ("&userid=" + encodeURIComponent(this.userId));
this.m_userPrefs = this.issueSyncRequest(
@ -920,7 +940,8 @@ calWcapSession.prototype = {
var ret = [];
var nodeList = this.m_userPrefs.getElementsByTagName(prefName);
for ( var i = 0; i < nodeList.length; ++i ) {
ret.push( trimString(nodeList.item(i).textContent) );
var node = nodeList.item(i);
ret.push( trimString(node.textContent) );
}
out_count.value = ret.length;
return ret;
@ -931,6 +952,35 @@ calWcapSession.prototype = {
}
},
get defaultAlarmStart() {
var alarmStart = null;
var ar = this.getUserPreferences(
"X-NSCP-WCAP-PREF-ceDefaultAlarmStart", {});
if (ar.length > 0 && ar[0].length > 0) {
// workarounding cs duration bug, missing "T":
var dur = ar[0].replace(/(^P)(\d+[HMS]$)/, "$1T$2");
alarmStart = new CalDuration();
alarmStart.icalString = dur;
alarmStart.isNegative = !alarmStart.isNegative;
}
return alarmStart;
},
getDefaultAlarmEmails:
function( out_count )
{
var ret = [];
var ar = this.getUserPreferences(
"X-NSCP-WCAP-PREF-ceDefaultAlarmEmail", {});
if (ar.length > 0 && ar[0].length > 0) {
for each ( var i in ar ) {
ret = ret.concat( i.split(/[;,]/).map(trimString) );
}
}
out_count.value = ret.length;
return ret;
},
getFreeBusyTimes_resp:
function( wcapResponse, calId, listener, requestId )
{
@ -940,14 +990,14 @@ calWcapSession.prototype = {
var ret = [];
var nodeList = xml.getElementsByTagName("FB");
for ( var i = 0; i < nodeList.length; ++i ) {
var item = nodeList.item(i);
var str = item.textContent;
var node = nodeList.item(i);
var str = node.textContent;
var slash = str.indexOf( '/' );
var start = getDatetimeFromIcalString(str.substr(0, slash));
var end = getDatetimeFromIcalString(str.substr(slash + 1));
var entry = {
isBusyEntry:
(item.attributes.getNamedItem("FBTYPE").nodeValue
(node.attributes.getNamedItem("FBTYPE").nodeValue
== "BUSY"),
dtRangeStart: start,
dtRangeEnd: end
@ -970,8 +1020,8 @@ calWcapSession.prototype = {
case calIWcapErrors.WCAP_NO_ERRNO: // workaround
case calIWcapErrors.WCAP_ACCESS_DENIED_TO_CALENDAR:
case calIWcapErrors.WCAP_CALENDAR_DOES_NOT_EXIST:
this.log( "getFreeBusyTimes_resp() ignored: " +
errorToString(exc) ); // no error
this.log("ignored error: " + errorToString(exc),
"getFreeBusyTimes_resp()");
break;
default:
this.notifyError( exc );
@ -1001,7 +1051,6 @@ calWcapSession.prototype = {
",\n\trangeEnd=" + zRangeEnd,
"getFreeBusyTimes()" );
this.assureLoggedIn();
var url = this.getCommandUrl( "get_freebusy" );
url += ("&calid=" + encodeURIComponent(calId));
url += ("&busyonly=" + (bBusyOnly ? "1" : "0"));
@ -1022,6 +1071,103 @@ calWcapSession.prototype = {
listener.onGetFreeBusyTimes( exc, requestId, calId, 0, [] );
}
},
searchForCalendars_resp:
function( wcapResponse, listener, requestId )
{
try {
var xml = wcapResponse.data; // first statement, may throw
if (listener) {
var ret = [];
var nodeList = xml.getElementsByTagName("iCal");
for ( var i = 0; i < nodeList.length; ++i ) {
var node = nodeList.item(i);
try {
checkWcapXmlErrno(node);
var ar = filterCalProps(
"X-NSCP-CALPROPS-RELATIVE_CALID");
if (ar.length > 0) {
var calId = ar[0];
// take existing one from subscribed list;
// xxx todo assuming there is an existing instance
// for every subscribed calendar at this point!
var cal = this.getCalendarByCalId_(
calId, false/*bCreate*/);
if (!cal)
cal = createWcapCalendar(calId, this, node);
ret.push(cal);
}
}
catch (exc) {
const calIWcapErrors = Components.interfaces
.calIWcapErrors;
switch (getResultCode(exc)) {
case calIWcapErrors.WCAP_NO_ERRNO: // workaround
case calIWcapErrors.WCAP_ACCESS_DENIED_TO_CALENDAR:
this.log("ignored error: " + errorToString(exc),
"searchForCalendars_resp()");
break;
default:
this.notifyError(exc);
break;
}
}
}
this.log("number of found calendars: " + ret.length);
listener.onSearchForCalendarsResults(
Components.results.NS_OK, requestId, ret.length, ret);
}
if (LOG_LEVEL > 0)
this.log("search done.");
}
catch (exc) {
this.notifyError(exc);
if (listener)
listener.onSearchForCalendarsResults(exc, requestId, 0, []);
}
},
searchForCalendars_queued:
function( searchString, searchOptions, listener, requestId )
{
try {
var url = this.getCommandUrl("search_calprops");
url += ("&search-string=" + encodeURIComponent(searchString));
url += ("&searchOpts=" + (searchOptions & 3).toString(10));
const calIWcapSession = Components.interfaces.calIWcapSession;
if (searchOptions & calIWcapSession.SEARCH_INCLUDE_CALID)
url += "&calid=1";
if (searchOptions & calIWcapSession.SEARCH_INCLUDE_NAME)
url += "&name=1";
if (searchOptions & calIWcapSession.SEARCH_INCLUDE_OWNER)
url += "&primaryOwner=1";
url += "&fmt-out=text%2Fxml";
var this_ = this;
this.issueAsyncRequest(
url,
// string to xml converter func without WCAP errno check:
function(data) {
if (!data || data == "") { // assuming time-out
throw new Components.Exception(
"Login failed. Invalid session ID.",
Components.interfaces.calIWcapErrors
.WCAP_LOGIN_FAILED );
}
return getDomParser().parseFromString(data, "text/xml");
},
// response func:
function(wcapResponse) {
this_.searchForCalendars_resp(
wcapResponse, listener, requestId);
} );
}
catch (exc) {
this.notifyError(exc);
if (listener)
listener.onSearchForCalendarsResults(exc, requestId, 0, []);
}
}
};
var g_confirmedHttpLogins = null;

View File

@ -182,6 +182,19 @@ function forEachIcalComponent( icalRootComp, componentType, func, maxResult )
}
}
function filterCalProps(propName, calProps)
{
var ret = [];
if (calProps) {
var nodeList = calProps.getElementsByTagName(propName);
for ( var i = 0; i < nodeList.length; ++i ) {
var node = nodeList.item(i);
ret.push( trimString(node.textContent) );
}
}
return ret;
}
function trimString( str )
{
return str.replace( /(^\s+|\s+$)/g, "" );
@ -277,6 +290,12 @@ function AsyncQueue()
AsyncQueue.prototype = {
m_queue: null,
reset:
function()
{
this.m_queue = [];
},
m_proxy: null,
get proxy() {
if (!this.m_proxy) {

View File

@ -51,6 +51,7 @@ XPIDLSRCS = calIWcapCalendar.idl \
calIWcapErrors.idl \
calIWcapFreeBusyEntry.idl \
calIWcapFreeBusyListener.idl \
calIWcapSearchListener.idl \
calIWcapSession.idl \
$(NULL)

View File

@ -78,7 +78,7 @@ interface calIWcapCalendar : calICalendar
readonly attribute string displayName;
/**
* Gets or sets this calendar's (calId) default timezone.
* Gets this calendar's (calId) default timezone.
*/
readonly attribute string defaultTimezone;

View File

@ -38,7 +38,6 @@
* ***** END LICENSE BLOCK ***** */
#include "calIWcapFreeBusyEntry.idl"
#include "calIWcapCalendar.idl"
[scriptable, uuid(4498E0D0-04EC-43a3-92E0-560667696CF3)]
interface calIWcapFreeBusyListener : nsISupports

View File

@ -39,6 +39,8 @@
#include "calIWcapCalendar.idl"
#include "calIWcapFreeBusyListener.idl"
#include "calIWcapSearchListener.idl"
#include "calIDuration.idl"
/**
* WCAP session.
@ -65,10 +67,10 @@ interface calIWcapSession : nsISupports
readonly attribute boolean isLoggedIn;
/**
* Explicitly performs a session establishment.
* Explicitly performs a session establishment if the user is not logged
* in already.
* Commonly not needed, because any attempt to get a calendar instance
* will establish a session automatically.
* If the user is already logged in, she will be logged out before.
* UI will prompt for a userId and password.
*/
void login();
@ -89,6 +91,7 @@ interface calIWcapSession : nsISupports
* @exception NS_ERROR_INVALID_ARG
*/
string getWcapErrorString( in unsigned long rc );
/**
* The user's default calendar.
@ -123,6 +126,40 @@ interface calIWcapSession : nsISupports
out unsigned long count,
[array, size_is(count), retval] out calIWcapCalendar subscribedCals );
/**
* Specifies how to match the searchString.
*/
const unsigned long SEARCH_STRING_CONTAINS = 0;
const unsigned long SEARCH_STRING_BEGINS_WITH = 1;
const unsigned long SEARCH_STRING_ENDS_WITH = 2;
const unsigned long SEARCH_STRING_EXACT = 3;
/**
* Specifies what properties to include.
*/
const unsigned long SEARCH_INCLUDE_CALID = 1 << 2;
const unsigned long SEARCH_INCLUDE_NAME = 1 << 3;
const unsigned long SEARCH_INCLUDE_OWNER = 1 << 4;
/* xxx todo searching: separate into own interface? */
/**
* Searches for calendars matching the specified searchString.
* Results are notified to the passed listener instance.
* An error is notified to all registered calIObservers and
* to calIWcapSearchListener::onGetFreeBusyTimes with rc != NS_OK.
* The returned count of calendars (with respect to Sun calendar
* servers) is limited to 200.
*
* @param searchString the search string to match
* @param searchOptions the search options
* @param listener listener receiving results
* @param requestId request id to distinguish asynchronous requests
*/
void searchForCalendars(
in string searchString,
in unsigned long searchOptions,
in calIWcapSearchListener listener,
in unsigned long requestId );
/**
* Creates a new calendar for the session's user.
*
@ -136,51 +173,37 @@ interface calIWcapSession : nsISupports
* - Underscore (_)
* - Period (.)
* @param name calendar's name, e.g. "My Work Cal"
* @param bAllowDoubleBooking whether double booking (events/todos) is
* allowed
* @param bSetCalProps whether properties of the new calendar are set
* @param bAddToSubscribed allows a user to specify if the newly
* created calendar should be added to the
* users subscribed calendar list
* @return created calendar
*/
calIWcapCalendar createCalendar(
in string calId,
in string name,
in boolean bAllowDoubleBooking,
in boolean bSetCalProps,
in boolean bAddToSubscribed );
calIWcapCalendar createCalendar( in string calId, in string name );
/**
* Deletes a calendar.
* Deletes a calendar. Don't do any further calls on the deleted instance.
*
* @param calId full calId (incl. "<user>:")
* @param bRemoveFromSubscribed whether calendar ought to be removed
* from subscription list
* @param cal calendar to be deleted
*/
void deleteCalendar(
in string calId,
in boolean bRemoveFromSubscribed );
void deleteCalendar( in calIWcapCalendar cal );
/**
* Subscribe to calendar(s).
*
* @param count number of calIds
* @param calIds array of calIds (calid or "mailto:rfc822addr")
* @param count length of cals
* @param calendars array of cals
*/
void subscribeToCalendars(
in unsigned long count,
[array, size_is(count)] in string calIds );
[array, size_is(count)] in calIWcapCalendar cals );
/**
* Unsubscribe from calendar(s).
*
* @param count number of calIds
* @param calIds array of calIds (calid or "mailto:rfc822addr")
* @param count length of cals
* @param calendars array of cals
*/
void unsubscribeFromCalendars(
in unsigned long count,
[array, size_is(count)] in string calIds );
[array, size_is(count)] in calIWcapCalendar cals );
/**
* Gets the user's preferences.
@ -193,10 +216,23 @@ interface calIWcapSession : nsISupports
out unsigned long count,
[array, size_is(count), retval] out string properties );
/**
* Gets this user's default alarm start.
*/
readonly attribute calIDuration defaultAlarmStart;
/**
* Gets this user's default alarm eMail addresses.
*/
void getDefaultAlarmEmails(
out unsigned long count,
[array, size_is(count), retval] out string emails );
/* xxx todo freebusy: separate into own interface? */
/**
* Gets free-busy entries for calid.
* Results are notified to passed listener instance.
* Results are notified to the passed listener instance.
* An error is notified to all registered calIObservers and
* to calIWcapFreeBusyListener::onGetFreeBusyTimes with rc != NS_OK.
*