Bug 340949: major rework of the whole wcap provider with async request framework, subscription support

This commit is contained in:
daniel.boelzle%sun.com 2007-01-25 13:01:56 +00:00
Родитель 56d5474623
Коммит 5f32e44ee9
16 изменённых файлов: 2943 добавлений и 3241 удалений

Просмотреть файл

@ -45,10 +45,6 @@ noHttpsConfirmation.text=Insecure login on %1$S!\nContinue?
noHttpsConfirmation.check.text=Don't ask again.
noHttpsConfirmation.label=Warning!
# args: host
reconnectConfirmation.text=Session on %1$S has timed out. Reconnect?
reconnectConfirmation.label=Session TimeOut
# args: host, prodId, serverVersion, wcapVersion
insufficientWcapVersionConfirmation.text=Server %1$S (%2$S, v%3$S, WCAP v%4$S) doesn't support a sufficient WCAP version! The required version is at least 3.0.0.\nContinue?
insufficientWcapVersionConfirmation.label=Insufficient WCAP version!

Просмотреть файл

@ -54,24 +54,12 @@ EXTRA_SCRIPTS = \
calWcapSession.js \
calWcapCalendarItems.js \
calWcapCalendar.js \
calWcapCachedCalendar.js \
$(NULL)
EXTRA_PP_COMPONENTS = \
EXTRA_COMPONENTS = \
calWcapCalendarModule.js \
$(NULL)
# minimum log level:
ifdef wcap_logging
ifeq (,$(findstring $(wcap_logging),1 2 3 4 5))
DEFINES += -DLOG_LEVEL=2
else
DEFINES += -DLOG_LEVEL=$(wcap_logging)
endif
else # ifdef wcap_logging
DEFINES += -DLOG_LEVEL=0
endif # ifdef wcap_logging
# installing EXTRA_SCRIPTS into js/
# using NSINSTALL to make directory: no mtime to preserve:

Просмотреть файл

@ -37,73 +37,51 @@
*
* ***** END LICENSE BLOCK ***** */
function createWcapCalendar( calId, session, /*optional*/calProps )
function createWcapCalendar(session, /*optional*/calProps)
{
var cal = new calWcapCalendar( calId, session, calProps );
switch (CACHE) {
case "memory":
case "storage":
// wrap it up:
var cal_ = new calWcapCachedCalendar();
cal_.remoteCal = cal;
cal = cal_;
break;
}
var cal = new calWcapCalendar(session, calProps);
// switch (CACHE) {
// case "memory":
// case "storage":
// // wrap it up:
// var cal_ = new calWcapCachedCalendar();
// cal_.remoteCal = cal;
// cal = cal_;
// break;
// }
return cal;
}
function calWcapCalendar( calId, session, /*optional*/calProps ) {
function calWcapCalendar(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:
this.adoptItem = makeQueuedCall(this.session.asyncQueue,
this, this.adoptItem_queued);
this.modifyItem = makeQueuedCall(this.session.asyncQueue,
this, this.modifyItem_queued);
this.deleteItem = makeQueuedCall(this.session.asyncQueue,
this, this.deleteItem_queued);
this.getItem = makeQueuedCall(this.session.asyncQueue,
this, this.getItem_queued);
this.getItems = makeQueuedCall(this.session.asyncQueue,
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]);
}
if (this.m_calProps) {
var ar = this.getCalProps("X-NSCP-CALPROPS-RELATIVE-CALID");
if (ar.length > 0)
this.m_calId = ar[0];
else
this.notifyError("no X-NSCP-CALPROPS-RELATIVE-CALID!");
}
}
calWcapCalendar.prototype = {
m_ifaces: [ Components.interfaces.calIWcapCalendar,
Components.interfaces.calICalendar,
m_ifaces: [ calIWcapCalendar,
calICalendar,
Components.interfaces.calICalendarProvider,
Components.interfaces.nsIInterfaceRequestor,
Components.interfaces.nsIClassInfo,
Components.interfaces.nsISupports ],
// nsISupports:
QueryInterface:
function( iid )
{
for each ( var iface in this.m_ifaces ) {
if (iid.equals( iface ))
return this;
}
throw Components.results.NS_ERROR_NO_INTERFACE;
QueryInterface: function calWcapCalendar_QueryInterface(iid) {
qiface(this.m_ifaces, iid);
return this;
},
// nsIClassInfo:
getInterfaces:
function( count )
{
getInterfaces: function calWcapCalendar_getInterfaces( count ) {
count.value = this.m_ifaces.length;
return this.m_ifaces;
},
@ -116,14 +94,14 @@ calWcapCalendar.prototype = {
get classID() {
return calWcapCalendarModule.WcapCalendarInfo.classID;
},
getHelperForLanguage: function( language ) { return null; },
getHelperForLanguage:
function calWcapCalendar_getHelperForLanguage(language) { return null; },
implementationLanguage:
Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,
flags: 0,
// nsIInterfaceRequestor:
getInterface:
function( iid, instance )
getInterface: function calWcapCalendar_getInterface(iid, instance)
{
if (iid.equals(Components.interfaces.nsIAuthPrompt)) {
// use the window watcher service to get a nsIAuthPrompt impl
@ -137,35 +115,22 @@ calWcapCalendar.prototype = {
return null;
},
toString:
function()
{
toString: function calWcapCalendar_toString() {
var str = this.session.toString();
str += (", calId=" +
(this.session.isLoggedIn ? this.calId : this.m_calId));
if (this.m_calId)
str += (", calId=" + this.calId);
else
str += ", default calendar";
return str;
},
log:
function( msg, context )
{
return logMessage( context ? context : this.toString(), msg );
},
logError:
function( err, context )
{
var msg = errorToString(err);
Components.utils.reportError( this.log("error: " + msg, context) );
return msg;
},
notifyError:
function( err )
notifyError: function calWcapCalendar_notifyError(err)
{
debugger;
var msg = this.logError(err);
var msg = logError(err, this);
this.notifyObservers(
"onError",
err instanceof Components.interfaces.nsIException
? [err.result, err.message] : [-1, msg] );
? [err.result, err.message] : [isNaN(err) ? -1 : err, msg] );
},
// calICalendarProvider:
@ -173,19 +138,13 @@ calWcapCalendar.prototype = {
return null;
},
// displayName attribute already part of calIWcapCalendar
createCalendar:
function( name, url, listener )
{
createCalendar: function calWcapCalendar_createCalendar(name, url, listener) {
throw NS_ERROR_NOT_IMPLEMENTED;
},
deleteCalendar:
function( calendar, listener )
{
deleteCalendar: function calWcapCalendar_deleteCalendar(calendar, listener) {
throw NS_ERROR_NOT_IMPLEMENTED;
},
getCalendar:
function( url )
{
getCalendar: function calWcapCalendar_getCalendar( url ) {
throw NS_ERROR_NOT_IMPLEMENTED;
},
@ -213,23 +172,16 @@ calWcapCalendar.prototype = {
// early, so don't log in here if not logged in already...
!this.session.isLoggedIn ||
// limit to write permission on components:
!this.checkAccess(
Components.interfaces.calIWcapCalendar.AC_COMP_WRITE));
!this.checkAccess(calIWcapCalendar.AC_COMP_WRITE));
},
set readOnly( bReadOnly ) { this.m_bReadOnly = bReadOnly; },
resetCalProps:
function()
{
this.m_calProps = null;
set readOnly(bReadOnly) {
this.m_bReadOnly = bReadOnly;
},
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));
}
ret.path += ("?calid=" + encodeURIComponent(this.m_calId));
return ret;
}
else
@ -237,26 +189,25 @@ calWcapCalendar.prototype = {
},
set uri( thatUri ) {
this.session.uri = thatUri;
// uri changes, but calId stays constant:
this.resetCalProps();
},
notifyObservers:
function( func, args ) {
this.session.notifyObservers( func, args );
notifyObservers: function calWcapCalendar_notifyObservers(func, args) {
this.session.notifyObservers(func, args);
},
addObserver:
function( observer ) {
this.session.addObserver( observer );
addObserver: function calWcapCalendar_addObserver(observer) {
this.session.addObserver(observer);
},
removeObserver:
function( observer ) {
this.session.removeObserver( observer );
removeObserver: function calWcapCalendar_removeObserver(observer) {
this.session.removeObserver(observer);
},
// xxx todo: batch currently not used
startBatch: function() { this.notifyObservers( "onStartBatch", [] ); },
endBatch: function() { this.notifyObservers( "onEndBatch", [] ); },
startBatch: function calWcapCalendar_startBatch() {
this.notifyObservers("onStartBatch", []);
},
endBatch: function calWcapCalendar_endBatch() {
this.notifyObservers("onEndBatch", []);
},
// xxx todo: rework like in
// https://bugzilla.mozilla.org/show_bug.cgi?id=257428
@ -273,63 +224,58 @@ calWcapCalendar.prototype = {
// xxx todo: assume alarms if not logged in already
(this.session.isLoggedIn && !this.isOwnedCalendar));
},
set suppressAlarms( bSuppressAlarms ) {
set suppressAlarms(bSuppressAlarms) {
this.m_bSuppressAlarms = bSuppressAlarms;
},
get canRefresh() { return true; },
refresh:
function() {
// xxx todo: somehow misusing reload remote calendars for
// session renewal...
// refresh session ticket immedidately, not queued:
this.log("refresh!");
this.session.refresh();
get canRefresh() { return false; },
refresh: function calWcapCalendar_refresh() {
log("refresh.", this);
},
getCommandUrl:
function( wcapCommand )
issueNetworkRequest: function calWcapCalendar_issueNetworkRequest(
request, respFunc, dataConvFunc, wcapCommand, params, accessRights)
{
var url = this.session.getCommandUrl(wcapCommand);
var calId = this.calId;
if (calId)
url += ("&calid=" + encodeURIComponent(calId));
return url;
var this_ = this;
// - bootstrap problem: no cal_props, no access check, no default calId
// - assure being logged in, thus the default cal_props are available
// - every subscribed calendar will come along with cal_props
return this.session.getSessionId(
request,
function getSessionId_resp(err, sessionId) {
try {
if (err)
throw err;
this_.assureAccess(accessRights);
params += ("&calid=" + encodeURIComponent(this_.calId));
this_.session.issueNetworkRequest(
request, respFunc, dataConvFunc, wcapCommand, params);
}
catch (exc) {
respFunc(exc);
}
});
},
// calIWcapCalendar:
m_session: null,
get session() {
if (this.m_session)
return this.m_session;
throw new Components.Exception("Disconnected from session!");
return this.m_session;
},
// xxx todo: for now to make subscriptions context menu work,
// will vanish when UI has been revised and every subscribed
// calendar has its own calICalendar object...
// poking calId, so default calendar will then behave
// like a subscribed one...
m_calId: null,
get calId() {
if (this.m_calId)
return this.m_calId;
return this.session.defaultCalId;
},
set calId( id ) {
this.log( "setting calId to " + id );
this.m_calId = id;
// refresh calprops:
this.getCalProps_( true /*async*/, true /*refresh*/ );
},
get ownerId() {
var ar = this.getCalendarProperties("X-NSCP-CALPROPS-PRIMARY-OWNER",{});
var ar = this.getCalProps("X-NSCP-CALPROPS-PRIMARY-OWNER");
if (ar.length == 0) {
var calId = this.calId;
this.logError(
"cannot determine primary owner of calendar " + calId );
logError("cannot determine primary owner of calendar " + calId, this);
// fallback to calId prefix:
var nColon = calId.indexOf(":");
if (nColon >= 0)
@ -340,7 +286,7 @@ calWcapCalendar.prototype = {
},
get description() {
var ar = this.getCalendarProperties("X-NSCP-CALPROPS-DESCRIPTION", {});
var ar = this.getCalProps("X-NSCP-CALPROPS-DESCRIPTION");
if (ar.length == 0) {
// fallback to display name:
return this.displayName;
@ -349,11 +295,10 @@ calWcapCalendar.prototype = {
},
get displayName() {
var ar = this.getCalendarProperties("X-NSCP-CALPROPS-NAME", {});
var ar = this.getCalProps("X-NSCP-CALPROPS-NAME");
if (ar.length == 0) {
// fallback to common name:
ar = this.getCalendarProperties(
"X-S1CS-CALPROPS-COMMON-NAME", {});
ar = this.getCalProps("X-S1CS-CALPROPS-COMMON-NAME");
if (ar.length == 0) {
return this.calId;
}
@ -362,69 +307,41 @@ calWcapCalendar.prototype = {
},
get isOwnedCalendar() {
if (this.isDefaultCalendar)
return true; // default calendar is owned
return (this.ownerId == this.session.userId);
},
get isDefaultCalendar() {
return !this.m_calId;
},
getCalendarProperties:
function( propName, out_count )
{
var ret = filterCalProps(
propName, this.getCalProps_(false /* !async: waits for response*/));
function(propName, out_count) {
var ret = this.getCalProps(propName);
out_count.value = ret.length;
return ret;
},
m_calProps: null,
getCalProps_:
function( bAsync, bRefresh )
{
// this.session.assureLoggedIn();
if (bRefresh || !this.m_calProps) {
this.m_calProps = null;
var url = this.getCommandUrl( "get_calprops" );
url += "&fmt-out=text%2Fxml";
var this_ = this;
function resp( wcapResponse ) {
try {
// first statement, may throw:
var xml = wcapResponse.data;
if (this_.m_calProps == null)
this_.m_calProps = xml;
}
catch (exc) {
// just logging here, because user may have dangling
// users referred in his subscription list:
this_.logError(exc);
if (!bAsync && testResultCode(
exc, Components.interfaces.
calIWcapErrors.WCAP_ACCESS_DENIED_TO_CALENDAR)) {
// the user obviously has no property access,
// forward in case of synchronous calls.
// async will be swallowed though.
throw exc;
}
}
}
if (bAsync)
this.session.issueAsyncRequest( url, stringToXml, resp );
else
this.session.issueSyncRequest( url, stringToXml, resp );
getCalProps: function calWcapCalendar_getCalProps(propName) {
if (!this.m_calProps) {
log("soft error: no calprops, most possibly not logged in.", this);
// throw new Components.Exception("No calprops available!",
// Components.results.NS_ERROR_NOT_AVAILABLE);
}
return this.m_calProps;
return filterXmlNodes(propName, this.m_calProps);
},
get defaultTimezone() {
var tzid = this.getCalendarProperties("X-NSCP-CALPROPS-TZID", {});
var tzid = this.getCalProps("X-NSCP-CALPROPS-TZID");
if (tzid.length == 0) {
this.logError("cannot get X-NSCP-CALPROPS-TZID!",
"defaultTimezone");
logError("defaultTimezone: cannot get X-NSCP-CALPROPS-TZID!", this);
return "UTC"; // fallback
}
return tzid[0];
},
getAlignedTimezone:
function( tzid )
{
getAlignedTimezone: function calWcapCalendar_getAlignedTimezone(tzid) {
// check whether it is one of cs:
if (tzid.indexOf("/mozilla.org/") == 0) {
// cut mozilla prefix: assuming that the latter string portion
@ -438,55 +355,51 @@ calWcapCalendar.prototype = {
// user's default if not supported directly
var ret = this.defaultTimezone;
// use calendar's default:
this.log(tzid + " not supported, falling back to default: " + ret);
log(tzid + " not supported, falling back to default: " + ret, this);
return ret;
}
else // is ok (supported):
return tzid;
},
checkAccess:
function( accessControlBits )
checkAccess: function calWcapCalendar_checkAccess(accessControlBits)
{
// xxx todo: take real acl into account
// for now, assuming that owners have been granted full access,
// and all others can read, but not add/modify/delete.
var granted = Components.interfaces.calIWcapCalendar.AC_FULL;
var granted = calIWcapCalendar.AC_FULL;
if (!this.isOwnedCalendar) {
// burn out write access:
granted &= ~(Components.interfaces.calIWcapCalendar.AC_COMP_WRITE |
Components.interfaces.calIWcapCalendar.AC_PROP_WRITE);
granted &= ~(calIWcapCalendar.AC_COMP_WRITE |
calIWcapCalendar.AC_PROP_WRITE);
}
// check whether every bit fits:
return ((accessControlBits & granted) == accessControlBits);
},
assureAccess:
function( accessControlBits )
assureAccess: function calWcapCalendar_assureAccess(accessControlBits)
{
if (!this.checkAccess(accessControlBits)) {
throw new Components.Exception("Access denied!",
Components.interfaces.calIWcapErrors
.WCAP_ACCESS_DENIED_TO_CALENDAR);
calIWcapErrors.WCAP_ACCESS_DENIED_TO_CALENDAR);
// xxx todo: throwing different error here, no
// calIErrors.CAL_IS_READONLY anymore
}
},
defineAccessControl:
function( userId, accessControlBits )
defineAccessControl: function calWcapCalendar_defineAccessControl(
userId, accessControlBits)
{
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
},
resetAccessControl:
function( userId )
resetAccessControl: function calWcapCalendar_resetAccessControl(userId)
{
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
},
getAccessControlDefinitions:
function( out_count, out_users, out_accessControlBits )
getAccessControlDefinitions: function calWcapCalendar_getAccessControlDefinitions(
out_count, out_users, out_accessControlBits)
{
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -40,7 +40,7 @@
var g_ioService = null;
function getIoService()
{
if (g_ioService == null) {
if (!g_ioService) {
g_ioService = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
}
@ -51,12 +51,20 @@ function getIoService()
// init code for globals, prefs:
//
// constants:
const nsIException = Components.interfaces.nsIException;
const calIWcapSession = Components.interfaces.calIWcapSession;
const calIWcapCalendar = Components.interfaces.calIWcapCalendar;
const calIWcapErrors = Components.interfaces.calIWcapErrors;
const calICalendar = Components.interfaces.calICalendar;
const calIOperationListener = Components.interfaces.calIOperationListener;
// ctors:
var CalEvent;
var CalTodo;
var CalDateTime;
var CalDuration;
var XmlHttpRequest;
var CalPeriod;
var Timer;
// some string resources:
@ -71,30 +79,48 @@ var CACHE = "off";
// denotes where to host local storage calendar(s)
var CACHE_DIR = null;
// caching the last data retrievals:
var CACHE_LAST_RESULTS = 4;
// timer secs for invalidation:
var CACHE_LAST_RESULTS_INVALIDATE = 120;
// logging:
#expand var LOG_LEVEL = __LOG_LEVEL__;
var LOG_TIMEZONE = null;
var LOG_FILE_STREAM = null;
var LOG_LEVEL = 0;
// whether alarms are by default turned on/off:
var SUPPRESS_ALARMS = true;
function initWcapProvider()
{
try {
// xxx todo: hack
// the master password prompt is currently not guarded against
// multiple prompt; this initializes/raises the pw db at early stage.
var tokenDB = Components.classes["@mozilla.org/security/pk11tokendb;1"]
.getService(Components.interfaces.nsIPK11TokenDB);
var token = tokenDB.getInternalKeyToken();
if (token.needsLogin && !token.needsUserInit)
token.login(false);
}
catch (exc) {
}
try {
// ctors:
CalEvent = new Components.Constructor(
"@mozilla.org/calendar/event;1", "calIEvent" );
CalTodo = new Components.Constructor(
"@mozilla.org/calendar/todo;1", "calITodo" );
CalDateTime = new Components.Constructor(
"@mozilla.org/calendar/datetime;1", "calIDateTime" );
CalDuration = new Components.Constructor(
"@mozilla.org/calendar/duration;1", "calIDuration" );
XmlHttpRequest = new Components.Constructor(
"@mozilla.org/xmlextras/xmlhttprequest;1", "nsIXMLHttpRequest" );
Timer = new Components.Constructor(
"@mozilla.org/timer;1", "nsITimer" );
CalEvent = new Components.Constructor("@mozilla.org/calendar/event;1",
"calIEvent");
CalTodo = new Components.Constructor("@mozilla.org/calendar/todo;1",
"calITodo");
CalDateTime = new Components.Constructor("@mozilla.org/calendar/datetime;1",
"calIDateTime");
CalDuration = new Components.Constructor("@mozilla.org/calendar/duration;1",
"calIDuration");
CalPeriod = new Components.Constructor("@mozilla.org/calendar/period;1",
"calIPeriod");
Timer = new Components.Constructor("@mozilla.org/timer;1",
"nsITimer");
initLogging();
// some string resources:
g_privateItemTitle = getWcapBundle().GetStringFromName(
@ -105,50 +131,13 @@ function initWcapProvider()
"busyItem.title.text");
g_busyPhantomItemUuidPrefix = ("PHANTOM_uuid" + getTime().icalString);
LOG_TIMEZONE = getPref("calendar.timezone.local", null);
var logLevel = getPref("calendar.wcap.log_level", null);
if (logLevel == null) { // log_level pref undefined:
if (getPref("calendar.debug.log", false))
logLevel = 1; // at least basic logging when calendar.debug.log
}
if (logLevel > LOG_LEVEL) {
LOG_LEVEL = logLevel;
}
if (LOG_LEVEL > 0) {
var logFileName = getPref("calendar.wcap.log_file", null);
if (logFileName != null) {
// set up file:
var logFile =
Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
logFile.initWithPath( logFileName );
// create output stream:
var logFileStream = Components.classes[
"@mozilla.org/network/file-output-stream;1"]
.createInstance(Components.interfaces.nsIFileOutputStream);
logFileStream.init(
logFile,
0x02 /* PR_WRONLY */ |
0x08 /* PR_CREATE_FILE */ |
0x10 /* PR_APPEND */,
0700 /* read, write, execute/search by owner */,
0 /* unused */ );
LOG_FILE_STREAM = logFileStream;
}
logMessage( "init sequence",
"################################# NEW LOG " +
"#################################" );
}
SUPPRESS_ALARMS = getPref("calendar.wcap.suppress_alarms", true);
logMessage("calendar.wcap.suppress_alarms",
SUPPRESS_ALARMS.toString());
CACHE_LAST_RESULTS = getPref("calendar.wcap.cache_last_results", 4);
CACHE_LAST_RESULTS_INVALIDATE = getPref("calendar.wcap.cache_last_results_invalidate", 120);
// init cache dir directory:
CACHE = getPref("calendar.wcap.cache", "off");
logMessage( "calendar.wcap.cache", CACHE );
if (CACHE == "storage") {
var cacheDir = null;
var sCacheDir = getPref("calendar.wcap.cache_dir", null);
@ -158,15 +147,13 @@ function initWcapProvider()
cacheDir.initWithPath( sCacheDir );
}
else { // not found: default to wcap/ directory in profile
var dirService = Components.classes[
"@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties);
cacheDir = dirService.get(
"ProfD", Components.interfaces.nsILocalFile );
var dirService = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties);
cacheDir = dirService.get("ProfD", Components.interfaces.nsILocalFile);
cacheDir.append( "wcap" );
}
CACHE_DIR = cacheDir;
logMessage( "calendar.wcap.cache_dir", CACHE_DIR.path );
log(CACHE_DIR.path, "cache dir");
if (!CACHE_DIR.exists()) {
CACHE_DIR.create(
Components.interfaces.nsIFile.DIRECTORY_TYPE,
@ -175,10 +162,21 @@ function initWcapProvider()
}
}
catch (exc) {
logMessage( "error in init sequence", exc );
logError(exc, "error in init sequence");
}
}
var calWcapCalendarFactory = { // nsIFactory:
lockFactory: function calWcapCalendarFactory_lockFactory(lock) {},
createInstance: function calWcapCalendarFactory_createInstance(outer, iid) {
if (outer)
throw Components.results.NS_ERROR_NO_AGGREGATION;
var session = new calWcapSession();
return session.defaultCalendar.QueryInterface(iid);
}
};
var calWcapCalendarModule = { // nsIModule:
WcapCalendarInfo: {
@ -193,80 +191,61 @@ var calWcapCalendarModule = { // nsIModule:
classID: Components.ID("{CBF803FD-4469-4999-AE39-367AF1C7B077}")
},
registerSelf:
function( compMgr, fileSpec, location, type )
registerSelf: function calWcapCalendarModule_registerSelf(compMgr, fileSpec, location, type)
{
compMgr = compMgr.QueryInterface(
Components.interfaces.nsIComponentRegistrar );
compMgr.registerFactoryLocation(
this.WcapCalendarInfo.classID,
this.WcapCalendarInfo.classDescription,
this.WcapCalendarInfo.contractID,
fileSpec, location, type );
compMgr.registerFactoryLocation(
this.WcapSessionInfo.classID,
this.WcapSessionInfo.classDescription,
this.WcapSessionInfo.contractID,
fileSpec, location, type );
compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
compMgr.registerFactoryLocation(this.WcapCalendarInfo.classID,
this.WcapCalendarInfo.classDescription,
this.WcapCalendarInfo.contractID,
fileSpec, location, type);
compMgr.registerFactoryLocation(this.WcapSessionInfo.classID,
this.WcapSessionInfo.classDescription,
this.WcapSessionInfo.contractID,
fileSpec, location, type);
},
unregisterSelf:
function( compMgr, fileSpec, location ) {
compMgr = compMgr.QueryInterface(
Components.interfaces.nsIComponentRegistrar );
compMgr.unregisterFactoryLocation(
this.WcapCalendarInfo.classID, fileSpec );
compMgr.unregisterFactoryLocation(
this.WcapSessionInfo.classID, fileSpec );
unregisterSelf: function calWcapCalendarModule_unregisterSelf(compMgr, fileSpec, location)
{
compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
compMgr.unregisterFactoryLocation(this.WcapCalendarInfo.classID, fileSpec);
compMgr.unregisterFactoryLocation(this.WcapSessionInfo.classID, fileSpec);
},
m_scriptsLoaded: false,
getClassObject:
function( compMgr, cid, iid )
getClassObject: function calWcapCalendarModule_getClassObject(compMgr, cid, iid)
{
if (!this.m_scriptsLoaded) {
// loading extra scripts from ../js:
const scripts = [ "calWcapUtils.js", "calWcapErrors.js",
"calWcapRequest.js", "calWcapSession.js",
"calWcapCalendar.js", "calWcapCalendarItems.js",
"calWcapCachedCalendar.js" ];
"calWcapCalendar.js", "calWcapCalendarItems.js" ];
var scriptLoader =
Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
.createInstance(Components.interfaces.mozIJSSubScriptLoader);
.createInstance(Components.interfaces.mozIJSSubScriptLoader);
var ioService = getIoService();
var baseDir = __LOCATION__.parent.parent;
baseDir.append("js");
for each ( var script in scripts ) {
for each (var script in scripts) {
var scriptFile = baseDir.clone();
scriptFile.append(script);
scriptLoader.loadSubScript(
ioService.newFileURI(scriptFile).spec, null );
scriptLoader.loadSubScript(ioService.newFileURI(scriptFile).spec, null);
}
initWcapProvider();
this.m_scriptsLoaded = true;
}
if (!iid.equals( Components.interfaces.nsIFactory ))
if (!iid.equals(Components.interfaces.nsIFactory))
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
if (!cid.equals( calWcapCalendar.prototype.classID ))
if (!cid.equals(calWcapCalendar.prototype.classID))
throw Components.results.NS_ERROR_NO_INTERFACE;
return { // nsIFactory:
lockFactory: function( lock ) {},
createInstance: function( outer, iid ) {
if (outer)
throw Components.results.NS_ERROR_NO_AGGREGATION;
var session = new calWcapSession();
return session.defaultCalendar.QueryInterface(iid);
}
};
return calWcapCalendarFactory;
},
canUnload: function( compMgr ) { return true; }
canUnload: function calWcapCalendarModule_canUnload(compMgr) { return true; }
};
/** module export */
function NSGetModule( compMgr, fileSpec ) {
function NSGetModule(compMgr, fileSpec) {
return calWcapCalendarModule;
}

Просмотреть файл

@ -51,7 +51,7 @@ function generateNetFailure(code) {
return generateFailure(NS_ERROR_MODULE_NETWORK, code);
}
function getErrorModule( rc ) {
function getErrorModule(rc) {
return (((rc >>> 16) & 0x7fff) - NS_ERROR_MODULE_BASE_OFFSET);
}
@ -138,99 +138,99 @@ function netErrorToString( rc )
const g_wcapErrorCodes = [
/* -1 */ Components.results.NS_OK, "Logout successful.",
/* 0 */ Components.results.NS_OK, "Command successful.",
/* 1 */ Components.interfaces.calIWcapErrors.WCAP_LOGIN_FAILED, "Login failed. Invalid session ID.",
/* 2 */ Components.interfaces.calIWcapErrors.WCAP_LOGIN_OK_DEFAULT_CALENDAR_NOT_FOUND, "login.wcap was successful, but the default calendar for this user was not found. A new default calendar set to the userid was created.",
/* 1 */ calIWcapErrors.WCAP_LOGIN_FAILED, "Login failed. Invalid session ID.",
/* 2 */ calIWcapErrors.WCAP_LOGIN_OK_DEFAULT_CALENDAR_NOT_FOUND, "login.wcap was successful, but the default calendar for this user was not found. A new default calendar set to the userid was created.",
/* 3 */ Components.results.NS_ERROR_INVALID_ARG, "No WCAP error code.",
/* 4 */ Components.results.NS_ERROR_INVALID_ARG, "No WCAP error code.",
/* 5 */ Components.results.NS_ERROR_INVALID_ARG, "No WCAP error code.",
/* 6 */ Components.interfaces.calIWcapErrors.WCAP_DELETE_EVENTS_BY_ID_FAILED, "WCAP_DELETE_EVENTS_BY_ID_FAILED",
/* 6 */ calIWcapErrors.WCAP_DELETE_EVENTS_BY_ID_FAILED, "WCAP_DELETE_EVENTS_BY_ID_FAILED",
/* 7 */ Components.results.NS_ERROR_INVALID_ARG, "No WCAP error code.",
/* 8 */ Components.interfaces.calIWcapErrors.WCAP_SETCALPROPS_FAILED, "WCAP_SETCALPROPS_FAILED",
/* 9 */ Components.interfaces.calIWcapErrors.WCAP_FETCH_EVENTS_BY_ID_FAILED, "WCAP_FETCH_EVENTS_BY_ID_FAILED",
/* 10 */ Components.interfaces.calIWcapErrors.WCAP_CREATECALENDAR_FAILED, "WCAP_CREATECALENDAR_FAILED",
/* 11 */ Components.interfaces.calIWcapErrors.WCAP_DELETECALENDAR_FAILED, "WCAP_DELETECALENDAR_FAILED",
/* 12 */ Components.interfaces.calIWcapErrors.WCAP_ADDLINK_FAILED, "WCAP_ADDLINK_FAILED",
/* 13 */ Components.interfaces.calIWcapErrors.WCAP_FETCHBYDATERANGE_FAILED, "WCAP_FETCHBYDATERANGE_FAILED",
/* 14 */ Components.interfaces.calIWcapErrors.WCAP_STOREEVENTS_FAILED, "WCAP_STOREEVENTS_FAILED",
/* 15 */ Components.interfaces.calIWcapErrors.WCAP_STORETODOS_FAILED, "WCAP_STORETODOS_FAILED",
/* 16 */ Components.interfaces.calIWcapErrors.WCAP_DELETE_TODOS_BY_ID_FAILED, "WCAP_DELETE_TODOS_BY_ID_FAILED",
/* 17 */ Components.interfaces.calIWcapErrors.WCAP_FETCH_TODOS_BY_ID_FAILED, "WCAP_FETCH_TODOS_BY_ID_FAILED",
/* 18 */ Components.interfaces.calIWcapErrors.WCAP_FETCHCOMPONENTS_FAILED_BAD_TZID, "Command failed to find correct tzid. Applies to fetchcomponents_by_range.wcap, fetchevents_by_id.wcap, fetchtodos_by_id.wcap.",
/* 19 */ Components.interfaces.calIWcapErrors.WCAP_SEARCH_CALPROPS_FAILED, "WCAP_SEARCH_CALPROPS_FAILED",
/* 20 */ Components.interfaces.calIWcapErrors.WCAP_GET_CALPROPS_FAILED, "WCAP_GET_CALPROPS_FAILED",
/* 21 */ Components.interfaces.calIWcapErrors.WCAP_DELETECOMPONENTS_BY_RANGE_FAILED, "WCAP_DELETECOMPONENTS_BY_RANGE_FAILED",
/* 22 */ Components.interfaces.calIWcapErrors.WCAP_DELETEEVENTS_BY_RANGE_FAILED, "WCAP_DELETEEVENTS_BY_RANGE_FAILED",
/* 23 */ Components.interfaces.calIWcapErrors.WCAP_DELETETODOS_BY_RANGE_FAILED, "WCAP_DELETETODOS_BY_RANGE_FAILED",
/* 24 */ Components.interfaces.calIWcapErrors.WCAP_GET_ALL_TIMEZONES_FAILED, "WCAP_GET_ALL_TIMEZONES_FAILED",
/* 25 */ Components.interfaces.calIWcapErrors.WCAP_CREATECALENDAR_ALREADY_EXISTS_FAILED, "The command createcalendar.wcap failed. A calendar with that name already exists in the database.",
/* 26 */ Components.interfaces.calIWcapErrors.WCAP_SET_USERPREFS_FAILED, "WCAP_SET_USERPREFS_FAILED",
/* 27 */ Components.interfaces.calIWcapErrors.WCAP_CHANGE_PASSWORD_FAILED, "WCAP_CHANGE_PASSWORD_FAILED",
/* 28 */ Components.interfaces.calIWcapErrors.WCAP_ACCESS_DENIED_TO_CALENDAR, "Command failed. The user is denied access to a calendar.",
/* 29 */ Components.interfaces.calIWcapErrors.WCAP_CALENDAR_DOES_NOT_EXIST, "Command failed. The requested calendar does not exist in the database.",
/* 30 */ Components.interfaces.calIWcapErrors.WCAP_ILLEGAL_CALID_NAME, "createcalendar.wcap failed. Invalid calid passed in.",
/* 31 */ Components.interfaces.calIWcapErrors.WCAP_CANNOT_MODIFY_LINKED_EVENTS, "storeevents.wcap failed. The event to modify was a linked event.",
/* 32 */ Components.interfaces.calIWcapErrors.WCAP_CANNOT_MODIFY_LINKED_TODOS, "storetodos.wcap failed. The todo to modify was a linked todo.",
/* 33 */ Components.interfaces.calIWcapErrors.WCAP_CANNOT_SENT_EMAIL, "Command failed. Email notification failed. Usually caused by the server not being properly configured to send email. This can occur in storeevents.wcap, storetodos.wcap, deleteevents_by_id.wcap, deletetodos_by_id.wcap.",
/* 34 */ Components.interfaces.calIWcapErrors.WCAP_CALENDAR_DISABLED, "Command failed. The calendar is disabled in the database.",
/* 35 */ Components.interfaces.calIWcapErrors.WCAP_WRITE_IMPORT_FAILED, "Import failed when writing files to the server.",
/* 36 */ Components.interfaces.calIWcapErrors.WCAP_FETCH_BY_LAST_MODIFIED_FAILED, "WCAP_FETCH_BY_LAST_MODIFIED_FAILED",
/* 37 */ Components.interfaces.calIWcapErrors.WCAP_CAPI_NOT_SUPPORTED, "Failed trying to read from unsupported format calendar data.",
/* 38 */ Components.interfaces.calIWcapErrors.WCAP_CALID_NOT_SPECIFIED, "Calendar ID was not specified.",
/* 39 */ Components.interfaces.calIWcapErrors.WCAP_GET_FREEBUSY_FAILED, "WCAP_GET_FREEBUSY_FAILED",
/* 40 */ Components.interfaces.calIWcapErrors.WCAP_STORE_FAILED_DOUBLE_BOOKED, "If double booking is not allowed in this calendar, storeevents.wcap fails with this error when attempting to store an event in a time slot that was already filled.",
/* 41 */ Components.interfaces.calIWcapErrors.WCAP_FETCH_BY_ALARM_RANGE_FAILED, "WCAP_FETCH_BY_ALARM_RANGE_FAILED",
/* 42 */ Components.interfaces.calIWcapErrors.WCAP_FETCH_BY_ATTENDEE_ERROR_FAILED, "WCAP_FETCH_BY_ATTENDEE_ERROR_FAILED",
/* 43 */ Components.interfaces.calIWcapErrors.WCAP_ATTENDEE_GROUP_EXPANSION_CLIPPED, "An LDAP group being expanded was too large and exceeded the maximum number allowed in an expansion. The expansion stopped at the specified maximum limit. The maximum limit defaults to 200. To change the maximum limit, set the server configuration preference calstore.group.attendee.maxsize.",
/* 44 */ Components.interfaces.calIWcapErrors.WCAP_USERPREFS_ACCESS_DENIED, "Either the server does not allow this administrator access to get or modify user preferences, or the requester is not an administrator.",
/* 45 */ Components.interfaces.calIWcapErrors.WCAP_NOT_ALLOWED_TO_REQUEST_PUBLISH, "The requester was not an organizer of the event, and, therefore, is not allowed to edit the component using the PUBLISH or REQUEST method.",
/* 46 */ Components.interfaces.calIWcapErrors.WCAP_INSUFFICIENT_PARAMETERS, "The caller tried to invoke verifyevents_by_ids.wcap, or verifytodos_by_ids.wcap with insufficient arguments (mismatched number of uids and rids).",
/* 47 */ Components.interfaces.calIWcapErrors.WCAP_MUSTBEOWNER_OPERATION, "The user needs to be an owner or co-owner of the calendar in questions to complete this operation. (Probably related to private or confidential component.)",
/* 48 */ Components.interfaces.calIWcapErrors.WCAP_DWP_CONNECTION_FAILED, "GSE scheduling engine failed to make connection to DWP.",
/* 49 */ Components.interfaces.calIWcapErrors.WCAP_DWP_MAX_CONNECTION_REACHED, "Reached the maximum number of connections. When some of the connections are freed, users can successfully connect. Same as error 11001.",
/* 50 */ Components.interfaces.calIWcapErrors.WCAP_DWP_CANNOT_RESOLVE_CALENDAR, "Front end cant resolve to a particular back end. Same as error 11002.",
/* 51 */ Components.interfaces.calIWcapErrors.WCAP_DWP_BAD_DATA, "Generic response. Check all DWP servers. One might be down. Same as error 11003.",
/* 52 */ Components.interfaces.calIWcapErrors.WCAP_BAD_COMMAND, "The command sent in was not recognized. This is an internal only error code. It should not appear in the error logs.",
/* 53 */ Components.interfaces.calIWcapErrors.WCAP_NOT_FOUND, "Returned for all errors from a write to the Berkeley DB. This is an internal only error code. It should not appear in the error logs.",
/* 54 */ Components.interfaces.calIWcapErrors.WCAP_WRITE_IMPORT_CANT_EXPAND_CALID, "Cant expand calid when importing file.",
/* 55 */ Components.interfaces.calIWcapErrors.WCAP_GETTIME_FAILED, "Get server time failed.",
/* 56 */ Components.interfaces.calIWcapErrors.WCAP_FETCH_DELETEDCOMPONENTS_FAILED, "fetch_deletedcomponents.wcap failed.",
/* 57 */ Components.interfaces.calIWcapErrors.WCAP_FETCH_DELETEDCOMPONENTS_PARTIAL_RESULT, "Success but partial result.",
/* 58 */ Components.interfaces.calIWcapErrors.WCAP_WCAP_NO_SUCH_FORMAT, "Returned in any of the commands when supplied fmt-out is not a supported format.",
/* 59 */ Components.interfaces.calIWcapErrors.WCAP_COMPONENT_NOT_FOUND, "Returned when a fetch or delete is attempted that does not exist.",
/* 60 */ Components.interfaces.calIWcapErrors.WCAP_BAD_ARGUMENTS, "Currently used when attendee or organizer specified does not have a valid email address.",
/* 61 */ Components.interfaces.calIWcapErrors.WCAP_GET_USERPREFS_FAILED, "get_userprefs.wcap failed. The following error conditions returns error code 61: LDAP access denied, no results found, LDAP limit exceeded, LDAP connection failed.",
/* 62 */ Components.interfaces.calIWcapErrors.WCAP_WCAP_MODIFY_NO_EVENT, "storeevents.wcap issued with storetype set to 2 (WCAP_STORE_TYPE_MODIFY) and the event doesn\t exist.",
/* 63 */ Components.interfaces.calIWcapErrors.WCAP_WCAP_CREATE_EXISTS, "storeevents.wcap issued with storetype set to 1 (WCAP_STORE_TYPE_CREATE) and the event already exists.",
/* 64 */ Components.interfaces.calIWcapErrors.WCAP_WCAP_MODIFY_CANT_MAKE_COPY, "storevents.wcap issued and copy of event failed during processing.",
/* 65 */ Components.interfaces.calIWcapErrors.WCAP_STORE_FAILED_RECUR_SKIP, "One instance of a recurring event skips over another.",
/* 66 */ Components.interfaces.calIWcapErrors.WCAP_STORE_FAILED_RECUR_SAMEDAY, "Two instances of a recurring event cant occur on the same day.",
/* 67 */ Components.interfaces.calIWcapErrors.WCAP_BAD_ORG_ARGUMENTS, "Bad organizer arguments. orgCalid or orgEmail must be passed if any other \"org\" parameter is sent. That is, orgUID cant be sent alone on a storeevents.wcap or a storetodos.wcao command if it is trying about to \"create\" the event or task. Note, if no \"org\" information is passed, the organizer defaults to the calid being passed with the command.",
/* 68 */ Components.interfaces.calIWcapErrors.WCAP_STORE_FAILED_RECUR_PRIVACY, "Error returned if you try to change the privacy or transparency of a single instance in a recurring series.",
/* 69 */ Components.interfaces.calIWcapErrors.WCAP_LDAP_ERROR, "For get_calprops.wcap, when there is an error is getting LDAP derived token values (X-S1CS-CALPROPS-FB-INCLUDE, X-S1CS-CALPROPS-COMMON-NAME).",
/* 70 */ Components.interfaces.calIWcapErrors.WCAP_GET_INVITE_COUNT_FAILED, "Error in getting invite count (for get_calprops.wcap and fetchcomponents_by_range.wcap commands).",
/* 71 */ Components.interfaces.calIWcapErrors.WCAP_LIST_FAILED, "list.wcap failed.",
/* 72 */ Components.interfaces.calIWcapErrors.WCAP_LIST_SUBSCRIBED_FAILED, "list_subscribed.wcap failed.",
/* 73 */ Components.interfaces.calIWcapErrors.WCAP_SUBSCRIBE_FAILED, "subscribe.wcap failed.",
/* 74 */ Components.interfaces.calIWcapErrors.WCAP_UNSUBSCRIBE_FAILED, "unsubscribe.wcap failed.",
/* 75 */ Components.interfaces.calIWcapErrors.WCAP_ANONYMOUS_NOT_ALLOWED, "Command cannot be executed as anonymous. Used only for list.wcap, list_subscribed.wcap, subscribe.wcap, and unsubscribe.wcap commands.",
/* 76 */ Components.interfaces.calIWcapErrors.WCAP_ACCESS_DENIED, "Generated if a non-administrator user tries to read or set the calendar-owned list or the calendar-subscribed list of some other user, or if the option is not turned on in the server.",
/* 77 */ Components.interfaces.calIWcapErrors.WCAP_BAD_IMPORT_ARGUMENTS, "Incorrect parameter received by import.wcap.",
/* 78 */ Components.interfaces.calIWcapErrors.WCAP_READONLY_DATABASE, "Database is in read-only mode (returned for all attempts to write to the database).",
/* 79 */ Components.interfaces.calIWcapErrors.WCAP_ATTENDEE_NOT_ALLOWED_TO_REQUEST_ON_MODIFY, "Attendee is not allowed to modify an event with method=request.",
/* 80 */ Components.interfaces.calIWcapErrors.WCAP_TRANSP_RESOURCE_NOT_ALLOWED, "Resources do not permit the transparency parameter.",
/* 81 */ Components.interfaces.calIWcapErrors.WCAP_RECURRING_COMPONENT_NOT_FOUND, "Recurring component not found. Only happens when recurring=1 is passed in by fetch commands. This code is returned if part of the recurring series (either the master or an exception) is missing.",
/* 8 */ calIWcapErrors.WCAP_SETCALPROPS_FAILED, "WCAP_SETCALPROPS_FAILED",
/* 9 */ calIWcapErrors.WCAP_FETCH_EVENTS_BY_ID_FAILED, "WCAP_FETCH_EVENTS_BY_ID_FAILED",
/* 10 */ calIWcapErrors.WCAP_CREATECALENDAR_FAILED, "WCAP_CREATECALENDAR_FAILED",
/* 11 */ calIWcapErrors.WCAP_DELETECALENDAR_FAILED, "WCAP_DELETECALENDAR_FAILED",
/* 12 */ calIWcapErrors.WCAP_ADDLINK_FAILED, "WCAP_ADDLINK_FAILED",
/* 13 */ calIWcapErrors.WCAP_FETCHBYDATERANGE_FAILED, "WCAP_FETCHBYDATERANGE_FAILED",
/* 14 */ calIWcapErrors.WCAP_STOREEVENTS_FAILED, "WCAP_STOREEVENTS_FAILED",
/* 15 */ calIWcapErrors.WCAP_STORETODOS_FAILED, "WCAP_STORETODOS_FAILED",
/* 16 */ calIWcapErrors.WCAP_DELETE_TODOS_BY_ID_FAILED, "WCAP_DELETE_TODOS_BY_ID_FAILED",
/* 17 */ calIWcapErrors.WCAP_FETCH_TODOS_BY_ID_FAILED, "WCAP_FETCH_TODOS_BY_ID_FAILED",
/* 18 */ calIWcapErrors.WCAP_FETCHCOMPONENTS_FAILED_BAD_TZID, "Command failed to find correct tzid. Applies to fetchcomponents_by_range.wcap, fetchevents_by_id.wcap, fetchtodos_by_id.wcap.",
/* 19 */ calIWcapErrors.WCAP_SEARCH_CALPROPS_FAILED, "WCAP_SEARCH_CALPROPS_FAILED",
/* 20 */ calIWcapErrors.WCAP_GET_CALPROPS_FAILED, "WCAP_GET_CALPROPS_FAILED",
/* 21 */ calIWcapErrors.WCAP_DELETECOMPONENTS_BY_RANGE_FAILED, "WCAP_DELETECOMPONENTS_BY_RANGE_FAILED",
/* 22 */ calIWcapErrors.WCAP_DELETEEVENTS_BY_RANGE_FAILED, "WCAP_DELETEEVENTS_BY_RANGE_FAILED",
/* 23 */ calIWcapErrors.WCAP_DELETETODOS_BY_RANGE_FAILED, "WCAP_DELETETODOS_BY_RANGE_FAILED",
/* 24 */ calIWcapErrors.WCAP_GET_ALL_TIMEZONES_FAILED, "WCAP_GET_ALL_TIMEZONES_FAILED",
/* 25 */ calIWcapErrors.WCAP_CREATECALENDAR_ALREADY_EXISTS_FAILED, "The command createcalendar.wcap failed. A calendar with that name already exists in the database.",
/* 26 */ calIWcapErrors.WCAP_SET_USERPREFS_FAILED, "WCAP_SET_USERPREFS_FAILED",
/* 27 */ calIWcapErrors.WCAP_CHANGE_PASSWORD_FAILED, "WCAP_CHANGE_PASSWORD_FAILED",
/* 28 */ calIWcapErrors.WCAP_ACCESS_DENIED_TO_CALENDAR, "Command failed. The user is denied access to a calendar.",
/* 29 */ calIWcapErrors.WCAP_CALENDAR_DOES_NOT_EXIST, "Command failed. The requested calendar does not exist in the database.",
/* 30 */ calIWcapErrors.WCAP_ILLEGAL_CALID_NAME, "createcalendar.wcap failed. Invalid calid passed in.",
/* 31 */ calIWcapErrors.WCAP_CANNOT_MODIFY_LINKED_EVENTS, "storeevents.wcap failed. The event to modify was a linked event.",
/* 32 */ calIWcapErrors.WCAP_CANNOT_MODIFY_LINKED_TODOS, "storetodos.wcap failed. The todo to modify was a linked todo.",
/* 33 */ calIWcapErrors.WCAP_CANNOT_SENT_EMAIL, "Command failed. Email notification failed. Usually caused by the server not being properly configured to send email. This can occur in storeevents.wcap, storetodos.wcap, deleteevents_by_id.wcap, deletetodos_by_id.wcap.",
/* 34 */ calIWcapErrors.WCAP_CALENDAR_DISABLED, "Command failed. The calendar is disabled in the database.",
/* 35 */ calIWcapErrors.WCAP_WRITE_IMPORT_FAILED, "Import failed when writing files to the server.",
/* 36 */ calIWcapErrors.WCAP_FETCH_BY_LAST_MODIFIED_FAILED, "WCAP_FETCH_BY_LAST_MODIFIED_FAILED",
/* 37 */ calIWcapErrors.WCAP_CAPI_NOT_SUPPORTED, "Failed trying to read from unsupported format calendar data.",
/* 38 */ calIWcapErrors.WCAP_CALID_NOT_SPECIFIED, "Calendar ID was not specified.",
/* 39 */ calIWcapErrors.WCAP_GET_FREEBUSY_FAILED, "WCAP_GET_FREEBUSY_FAILED",
/* 40 */ calIWcapErrors.WCAP_STORE_FAILED_DOUBLE_BOOKED, "If double booking is not allowed in this calendar, storeevents.wcap fails with this error when attempting to store an event in a time slot that was already filled.",
/* 41 */ calIWcapErrors.WCAP_FETCH_BY_ALARM_RANGE_FAILED, "WCAP_FETCH_BY_ALARM_RANGE_FAILED",
/* 42 */ calIWcapErrors.WCAP_FETCH_BY_ATTENDEE_ERROR_FAILED, "WCAP_FETCH_BY_ATTENDEE_ERROR_FAILED",
/* 43 */ calIWcapErrors.WCAP_ATTENDEE_GROUP_EXPANSION_CLIPPED, "An LDAP group being expanded was too large and exceeded the maximum number allowed in an expansion. The expansion stopped at the specified maximum limit. The maximum limit defaults to 200. To change the maximum limit, set the server configuration preference calstore.group.attendee.maxsize.",
/* 44 */ calIWcapErrors.WCAP_USERPREFS_ACCESS_DENIED, "Either the server does not allow this administrator access to get or modify user preferences, or the requester is not an administrator.",
/* 45 */ calIWcapErrors.WCAP_NOT_ALLOWED_TO_REQUEST_PUBLISH, "The requester was not an organizer of the event, and, therefore, is not allowed to edit the component using the PUBLISH or REQUEST method.",
/* 46 */ calIWcapErrors.WCAP_INSUFFICIENT_PARAMETERS, "The caller tried to invoke verifyevents_by_ids.wcap, or verifytodos_by_ids.wcap with insufficient arguments (mismatched number of uids and rids).",
/* 47 */ calIWcapErrors.WCAP_MUSTBEOWNER_OPERATION, "The user needs to be an owner or co-owner of the calendar in questions to complete this operation. (Probably related to private or confidential component.)",
/* 48 */ calIWcapErrors.WCAP_DWP_CONNECTION_FAILED, "GSE scheduling engine failed to make connection to DWP.",
/* 49 */ calIWcapErrors.WCAP_DWP_MAX_CONNECTION_REACHED, "Reached the maximum number of connections. When some of the connections are freed, users can successfully connect. Same as error 11001.",
/* 50 */ calIWcapErrors.WCAP_DWP_CANNOT_RESOLVE_CALENDAR, "Front end cant resolve to a particular back end. Same as error 11002.",
/* 51 */ calIWcapErrors.WCAP_DWP_BAD_DATA, "Generic response. Check all DWP servers. One might be down. Same as error 11003.",
/* 52 */ calIWcapErrors.WCAP_BAD_COMMAND, "The command sent in was not recognized. This is an internal only error code. It should not appear in the error logs.",
/* 53 */ calIWcapErrors.WCAP_NOT_FOUND, "Returned for all errors from a write to the Berkeley DB. This is an internal only error code. It should not appear in the error logs.",
/* 54 */ calIWcapErrors.WCAP_WRITE_IMPORT_CANT_EXPAND_CALID, "Cant expand calid when importing file.",
/* 55 */ calIWcapErrors.WCAP_GETTIME_FAILED, "Get server time failed.",
/* 56 */ calIWcapErrors.WCAP_FETCH_DELETEDCOMPONENTS_FAILED, "fetch_deletedcomponents.wcap failed.",
/* 57 */ calIWcapErrors.WCAP_FETCH_DELETEDCOMPONENTS_PARTIAL_RESULT, "Success but partial result.",
/* 58 */ calIWcapErrors.WCAP_WCAP_NO_SUCH_FORMAT, "Returned in any of the commands when supplied fmt-out is not a supported format.",
/* 59 */ calIWcapErrors.WCAP_COMPONENT_NOT_FOUND, "Returned when a fetch or delete is attempted that does not exist.",
/* 60 */ calIWcapErrors.WCAP_BAD_ARGUMENTS, "Currently used when attendee or organizer specified does not have a valid email address.",
/* 61 */ calIWcapErrors.WCAP_GET_USERPREFS_FAILED, "get_userprefs.wcap failed. The following error conditions returns error code 61: LDAP access denied, no results found, LDAP limit exceeded, LDAP connection failed.",
/* 62 */ calIWcapErrors.WCAP_WCAP_MODIFY_NO_EVENT, "storeevents.wcap issued with storetype set to 2 (WCAP_STORE_TYPE_MODIFY) and the event doesn\t exist.",
/* 63 */ calIWcapErrors.WCAP_WCAP_CREATE_EXISTS, "storeevents.wcap issued with storetype set to 1 (WCAP_STORE_TYPE_CREATE) and the event already exists.",
/* 64 */ calIWcapErrors.WCAP_WCAP_MODIFY_CANT_MAKE_COPY, "storevents.wcap issued and copy of event failed during processing.",
/* 65 */ calIWcapErrors.WCAP_STORE_FAILED_RECUR_SKIP, "One instance of a recurring event skips over another.",
/* 66 */ calIWcapErrors.WCAP_STORE_FAILED_RECUR_SAMEDAY, "Two instances of a recurring event cant occur on the same day.",
/* 67 */ calIWcapErrors.WCAP_BAD_ORG_ARGUMENTS, "Bad organizer arguments. orgCalid or orgEmail must be passed if any other \"org\" parameter is sent. That is, orgUID cant be sent alone on a storeevents.wcap or a storetodos.wcao command if it is trying about to \"create\" the event or task. Note, if no \"org\" information is passed, the organizer defaults to the calid being passed with the command.",
/* 68 */ calIWcapErrors.WCAP_STORE_FAILED_RECUR_PRIVACY, "Error returned if you try to change the privacy or transparency of a single instance in a recurring series.",
/* 69 */ calIWcapErrors.WCAP_LDAP_ERROR, "For get_calprops.wcap, when there is an error is getting LDAP derived token values (X-S1CS-CALPROPS-FB-INCLUDE, X-S1CS-CALPROPS-COMMON-NAME).",
/* 70 */ calIWcapErrors.WCAP_GET_INVITE_COUNT_FAILED, "Error in getting invite count (for get_calprops.wcap and fetchcomponents_by_range.wcap commands).",
/* 71 */ calIWcapErrors.WCAP_LIST_FAILED, "list.wcap failed.",
/* 72 */ calIWcapErrors.WCAP_LIST_SUBSCRIBED_FAILED, "list_subscribed.wcap failed.",
/* 73 */ calIWcapErrors.WCAP_SUBSCRIBE_FAILED, "subscribe.wcap failed.",
/* 74 */ calIWcapErrors.WCAP_UNSUBSCRIBE_FAILED, "unsubscribe.wcap failed.",
/* 75 */ calIWcapErrors.WCAP_ANONYMOUS_NOT_ALLOWED, "Command cannot be executed as anonymous. Used only for list.wcap, list_subscribed.wcap, subscribe.wcap, and unsubscribe.wcap commands.",
/* 76 */ calIWcapErrors.WCAP_ACCESS_DENIED, "Generated if a non-administrator user tries to read or set the calendar-owned list or the calendar-subscribed list of some other user, or if the option is not turned on in the server.",
/* 77 */ calIWcapErrors.WCAP_BAD_IMPORT_ARGUMENTS, "Incorrect parameter received by import.wcap.",
/* 78 */ calIWcapErrors.WCAP_READONLY_DATABASE, "Database is in read-only mode (returned for all attempts to write to the database).",
/* 79 */ calIWcapErrors.WCAP_ATTENDEE_NOT_ALLOWED_TO_REQUEST_ON_MODIFY, "Attendee is not allowed to modify an event with method=request.",
/* 80 */ calIWcapErrors.WCAP_TRANSP_RESOURCE_NOT_ALLOWED, "Resources do not permit the transparency parameter.",
/* 81 */ calIWcapErrors.WCAP_RECURRING_COMPONENT_NOT_FOUND, "Recurring component not found. Only happens when recurring=1 is passed in by fetch commands. This code is returned if part of the recurring series (either the master or an exception) is missing.",
/* new by WCAP 4.0: */
/* 82 */ Components.interfaces.calIWcapErrors.WCAP_BAD_MIME_TYPE,
/* 82 */ calIWcapErrors.WCAP_BAD_MIME_TYPE,
"The mime headers supplied while storing the attachment using storeevents.wcap/storetodos.wcap is malformatted.",
/* 83 */ Components.interfaces.calIWcapErrors.WCAP_MISSING_BOUNDARY,
/* 83 */ calIWcapErrors.WCAP_MISSING_BOUNDARY,
"While supplying attachments to the storeveents/storetodos commands the mime boundary was not found.",
/* 84 */ Components.interfaces.calIWcapErrors.WCAP_INVALID_ATTACHMENT,
/* 84 */ calIWcapErrors.WCAP_INVALID_ATTACHMENT,
"The attachment supplied to be stored on the server is malformatted.",
/* 85 */ Components.interfaces.calIWcapErrors.WCAP_ATTACH_DELETE_SUCCESS,
/* 85 */ calIWcapErrors.WCAP_ATTACH_DELETE_SUCCESS,
"All the attachments requested to be deleted from the server by supplying deleteattach were deleted successsfully.",
/* 86 */ Components.interfaces.calIWcapErrors.WCAP_ATTACH_DELETE_PARTIAL,
/* 86 */ calIWcapErrors.WCAP_ATTACH_DELETE_PARTIAL,
"Of All attachments requested to be deleted from the server by supplying deleteattach , only few were deleted successfully.",
/* 87 */ Components.interfaces.calIWcapErrors.WCAP_ATTACHMENT_NOT_FOUND,
/* 87 */ calIWcapErrors.WCAP_ATTACHMENT_NOT_FOUND,
"The attachent requested to be fetched or deleted from the server was not found.",
/* / new by WCAP 4.0 */
/* 88 */ Components.results.NS_ERROR_INVALID_ARG, "No WCAP error code.",
@ -245,25 +245,25 @@ const g_wcapErrorCodes = [
/* 97 */ Components.results.NS_ERROR_INVALID_ARG, "No WCAP error code.",
/* 98 */ Components.results.NS_ERROR_INVALID_ARG, "No WCAP error code.",
/* 99 */ Components.results.NS_ERROR_INVALID_ARG, "No WCAP error code.",
/* 11000 */ Components.interfaces.calIWcapErrors.WCAP_CDWP_ERR_MAX_CONNECTION_REACHED, "Maximum connections to back-end database reached. As connections are freed up, users can connect to the back-end.",
/* 11001 */ Components.interfaces.calIWcapErrors.WCAP_CDWP_ERR_CANNOT_CONNECT, "Cannot connect to back-end server. Back-end machine might be down or DWP server is not up and running.",
/* 11002 */ Components.interfaces.calIWcapErrors.WCAP_CDWP_ERR_CANNOT_RESOLVE_CALENDAR, "Front-end cant resolve calendar to a particular back-end server.",
/* 11003 */ Components.interfaces.calIWcapErrors.WCAP_CDWP_ERR_BAD_DATA, "Bad data received from DWP connection. This is a generic formatting error. Check all DWP servers. One might be down.",
/* 11004 */ Components.interfaces.calIWcapErrors.WCAP_CDWP_ERR_DWPHOST_CTX_DOES_NOT_EXIST, "For the back-end host, context doesn\t exist in the context table.",
/* 11005 */ Components.interfaces.calIWcapErrors.WCAP_CDWP_ERR_HOSTNAME_NOT_RESOLVABLE, "DNS or NIS files, or hostname resolver is not set up properly or machine does not exist.",
/* 11006 */ Components.interfaces.calIWcapErrors.WCAP_CDWP_ERR_NO_DATA, "No data was received from reading the calendar properties from the DWP connection.",
/* 11007 */ Components.interfaces.calIWcapErrors.WCAP_CDWP_ERR_AUTH_FAILED, "DWP authentication failed.",
/* 11008 */ Components.interfaces.calIWcapErrors.WCAP_CDWP_ERR_CHECKVERSION_FAILED, "DWP version check failed."
/* 11000 */ calIWcapErrors.WCAP_CDWP_ERR_MAX_CONNECTION_REACHED, "Maximum connections to back-end database reached. As connections are freed up, users can connect to the back-end.",
/* 11001 */ calIWcapErrors.WCAP_CDWP_ERR_CANNOT_CONNECT, "Cannot connect to back-end server. Back-end machine might be down or DWP server is not up and running.",
/* 11002 */ calIWcapErrors.WCAP_CDWP_ERR_CANNOT_RESOLVE_CALENDAR, "Front-end cant resolve calendar to a particular back-end server.",
/* 11003 */ calIWcapErrors.WCAP_CDWP_ERR_BAD_DATA, "Bad data received from DWP connection. This is a generic formatting error. Check all DWP servers. One might be down.",
/* 11004 */ calIWcapErrors.WCAP_CDWP_ERR_DWPHOST_CTX_DOES_NOT_EXIST, "For the back-end host, context doesn\t exist in the context table.",
/* 11005 */ calIWcapErrors.WCAP_CDWP_ERR_HOSTNAME_NOT_RESOLVABLE, "DNS or NIS files, or hostname resolver is not set up properly or machine does not exist.",
/* 11006 */ calIWcapErrors.WCAP_CDWP_ERR_NO_DATA, "No data was received from reading the calendar properties from the DWP connection.",
/* 11007 */ calIWcapErrors.WCAP_CDWP_ERR_AUTH_FAILED, "DWP authentication failed.",
/* 11008 */ calIWcapErrors.WCAP_CDWP_ERR_CHECKVERSION_FAILED, "DWP version check failed."
];
function wcapErrorToString( rc )
{
if (isNaN(rc))
throw Components.results.NS_ERROR_INVALID_ARG;
if (rc == Components.interfaces.calIWcapErrors.WCAP_NO_ERRNO)
if (rc == calIWcapErrors.WCAP_NO_ERRNO)
return "No WCAP errno (missing X-NSCP-WCAP-ERRNO).";
var index = (rc - Components.interfaces.calIWcapErrors.WCAP_ERROR_BASE + 1);
var index = (rc - calIWcapErrors.WCAP_ERROR_BASE + 1);
if (index >= 1 && index <= 108 &&
g_wcapErrorCodes[index * 2] != Components.results.NS_ERROR_INVALID_ARG)
{
@ -272,7 +272,7 @@ function wcapErrorToString( rc )
throw Components.results.NS_ERROR_INVALID_ARG;
}
function getWcapErrorCode( errno )
function getWcapErrorCode(errno)
{
var index = -1;
if (errno >= -1 && errno <= 81)
@ -287,80 +287,112 @@ function getWcapErrorCode( errno )
throw Components.results.NS_ERROR_INVALID_ARG;
}
function getWcapXmlErrno( xml )
function getWcapXmlErrno(xml)
{
var elem = xml.getElementsByTagName( "X-NSCP-WCAP-ERRNO" );
var elem = xml.getElementsByTagName("X-NSCP-WCAP-ERRNO");
if (elem) {
elem = elem.item(0);
if (elem)
return parseInt(elem.textContent);
}
// some commands just respond with an empty calendar, no errno. WTF.
throw new Components.Exception(
"No WCAP errno (missing X-NSCP-WCAP-ERRNO).",
Components.interfaces.calIWcapErrors.WCAP_NO_ERRNO );
// assume success:
return undefined;
}
function getWcapIcalErrno( icalRootComp )
function getWcapIcalErrno(icalRootComp)
{
var prop = icalRootComp.getFirstProperty( "X-NSCP-WCAP-ERRNO" );
var prop = icalRootComp.getFirstProperty("X-NSCP-WCAP-ERRNO");
if (prop)
return parseInt(prop.value);
// some commands just respond with an empty calendar, no errno. WTF.
throw new Components.Exception(
"No WCAP errno (missing X-NSCP-WCAP-ERRNO).",
Components.interfaces.calIWcapErrors.WCAP_NO_ERRNO );
// assume success:
return undefined;
}
function checkWcapErrno( errno, expectedErrno )
function checkWcapErrno(errno, expectedErrno)
{
if (expectedErrno == undefined)
if (expectedErrno === undefined)
expectedErrno = 0; // i.e. Command successful.
if (errno != expectedErrno) {
if (errno !== undefined && errno != expectedErrno) {
var rc;
try {
rc = getWcapErrorCode(errno);
}
catch (exc) {
throw new Components.Exception(
"No WCAP error no.", Components.results.NS_ERROR_INVALID_ARG );
"No WCAP error no.", Components.results.NS_ERROR_INVALID_ARG);
}
throw new Components.Exception( wcapErrorToString(rc), rc );
throw new Components.Exception(wcapErrorToString(rc), rc);
}
}
function checkWcapXmlErrno( xml, expectedErrno )
{
checkWcapErrno( getWcapXmlErrno(xml), expectedErrno );
function checkWcapXmlErrno(xml, expectedErrno) {
checkWcapErrno(getWcapXmlErrno(xml), expectedErrno);
}
function checkWcapIcalErrno( icalRootComp, expectedErrno )
{
checkWcapErrno( getWcapIcalErrno(icalRootComp), expectedErrno );
function checkWcapIcalErrno(icalRootComp, expectedErrno) {
checkWcapErrno(getWcapIcalErrno(icalRootComp), expectedErrno);
}
function errorToString( err )
function getResultCode(err)
{
if (typeof(err) == "string")
return err;
if (err instanceof Error)
return err.message;
if (err instanceof Components.interfaces.nsIException)
return err.toString(); // xxx todo: or just message?
if (err === undefined || err === null)
return Components.results.NS_OK;
if (isNaN(err)) {
if (err instanceof nsIException)
return err.result;
else
return Components.results.NS_ERROR_FAILURE;
}
return err;
}
function errorToString(err)
{
if (err) {
if (typeof(err) == "string")
return err;
if (err instanceof Error)
return err.message;
if (err instanceof nsIException)
return err.toString(); // xxx todo: or just message?
if (isNaN(err))
return ("[" + err + "] unknown error.");
}
// numeric codes:
switch (err) {
case undefined:
case null:
case Components.results.NS_OK:
return "NS_OK";
case Components.results.NS_ERROR_INVALID_ARG:
return "NS_ERROR_INVALID_ARG";
case Components.results.NS_ERROR_NO_INTERFACE:
return "NS_ERROR_NO_INTERFACE";
case Components.results.NS_ERROR_NOT_IMPLEMENTED:
return "NS_ERROR_NOT_IMPLEMENTED";
case Components.results.NS_ERROR_NOT_AVAILABLE:
return "NS_ERROR_NOT_AVAILABLE";
case Components.results.NS_ERROR_FAILURE:
return "NS_ERROR_FAILURE";
case Components.results.NS_ERROR_BASE:
return "NS_ERROR_BASE";
case Components.results.NS_ERROR_NOT_INITIALIZED:
return "NS_ERROR_NOT_INITIALIZED";
case Components.results.NS_ERROR_ALREADY_INITIALIZED:
return "NS_ERROR_ALREADY_INITIALIZED";
case Components.results.NS_ERROR_NULL_POINTER:
return "NS_ERROR_NULL_POINTER";
case Components.results.NS_ERROR_ABORT:
return "NS_ERROR_ABORT";
case Components.results.NS_ERROR_UNEXPECTED:
return "NS_ERROR_UNEXPECTED";
case Components.results.NS_ERROR_OUT_OF_MEMORY:
return "NS_ERROR_OUT_OF_MEMORY";
case Components.results.NS_ERROR_ILLEGAL_VALUE:
return "NS_ERROR_ILLEGAL_VALUE";
default:
if (isNaN(err))
return ("[" + err + "] Unknown error.");
// probe for WCAP error:
try {
return wcapErrorToString(err);
@ -370,7 +402,7 @@ function errorToString( err )
return netErrorToString(err);
}
catch (exc) {
return ("[0x" + err.toString(16) + "] Unknown error.");
return ("[0x" + err.toString(0x10) + "] unknown error.");
}
}
}

Просмотреть файл

@ -37,9 +37,356 @@
*
* ***** END LICENSE BLOCK ***** */
//
// WCAP request helpers
//
/**
Requests, either the queued calWcapRequest or an async network request.
A request object is used to track an async action.
While the action is running, isPending is true.
Functions issuing an async action usually take a response function along
with their parameters, typically named respFunc.
That function is called *after* the action has ended (i.e. isPending of the
issued action/request is false when called, status remains stable).
The response function gets the ended request as first parameter to check
whether the request has been successful and get its data.
The request function itself may return either
- a further calIWcapRequest request object, i.e. an async continuation
- some data (incl null/undefined) which is the result of the async function,
indicating that there is no further continuation
*/
var g_requestId = 0;
function generateRequestId() {
++g_requestId;
return g_requestId;
}
function calWcapRequest(respFunc, logContext) {
this.wrappedJSObject = this;
this.m_logContext = logContext;
this.m_id = generateRequestId();
this.m_isPending = true;
this.m_status = Components.results.NS_OK;
this.m_respFunc = respFunc;
this.m_attachedRequests = [];
}
calWcapRequest.prototype = {
m_logContext: null,
m_parentRequest: null,
m_id: 0,
m_isPending: true,
m_status: Components.results.NS_OK,
m_respFunc: null,
m_attachedRequests: null,
m_locked: false,
get parentRequest() { return this.m_parentRequest; },
set parentRequest(req) {
if (this.parentRequest)
logError("already has parent!", this);
this.detachFromParent(); // detach without error
this.m_parentRequest = req;
},
/** The following locking is necessary when scheduling multiple async
requests; one cannot be sure that e.g. the first completes quickly
and responds the whole parent request when detaching.
*/
lockPending: function calWcapRequest_lockPending() {
this.m_locked = true;
},
unlockPending: function calWcapRequest_unlockPending() {
if (this.m_locked) {
this.m_locked = false;
// assures that respFunc is executed:
if (this.m_attachedRequests.length == 0) {
this.execRespFunc();
}
}
},
toString: function calWcapRequest_toString() {
var ret = ("calWcapRequest id=" + this.id +
", parent-id=" +
(this.parentRequest ? this.parentRequest.id : "<none>") +
" (" + this.m_logContext + ")");
if (LOG_LEVEL > 2 && this.m_attachedRequests.length > 0) {
ret += "\nattached requests:";
for each ( var req in this.m_attachedRequests ) {
ret += ("\n#" + req.id + "\t" + req);
}
}
return ret;
},
attachSubRequest: function calWcapRequest_attachSubRequest(req)
{
if (req) {
if (!this.m_attachedRequests.some(
function(req_) { return req.id == req_.id; } )) {
if (req.isPending) {
this.m_attachedRequests.push(req);
req.parentRequest = this;
log("attachSubRequest()", this);
}
else if (!this.m_locked && this.m_attachedRequests.length == 0) {
this.execRespFunc(req.status);
}
}
else {
logError("request already attached: " + req.id, this);
}
}
},
detachSubRequest: function calWcapRequest_detachSubRequest(req, err)
{
this.m_attachedRequests = this.m_attachedRequests.filter(
function(req_) { return req.id != req_.id; } );
if (err) {
// first failing sub request stops whole request:
this.execRespFunc(err);
}
// assures that respFunc is executed after every sub request has been completed:
else if (!this.m_locked && this.m_attachedRequests.length == 0) {
this.execRespFunc();
}
},
cancelAllSubRequests: function calWcapRequest_cancelAllSubRequests(status) {
var attachedRequests = this.m_attachedRequests;
this.m_attachedRequests = [];
attachedRequests.forEach( function(req) { req.cancel(status); } );
},
detachFromParent: function calWcapRequest_detachFromParent(err) {
var parentRequest = this.m_parentRequest;
if (parentRequest) {
this.m_parentRequest = null;
parentRequest.detachSubRequest(this, err);
}
},
execRespFunc: function calWcapRequest_execRespFunc(err, data)
{
if (this.isPending) {
this.m_isPending = false;
if (err)
this.m_status = err;
this.cancelAllSubRequests();
var respFunc = this.m_respFunc;
if (respFunc) {
this.m_respFunc = null; // call once only
if (LOG_LEVEL > 2) {
log("response exec: " + errorToString(err), this);
}
try {
respFunc(this, err, data);
}
catch (exc) {
this.m_status = exc;
logError(exc, this);
}
}
this.detachFromParent(this.m_status);
}
},
// calIWcapRequest:
get id() {
return this.m_id;
},
get isPending() {
return this.m_isPending;
},
get succeeded() {
return (!this.isPending &&
getResultCode(this.status) == Components.results.NS_OK);
},
get status() {
return (this.m_status === null ? Components.results.NS_OK
: this.m_status);
},
cancel: function calWcapRequest_cancel(status)
{
if (this.isPending) {
this.m_isPending = false;
log("cancel.", this);
this.m_respFunc = null;
if (!status)
status = Components.results.NS_ERROR_FAILURE;
this.m_status = status;
this.cancelAllSubRequests();
this.detachFromParent(); // detach without error
}
}
};
function calWcapNetworkRequest(channel, respFunc, bLogging) {
// this.superClass(respFunc);
this.wrappedJSObject = this;
this.m_id = generateRequestId();
this.m_channel = channel;
this.m_respFunc = respFunc;
this.m_bLogging = (bLogging === undefined ? true : bLogging);
}
// subClass(calWcapNetworkRequest, calWcapRequest);
calWcapNetworkRequest.prototype = {
m_id: 0,
m_channel: null,
m_respFunc: null,
m_bLogging: false,
m_isPending: true,
get isPending() { return this.m_isPending; },
toString: function calWcapNetworkRequest_toString() {
var ret = ("calWcapNetworkRequest id=" + this.id +
", parent-id=" +
(this.parentRequest ? this.parentRequest.id : "<none>"));
if (this.m_bLogging)
ret += (" (" + this.m_channel.URI.spec + ")");
return ret;
},
m_parentRequest: null,
get parentRequest() { return this.m_parentRequest; },
set parentRequest(req) {
if (this.parentRequest)
logError("already has parent!", this);
this.detachFromParent(); // detach without error
this.m_parentRequest = req;
},
get id() {
return this.m_id;
},
detachFromParent: function calWcapNetworkRequest_detachFromParent(err) {
var parentRequest = this.m_parentRequest;
if (parentRequest) {
this.m_parentRequest = null;
parentRequest.detachSubRequest(this, err);
}
},
cancel: function calWcapNetworkRequest_cancel(status) {
if (this.isPending) {
this.m_isPending = false;
log("cancel.", this);
this.m_respFunc = null;
this.detachFromParent(); // detach without error
// xxx todo: check whether this works on redirected channels!
if (this.m_channel.isPending()) {
log("cancelling netwerk request...", this);
this.m_channel.cancel(NS_BINDING_FAILED);
}
}
},
execRespFunc: function calWcapNetworkRequest_execRespFunc(err, str)
{
if (this.isPending) {
this.m_isPending = false;
var respFunc = this.m_respFunc;
if (respFunc) {
this.m_respFunc = null; // call once only
if (LOG_LEVEL > 2 && this.m_bLogging) {
log("response exec: " + errorToString(err), this);
}
try {
respFunc(err, str);
err = null; // may have been handled
}
catch (exc) {
logError(exc, this);
err = exc;
}
}
this.detachFromParent(err);
}
},
// nsIUnicharStreamLoaderObserver:
onDetermineCharset: function calWcapNetworkRequest_onDetermineCharset(
loader, context, firstSegment, length)
{
var channel = null;
if (loader)
channel = loader.channel;
var charset = null;
if (channel)
charset = channel.contentCharset;
if (!charset || charset.length == 0)
charset = "UTF-8";
return charset;
},
onStreamComplete: function calWcapNetworkRequest_onStreamComplete(
loader, context, status, /* nsIUnicharInputStream */ unicharData)
{
if (LOG_LEVEL > 0 && this.m_bLogging) {
log("status: " + errorToString(status), this);
}
switch (status) {
case NS_BINDING_SUCCEEDED: {
var err = null;
var str = "";
try {
if (unicharData) {
var str_ = {};
while (unicharData.readString(-1, str_)) {
str += str_.value;
}
}
if (LOG_LEVEL > 2 && this.m_bLogging) {
log("contentCharset = " + this.onDetermineCharset(loader) +
"\nrequest result:\n" + str, this);
}
}
catch (exc) {
err = exc;
}
this.execRespFunc(err, str);
break;
}
case NS_BINDING_REDIRECTED:
case NS_BINDING_RETARGETED:
// just status
// xxx todo: in case of a redirected channel,
// how to get that channel => cancel feature!
break;
default: // errors:
this.execRespFunc(status);
break;
}
}
};
function issueNetworkRequest(parentRequest, respFunc, url, bLogging)
{
var channel;
try {
var loader = Components.classes["@mozilla.org/network/unichar-stream-loader;1"]
.createInstance(Components.interfaces.nsIUnicharStreamLoader);
channel = getIoService().newChannel(url, "" /* charset */, null /* baseURI */);
channel.loadFlags |= Components.interfaces.nsIRequest.LOAD_BYPASS_CACHE;
}
catch (exc) {
respFunc(exc);
return;
}
var netRequest = new calWcapNetworkRequest(channel, respFunc, bLogging);
parentRequest.attachSubRequest(netRequest);
log("opening channel.", netRequest);
try {
loader.init(channel, netRequest, null /*context*/, 0 /*segment size*/);
}
catch (exc) {
netRequest.execRespFunc(exc);
}
}
function getWcapRequestStatusString( xml )
{
@ -52,249 +399,34 @@ function getWcapRequestStatusString( xml )
return str;
}
// response object for Calendar.issueRequest()
function WcapResponse() {
}
WcapResponse.prototype = {
m_response: null,
m_exc: null,
get data() {
if (this.m_exc != null) {
// clear exception, so it is not thrown again on sync requests:
var exc = this.m_exc;
this.m_exc = null;
throw exc;
}
return this.m_data;
},
set data(d) {
this.m_data = d;
this.m_exc = null;
},
get exception() {
return this.m_exc;
},
set exception(exc) {
this.m_exc = exc;
}
};
function stringToIcal( data )
function stringToIcal( data, expectedErrno )
{
if (!data || data == "") { // assuming time-out
if (!data || data == "") { // assuming time-out; WTF.
throw new Components.Exception(
"Login failed. Invalid session ID.",
Components.interfaces.calIWcapErrors.WCAP_LOGIN_FAILED );
Components.interfaces.calIWcapErrors.WCAP_LOGIN_FAILED);
}
var icalRootComp = getIcsService().parseICS( data );
checkWcapIcalErrno( icalRootComp );
var icalRootComp;
try {
icalRootComp = getIcsService().parseICS(data);
}
catch (exc) { // map into more useful error string:
throw new Components.Exception("error parsing ical data!",
Components.interfaces.calIErrors.ICS_PARSE);
}
checkWcapIcalErrno(icalRootComp, expectedErrno);
return icalRootComp;
}
function stringToXml( data )
function stringToXml( data, expectedErrno )
{
if (!data || data == "") { // assuming time-out
throw new Components.Exception(
"Login failed. Invalid session ID.",
Components.interfaces.calIWcapErrors.WCAP_LOGIN_FAILED );
Components.interfaces.calIWcapErrors.WCAP_LOGIN_FAILED);
}
var xml = getDomParser().parseFromString( data, "text/xml" );
checkWcapXmlErrno( xml );
var xml = getDomParser().parseFromString(data, "text/xml");
checkWcapXmlErrno(xml, expectedErrno);
return xml;
}
function UnicharReader( receiverFunc ) {
this.wrappedJSObject = this;
this.m_receiverFunc = receiverFunc;
}
UnicharReader.prototype = {
m_receiverFunc: null,
// nsIUnicharStreamLoaderObserver:
onDetermineCharset:
function( loader, context, firstSegment, length )
{
var charset = loader.channel.contentCharset;
if (!charset || charset == "")
charset = "UTF-8";
return charset;
},
onStreamComplete:
function( loader, context, status, /* nsIUnicharInputStream */ unicharData )
{
switch (status) {
case NS_BINDING_SUCCEEDED: {
if (LOG_LEVEL > 2) {
var channel = loader.channel;
logMessage( "issueAsyncRequest( \"" +
(channel ? channel.URI.spec : "<unknown>") + "\" )",
"received stream." );
}
var str = "";
if (unicharData) {
var str_ = {};
while (unicharData.readString( -1, str_ )) {
str += str_.value;
}
}
if (LOG_LEVEL > 1) {
var channel = loader.channel;
logMessage( "issueAsyncRequest( \"" +
(channel ? channel.URI.spec : "<unknown>") + "\" )",
"contentCharset = " + loader.channel.contentCharset+
"\nrequest result:\n" + str );
}
this.m_receiverFunc( str );
break;
}
case NS_BINDING_REDIRECTED:
case NS_BINDING_RETARGETED:
// just status
break;
default: // errors:
if (LOG_LEVEL > 0) {
var channel = loader.channel;
logMessage("issueAsyncRequest( \"" +
(channel ? channel.URI.spec : "<unknown>") + "\" )",
"error: " + errorToString(status));
}
this.m_receiverFunc(""); // will lead to timeout
break;
}
}
};
function issueAsyncRequest( url, receiverFunc )
{
var reader = null;
if (receiverFunc != null) {
reader = new UnicharReader( receiverFunc );
}
var loader =
Components.classes["@mozilla.org/network/unichar-stream-loader;1"]
.createInstance(Components.interfaces.nsIUnicharStreamLoader);
logMessage( "issueAsyncRequest( \"" + url + "\" )", "opening channel." );
var channel = getIoService().newChannel(
url, "" /* charset */, null /* baseURI */ );
channel.loadFlags |= Components.interfaces.nsIRequest.LOAD_BYPASS_CACHE;
loader.init( channel, reader, null /* context */, 0 /* segment size */ );
}
function streamToString( inStream, charset )
{
if (LOG_LEVEL > 2) {
logMessage( "streamToString()",
"inStream.available() = " + inStream.available() +
", charset = " + charset );
}
// byte-array to string:
var convStream =
Components.classes["@mozilla.org/intl/converter-input-stream;1"]
.createInstance(Components.interfaces.nsIConverterInputStream);
try {
convStream.init( inStream, charset, 0, 63 /* '?' */ );
var str = "";
var str_ = {};
while (convStream.readString( -1, str_ )) {
str += str_.value;
}
}
catch (exc) {
throw new Components.Exception(
"error converting stream: " + errorToString(exc) +
"\ncharset: " + charset +
"\npartially read string: " + str, exc );
}
return str;
}
function issueSyncRequest( url, receiverFunc, bLogging )
{
if (bLogging == undefined)
bLogging = true;
if (bLogging && LOG_LEVEL > 0) {
logMessage( "issueSyncRequest( \"" + url + "\" )",
"opening channel." );
}
var channel = getIoService().newChannel(
url, "" /* charset */, null /* baseURI */ );
channel.loadFlags |= Components.interfaces.nsIRequest.LOAD_BYPASS_CACHE;
var stream = channel.open();
var status = channel.status;
if (status == Components.results.NS_OK) {
var charset = channel.contentCharset;
if (!charset || charset == "")
charset = "UTF-8";
var str = streamToString( stream, charset );
if (bLogging && LOG_LEVEL > 1) {
logMessage( "issueSyncRequest( \"" + url + "\" )",
"returned: " + str );
}
if (receiverFunc) {
receiverFunc( str );
}
return str;
}
else if (bLogging && LOG_LEVEL > 0) {
logMessage( "issueSyncRequest( \"" + url + "\" )",
"failed: " + errorToString(status) );
}
throw status;
}
function issueSyncXMLRequest( url, receiverFunc, bLogging )
{
var str = issueSyncRequest( url, null, bLogging );
var xml = getDomParser().parseFromString( str, "text/xml" );
if (receiverFunc) {
receiverFunc( xml );
}
return xml;
}
// response object for Calendar.issueRequest()
function RequestQueue() {
this.m_requests = [];
}
RequestQueue.prototype = {
m_requests: null,
m_token: 0,
postRequest:
function( func )
{
var token = this.m_token;
this.m_token += 1;
this.m_requests.push( { m_token: token, m_func: func } );
var len = this.m_requests.length;
logMessage( "RequestQueue::postRequest()",
"queueing request. token=" + token +
", open requests=" + len );
if (len == 1) {
func( token );
}
},
requestCompleted:
function( requestToken )
{
var len_ = this.m_requests.length;
this.m_requests = this.m_requests.filter(
function(x) { return x.m_token != requestToken; } );
var len = this.m_requests.length;
logMessage( "RequestQueue::requestCompleted()",
"token=" + requestToken +
((len > 0 && len_ == len) ? "(expired !!!)" : "") +
", open requests=" + len );
if (len > 0) {
var entry = this.m_requests[0];
entry.m_func( entry.m_token );
}
}
};

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -37,121 +37,212 @@
*
* ***** END LICENSE BLOCK ***** */
function logMessage( context, msg )
var g_bShutdown = false;
var g_logTimezone = null;
var g_logFilestream = null;
var g_logPrefObserver = null;
function initLogging()
{
g_logTimezone = getPref("calendar.timezone.local", null);
if (g_logFilestream) {
try {
g_logFilestream.close();
}
catch (exc) {
}
g_logFilestream = null;
}
LOG_LEVEL = getPref("calendar.wcap.log_level", 0);
if (LOG_LEVEL < 1 && getPref("calendar.debug.log", false))
LOG_LEVEL = 1; // at least basic logging when calendar.debug.log is set
if (LOG_LEVEL > 0) {
var logFileName = getPref("calendar.wcap.log_file", null);
if (logFileName) {
try {
// set up file:
var logFile = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
logFile.initWithPath(logFileName);
// create output stream:
var logFileStream =
Components.classes["@mozilla.org/network/file-output-stream;1"]
.createInstance(Components.interfaces.nsIFileOutputStream);
logFileStream.init(
logFile,
0x02 /* PR_WRONLY */ |
0x08 /* PR_CREATE_FILE */ |
0x10 /* PR_APPEND */,
0700 /* read, write, execute/search by owner */,
0 /* unused */);
g_logFilestream = logFileStream;
}
catch (exc) {
logError(exc, "init logging");
}
}
log("################################# NEW LOG #################################",
"init logging");
}
if (!g_logPrefObserver) {
g_logPrefObserver = { // nsIObserver:
observe: function logPrefObserver_observe(subject, topic, data) {
if (topic == "nsPref:changed") {
switch (data) {
case "calendar.wcap.log_level":
case "calendar.wcap.log_file":
case "calendar.debug.log":
initLogging();
break;
}
}
}
};
var prefBranch = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch2);
prefBranch.addObserver("calendar.wcap.log_level", g_logPrefObserver, false);
prefBranch.addObserver("calendar.wcap.log_file", g_logPrefObserver, false);
prefBranch.addObserver("calendar.debug.log", g_logPrefObserver, false);
var observerService = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
var appObserver = { // nsIObserver:
observe: function app_observe(subject, topic, data) {
if (topic == "quit-application")
prefBranch.removeObserver("calendar.", g_logPrefObserver);
}
};
observerService.addObserver(appObserver, "quit-application", false);
}
}
function log(msg, context, bForce)
{
if (bForce || LOG_LEVEL > 0) {
var ret = "";
if (context)
ret += ("[" + context + "]");
if (msg) {
if (ret.length > 0)
ret += "\n";
ret += msg;
}
var now = getTime();
if (LOG_TIMEZONE != null)
now = now.getInTimezone(LOG_TIMEZONE);
var str = ("\n### WCAP log " + now + "\n### [" + context + "]\n### " +
(msg ? msg : ""));
getConsoleService().logStringMessage( str );
str += "\n\n";
dump( str );
if (LOG_FILE_STREAM != null) {
if (now && g_logTimezone)
now = now.getInTimezone(g_logTimezone);
var str = ("### WCAP log entry: " + now + "\n" + ret);
getConsoleService().logStringMessage(str);
str = ("\n" + str + "\n");
dump(str);
if (g_logFilestream) {
try {
// xxx todo?
// assuming ANSI chars here, for logging sufficient:
LOG_FILE_STREAM.write( str, str.length );
g_logFilestream.write(str, str.length);
}
catch (exc) { // catching any io errors here:
var err = ("error writing log file: " + exc);
Components.utils.reportError( exc );
getConsoleService().logStringMessage( err );
dump( err + "\n\n" );
var err = ("error writing log file: " + errorToString(exc));
Components.utils.reportError(exc);
getConsoleService().logStringMessage(err);
dump(err + "\n\n");
}
}
return str;
return ret;
}
else
return msg;
}
// late-init service accessors:
function logError(err, context)
{
var msg = errorToString(err);
Components.utils.reportError( log("error: " + msg, context, true) );
return msg;
}
// late-inited service accessors:
var g_consoleService = null;
function getConsoleService()
{
if (g_consoleService == null) {
g_consoleService = Components.classes["@mozilla.org/consoleservice;1"]
.getService(Components.interfaces.nsIConsoleService);
function getConsoleService() {
if (!g_consoleService) {
g_consoleService =
Components.classes["@mozilla.org/consoleservice;1"]
.getService(Components.interfaces.nsIConsoleService);
}
return g_consoleService;
}
var g_windowWatcher = null;
function getWindowWatcher()
{
if (g_windowWatcher == null) {
function getWindowWatcher() {
if (!g_windowWatcher) {
g_windowWatcher =
Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
.getService(Components.interfaces.nsIWindowWatcher);
.getService(Components.interfaces.nsIWindowWatcher);
}
return g_windowWatcher;
}
var g_icsService = null;
function getIcsService()
{
if (g_icsService == null) {
g_icsService = Components.classes["@mozilla.org/calendar/ics-service;1"]
.getService(Components.interfaces.calIICSService);
function getIcsService() {
if (!g_icsService) {
g_icsService =
Components.classes["@mozilla.org/calendar/ics-service;1"]
.getService(Components.interfaces.calIICSService);
}
return g_icsService;
}
var g_domParser = null;
function getDomParser()
{
if (g_domParser == null) {
g_domParser = Components.classes["@mozilla.org/xmlextras/domparser;1"]
function getDomParser() {
if (!g_domParser) {
g_domParser =
Components.classes["@mozilla.org/xmlextras/domparser;1"]
.getService(Components.interfaces.nsIDOMParser);
}
return g_domParser;
}
var g_calendarManager = null;
function getCalendarManager()
{
if (g_calendarManager == null) {
function getCalendarManager() {
if (!g_calendarManager) {
g_calendarManager =
Components.classes["@mozilla.org/calendar/manager;1"]
.getService(Components.interfaces.calICalendarManager);
.getService(Components.interfaces.calICalendarManager);
}
return g_calendarManager;
};
var g_wcapBundle = null;
function getWcapBundle()
{
if (g_wcapBundle == null) {
function getWcapBundle() {
if (!g_wcapBundle) {
var stringBundleService =
Components.classes["@mozilla.org/intl/stringbundle;1"]
.getService(Components.interfaces.nsIStringBundleService);
.getService(Components.interfaces.nsIStringBundleService);
g_wcapBundle = stringBundleService.createBundle(
"chrome://calendar/locale/wcap.properties" );
"chrome://calendar/locale/wcap.properties");
}
return g_wcapBundle;
}
function getResultCode( exc )
{
return (exc instanceof Components.interfaces.nsIException
? exc.result : exc);
function subClass(subCtor, baseCtor) {
subCtor.prototype = new baseCtor();
subCtor.prototype.constructor = subCtor;
subCtor.prototype.superClass = baseCtor;
}
function testResultCode( exc, rc )
{
return (getResultCode(exc) == rc);
function qiface(list, iid) {
if (!list.some( function(i) { return i.equals(iid); } ))
throw Components.results.NS_ERROR_NO_INTERFACE;
}
function isEvent( item )
{
function isEvent(item) {
return (item instanceof Components.interfaces.calIEvent);
}
function isParent( item )
{
function isParent(item) {
if (item.id != item.parentItem.id) {
throw new Components.Exception(
"proxy has different id than its parent!");
@ -159,7 +250,7 @@ function isParent( item )
return (!item.recurrenceId);
}
function forEachIcalComponent( icalRootComp, componentType, func, maxResult )
function forEachIcalComponent(icalRootComp, componentType, func, maxResult)
{
var itemCount = 0;
// libical returns the vcalendar component if there is just
@ -182,11 +273,11 @@ function forEachIcalComponent( icalRootComp, componentType, func, maxResult )
}
}
function filterCalProps(propName, calProps)
function filterXmlNodes(name, rootNode)
{
var ret = [];
if (calProps) {
var nodeList = calProps.getElementsByTagName(propName);
if (rootNode) {
var nodeList = rootNode.getElementsByTagName(name);
for ( var i = 0; i < nodeList.length; ++i ) {
var node = nodeList.item(i);
ret.push( trimString(node.textContent) );
@ -195,20 +286,19 @@ function filterCalProps(propName, calProps)
return ret;
}
function trimString( str )
{
function trimString(str) {
return str.replace( /(^\s+|\s+$)/g, "" );
}
function getTime()
{
function getTime() {
if (g_bShutdown)
return null;
var ret = new CalDateTime();
ret.jsDate = new Date();
return ret;
}
function getIcalUTC( dt )
{
function getIcalUTC(dt) {
if (!dt)
return "0";
else {
@ -220,52 +310,63 @@ function getIcalUTC( dt )
}
}
function getDatetimeFromIcalString( val )
{
function getDatetimeFromIcalString(val) {
if (!val || val.length == 0 || val == "0")
return null;
// assuming timezone is known:
var dt = new CalDateTime();
dt.icalString = val;
// if (dt.icalString != val)
// logMessage("date-time error", dt.icalString + " vs. " + val);
if (LOG_LEVEL > 1) {
var dt_ = dt.clone();
dt_.normalize();
if (dt.icalString != val || dt_.icalString != val) {
logError(dt.icalString + " vs. " + val, "date-time error");
logError(dt_.icalString + " vs. " + val, "date-time error");
debugger;
}
}
return dt;
}
function getDatetimeFromIcalProp( prop )
{
function getDatetimeFromIcalProp(prop) {
if (!prop)
return null;
return getDatetimeFromIcalString(prop.valueAsIcalString);
}
function getPref(prefName, defaultValue)
{
function getPref(prefName, defaultValue) {
const nsIPrefBranch = Components.interfaces.nsIPrefBranch;
var prefBranch = Components.classes["@mozilla.org/preferences-service;1"]
.getService(nsIPrefBranch);
.getService(nsIPrefBranch);
var ret;
try {
switch (prefBranch.getPrefType(prefName)) {
case nsIPrefBranch.PREF_BOOL:
return prefBranch.getBoolPref(prefName);
ret = prefBranch.getBoolPref(prefName);
break;
case nsIPrefBranch.PREF_INT:
return prefBranch.getIntPref(prefName);
ret = prefBranch.getIntPref(prefName);
break;
case nsIPrefBranch.PREF_STRING:
return prefBranch.getCharPref(prefName);
ret = prefBranch.getCharPref(prefName);
break;
default:
return defaultValue;
ret = defaultValue;
break;
}
}
catch (exc) {
return defaultValue;
ret = defaultValue;
}
log(ret, "getPref(): prefName=" + prefName);
return ret;
}
function setPref(prefName, value)
{
function setPref(prefName, value) {
log(value, "setPref(): prefName=" + prefName);
const nsIPrefBranch = Components.interfaces.nsIPrefBranch;
var prefBranch = Components.classes["@mozilla.org/preferences-service;1"]
.getService(nsIPrefBranch);
.getService(nsIPrefBranch);
switch (typeof(value)) {
case "boolean":
prefBranch.setBoolPref(prefName, value);
@ -282,123 +383,3 @@ function setPref(prefName, value)
}
}
function AsyncQueue()
{
this.wrappedJSObject = this;
this.m_queue = [];
}
AsyncQueue.prototype = {
m_queue: null,
reset:
function()
{
this.m_queue = [];
},
m_proxy: null,
get proxy() {
if (!this.m_proxy) {
var eventTarget = null;
try {
var eventQueueService =
Components.classes["@mozilla.org/event-queue-service;1"]
.getService(Components.interfaces.nsIEventQueueService);
eventTarget = eventQueueService.createThreadEventQueue(
Components.classes["@mozilla.org/thread;1"]
.createInstance(Components.interfaces.nsIThread), true);
}
catch (exc) { // eventQueue has vanished on trunk:
var threadManager =
Components.classes["@mozilla.org/thread-manager;1"]
.getService(Components.interfaces.nsIThreadManager);
eventTarget = threadManager.newThread(0);
}
var proxyMgr = Components.classes["@mozilla.org/xpcomproxy;1"]
.getService(Components.interfaces.nsIProxyObjectManager);
this.m_proxy = proxyMgr.getProxyForObject(
eventTarget, Components.interfaces.nsIRunnable, this,
Components.interfaces.nsIProxyObjectManager.INVOKE_ASYNC );
}
return this.m_proxy;
},
queuedExec:
function(func)
{
this.m_queue.push(func);
if (LOG_LEVEL > 1)
logMessage("enqueued: q=" + this.m_queue.length);
if (this.m_queue.length == 1) {
this.proxy.run(); // empty queue
}
},
m_ifaces: [ Components.interfaces.nsIRunnable,
Components.interfaces.nsIClassInfo,
Components.interfaces.nsISupports ],
// nsISupports:
QueryInterface:
function( iid )
{
for each ( var iface in this.m_ifaces ) {
if (iid.equals( iface ))
return this;
}
throw Components.results.NS_ERROR_NO_INTERFACE;
},
// nsIClassInfo:
getInterfaces: function( count ) {
count.value = this.m_ifaces.length;
return this.m_ifaces;
},
get classDescription() {
return "Async Queue";
},
get contractID() {
return "@mozilla.org/calendar/calendar/wcap/async-queue;1";
},
get classID() {
return Components.ID("{C50F7442-C43E-43f6-AA3F-1ADB87E7A962}");
},
getHelperForLanguage: function( language ) { return null; },
implementationLanguage:
Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,
flags: 0,
// nsIRunnable:
run:
function() {
while (this.m_queue.length > 0) {
if (LOG_LEVEL > 1)
logMessage("queue exec: " + this.m_queue.length);
try {
this.m_queue[0]();
}
catch (exc) { // swallow all exceptions,
// they does not belong to this call
debugger;
var msg = errorToString(exc);
Components.utils.reportError(
logMessage("error: " + msg, "swallowed exception") );
}
// don't remove element unless func has been executed:
this.m_queue.shift();
if (LOG_LEVEL > 1)
logMessage("dequeued: " + this.m_queue.length);
}
}
};
function makeQueuedCall(asyncQueue, obj, func)
{
return function() {
var args = [];
for ( var i = 0; i < arguments.length; ++i )
args.push(arguments[i]);
asyncQueue.queuedExec( function() { func.apply(obj, args); } );
}
}

Просмотреть файл

@ -48,11 +48,9 @@ MODULE = wcap
XPIDL_MODULE = wcap
XPIDLSRCS = calIWcapCalendar.idl \
calIWcapErrors.idl \
calIWcapFreeBusyEntry.idl \
calIWcapFreeBusyListener.idl \
calIWcapSearchListener.idl \
calIWcapSession.idl \
calIWcapErrors.idl \
calIWcapRequest.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -39,9 +39,11 @@
#include "calICalendar.idl"
#include "calIDateTime.idl"
#include "calIWcapRequest.idl"
interface calIWcapSession;
interface calIAttendee;
/** Adds WCAP specific capabilities.
/** Adds WCAP specific capabilities to calICalendar.
*/
[scriptable, uuid(21A189DF-6C92-41f6-9E2B-1929EF25CAEE)]
interface calIWcapCalendar : calICalendar
@ -53,46 +55,75 @@ interface calIWcapCalendar : calICalendar
/**
* Current calId the calendar instance acts on; defaults to userId.
* @exception may throw an NS_ERROR_NOT_AVAILABLE of not logged in
* @exception NS_ERROR_NOT_AVAILABLE if not logged in
*/
readonly attribute string calId;
/**
* UserId of primary owner of this calendar instance.
* @exception NS_ERROR_NOT_AVAILABLE if not logged in
*/
readonly attribute string ownerId;
/**
* Determines whether this calendar instance is the user's default calendar.
* @exception NS_ERROR_NOT_AVAILABLE if not logged in
*/
readonly attribute boolean isDefaultCalendar;
/**
* Whether the currently selected calendar belongs to user.
* @exception NS_ERROR_NOT_AVAILABLE if not logged in
*/
readonly attribute boolean isOwnedCalendar;
/**
* Calendar description.
* @exception NS_ERROR_NOT_AVAILABLE if not logged in
*/
readonly attribute string description;
/**
* Calendar display name.
* @exception NS_ERROR_NOT_AVAILABLE if not logged in
*/
readonly attribute string displayName;
/**
* Gets this calendar's (calId) default timezone.
* @exception NS_ERROR_NOT_AVAILABLE if not logged in
*/
readonly attribute string defaultTimezone;
/**
* Tests whether the passed item corresponds to an invitation.
*
* @param item item to be tested
* @return whether the passed item corresponds to an invitation
*/
boolean isInvitation(in calIItemBase item);
/**
* Gets the invited attendee if the passed item corresponds to
* an invitation.
*
* @param item invitation item
* @return attendee object else null
*/
calIAttendee getInvitedAttendee(in calIItemBase item);
/**
* Gets calendar properties.
* An error is notified to all registered calIObservers, then thrown.
*
* @param propName property name (e.g. X-S1CS-CALPROPS-COMMON-NAME)
* @return array of property values
* @param count length of props array
* @param listener called with array of strings as result
* @return request object to track operation
* @exception NS_ERROR_NOT_AVAILABLE if not logged in
*/
void getCalendarProperties(
in string propName,
out unsigned long count,
[array, size_is(count), retval] out string properties );
void getCalendarProperties(in string propName,
out unsigned long count,
[array, size_is(count), retval] out string props);
/* xxx todo: additional filters sensible for calICalendar, too?
claiming bits 24-30 for now.
@ -180,12 +211,13 @@ interface calIWcapCalendar : calICalendar
* @param listener operation listener for SYNC operation
* (may optionally implemented calIObserver to receive
* onAddItem(), onModifyItem() or onDeleteItem() calls)
* @return request object to track operation
*/
void syncChangesTo(
calIWcapRequest syncChangesTo(
in calICalendar destCal,
in unsigned long itemFilter,
in calIDateTime dtFrom,
in calIOperationListener listener );
in calIOperationListener listener);
/* xxx todo:
separate out into another interface and leave only an attribute
@ -262,10 +294,11 @@ interface calIWcapCalendar : calICalendar
* if (cal.checkAccess(calIWcapCalendar.AC_PROP_WRITE))
* cal.name = newName;
*
* @exception NS_ERROR_NOT_AVAILABLE if not logged in
* @param accessControlBits access control bits (above AC_ definitions)
* @return true if access is granted, false otherwise
*/
boolean checkAccess( in unsigned long accessControlBits );
boolean checkAccess(in unsigned long accessControlBits);
/**
* Defines granted and denied permissions for a specific user or
@ -288,9 +321,12 @@ interface calIWcapCalendar : calICalendar
* - @ stands in for everybody
* xxx todo: change the above
* @param accessControlBits access control bits (above AC_ definitions)
* @param listener called when access control bits have been updated
* @return request object to track operation
*/
void defineAccessControl(
in string userId, in unsigned long accessControlBits );
calIWcapRequest defineAccessControl(
in string userId, in unsigned long accessControlBits,
in calIWcapRequestResultListener listener);
/**
* To reset a user's access control definition to the default ones
@ -299,20 +335,26 @@ interface calIWcapCalendar : calICalendar
* Components.results.NS_ERROR_INVALID_ARG is thrown.
*
* @param userId user id
* @param listener called when access control bits have been updated
* @return request object to track operation
*/
void resetAccessControl( in string userId );
calIWcapRequest resetAccessControl(
in string userId,
in calIWcapRequestResultListener listener);
/**
* Gets the set of access control definitions (including "everybody").
* Both out arrays have the same length.
*
* @param count length of returned arrays
* @param users users ids
* @param accessControlBits access control bits
*/
void getAccessControlDefinitions(
out unsigned long count,
[array, size_is(count)] out string users,
[array, size_is(count)] out unsigned long accessControlBits );
// /**
// * Gets the set of access control definitions (including "everybody").
// * Both out arrays have the same length.
// *
// * @param count length of returned arrays
// * @param users users ids
// * @param accessControlBits access control bits
// * @param listener called with xxx todo
// * @return request object to track operation
// */
// calIWcapRequest getAccessControlDefinitions(
// out unsigned long count,
// [array, size_is(count)] out string users,
// [array, size_is(count)] out unsigned long accessControlBits );
};

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -0,0 +1,87 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Sun Microsystems, Inc.
* Portions created by Sun Microsystems are Copyright (C) 2006 Sun
* Microsystems, Inc. All Rights Reserved.
*
* Original Author: Daniel Boelzle (daniel.boelzle@sun.com)
*
* Contributor(s):
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsIVariant.idl"
[scriptable, uuid(6586B48D-3FF6-4b82-B9F6-5B561D416E36)]
interface calIWcapRequest : nsISupports
{
/**
* For easy testing for equality.
*/
readonly attribute unsigned long id;
/**
* Determines whether the request is pending, i.e. has not been completed.
*/
readonly attribute boolean isPending;
/**
* Determines whether the request has succeeded, i.e. it has successfully
* been completed.
* XXX todo: remove this and favor
* !request.isPending && Components.isSuccessCode(request.status) ?
*/
readonly attribute boolean succeeded;
/**
* Status of the request, e.g. NS_OK while pending or after successful
* completion, or NS_ERROR_FAILED when failed.
*/
readonly attribute nsIVariant status;
/**
* Cancels a pending request and changes status.
*/
void cancel(in nsIVariant status);
};
[scriptable, uuid(D0BC007F-D0B5-4352-A32A-8F7A9F55A713)]
interface calIWcapRequestResultListener : nsISupports
{
/**
* Callback receiving results.
*
* @param request object to track operation
* @param result request result or null in case of an error
*/
void onRequestResult(in calIWcapRequest request,
in nsIVariant result);
};

Просмотреть файл

Просмотреть файл

@ -38,9 +38,8 @@
* ***** END LICENSE BLOCK ***** */
#include "calIWcapCalendar.idl"
#include "calIWcapFreeBusyListener.idl"
#include "calIWcapSearchListener.idl"
#include "calIDuration.idl"
#include "calIDateTime.idl"
#include "calIWcapRequest.idl"
/**
* WCAP session.
@ -49,14 +48,13 @@
interface calIWcapSession : nsISupports
{
/**
* Setting this URI causes the session to be disconnected.
* Setting this URI causes the session to logged out and disconnected.
*/
attribute nsIURI uri;
/**
* User that has established this session.
* Reading this attribute prompts for login if the session has not yet
* been established.
* @exception NS_ERROR_NOT_AVAILABLE if not logged in
*/
readonly attribute string userId;
@ -65,67 +63,12 @@ interface calIWcapSession : nsISupports
* Does _not_ check whether the user's ticket has timed out!
*/
readonly attribute boolean isLoggedIn;
/**
* 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.
* UI will prompt for a userId and password.
*/
void login();
/**
* Explicitly performs a session logout.
* Commonly not needed, because the user will be logged out upon
* "network:offline-about-to-go-offline" and "quit-application"
* automatically.
*/
void logout();
/**
* Gets a text for an error code.
*
* @param rc error code defined in calIWcapErrors
* @return error string
* @exception NS_ERROR_INVALID_ARG
*/
string getWcapErrorString( in unsigned long rc );
/**
* The user's default calendar.
* Gets the default calendar instance of this session.
*/
readonly attribute calIWcapCalendar defaultCalendar;
/**
* Gets a calendar instance for the passed calId using this session.
*
* @param calId full calId (incl. "<user>:")
* @return calendar instance
*/
calIWcapCalendar getCalendarByCalId( in string calId );
/**
* Gets calendars where the user is the primary owner
* (including default calendar).
*
* @return array of owned calendars
*/
void getOwnedCalendars(
out unsigned long count,
[array, size_is(count), retval] out calIWcapCalendar ownedCals );
/**
* Gets subscribed calendars (may include calendars where the user
* is the primary owner).
*
* @return array of subscribed calendars
*/
void getSubscribedCalendars(
out unsigned long count,
[array, size_is(count), retval] out calIWcapCalendar subscribedCals );
/**
* Specifies how to match the searchString.
*/
@ -143,113 +86,36 @@ interface calIWcapSession : nsISupports
/* 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.
* Results are notified to the passed listener instance as
* an array of calendar instances.
* The maximum 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
* @param listener listener called with an array of calIWcapCalendar objects
* @return request object to track operation
*/
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.
*
* @param calId calendar's calId (portion);
* without user's id, e.g. "test-cal".
* valid characters for the calId parameter are:
* - Alphabet characters (A-Z, a-z)
* - Numeric characters (0-9)
* - Three special characters
* - Dash (-)
* - Underscore (_)
* - Period (.)
* @param name calendar's name, e.g. "My Work Cal"
* @return created calendar
*/
calIWcapCalendar createCalendar( in string calId, in string name );
/**
* Deletes a calendar. Don't do any further calls on the deleted instance.
*
* @param cal calendar to be deleted
*/
void deleteCalendar( in calIWcapCalendar cal );
/**
* Subscribe to calendar(s).
*
* @param count length of cals
* @param calendars array of cals
*/
void subscribeToCalendars(
in unsigned long count,
[array, size_is(count)] in calIWcapCalendar cals );
/**
* Unsubscribe from calendar(s).
*
* @param count length of cals
* @param calendars array of cals
*/
void unsubscribeFromCalendars(
in unsigned long count,
[array, size_is(count)] in calIWcapCalendar cals );
/**
* Gets the user's preferences.
*
* @param prefName preference name
* @return array of preference values
*/
void getUserPreferences(
in string prefName,
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 );
calIWcapRequest searchForCalendars(in string searchString,
in unsigned long searchOptions,
in calIWcapRequestResultListener listener);
/* xxx todo freebusy: separate into own interface? */
/**
* Gets free-busy entries for calid.
* Gets free-busy entries for calendar.
* Results are notified to the passed listener instance.
* An error is notified to all registered calIObservers and
* to calIWcapFreeBusyListener::onGetFreeBusyTimes with rc != NS_OK.
*
* @param calId a calid or "mailto:rfc822addr"
* @param dtRangeStart start time of free-busy search
* @param dtRangeEnd end time of free-busy search
* @param bBusyOnly whether to return busy entries only
* @param listener listener receiving results
* @param requestId request id to distinguish asynchronous requests
* @param calId calid or rfc822addr
* @param rangeStart start time of free-busy search
* @param rangeEnd end time of free-busy search
* @param bBusy whether to return busy entries or free entries
* @param listener called with an array of calIPeriod objects
* @return request object to track operation
*/
void getFreeBusyTimes(
in string calId,
in calIDateTime dtRangeStart,
in calIDateTime dtRangeEnd,
in boolean bBusyOnly,
in calIWcapFreeBusyListener listener,
in boolean bAsync,
in unsigned long requestId );
calIWcapRequest getFreeBusyTimes(in string calId,
in calIDateTime rangeStart,
in calIDateTime rangeEnd,
in boolean bBusy,
in calIWcapRequestResultListener listener);
};