This commit is contained in:
daniel.boelzle%sun.com 2006-07-26 15:14:28 +00:00
Родитель 05e25abc44
Коммит 314b11b563
9 изменённых файлов: 198 добавлений и 123 удалений

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

@ -44,7 +44,7 @@ accessingServerFailedError.text=Cannot access server %1$S!
mandatoryHttpsError.text=Server %1$S needs to support HTTPS!
# args: host
noHttpsConfirmation.text=Unsecure login on %1$S. Continue?
noHttpsConfirmation.text=Insecure login on %1$S. Continue?
noHttpsConfirmation.label=Warning!
# args: host

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

@ -189,25 +189,43 @@ calWcapCalendar.prototype = {
m_session: null,
get session() { return this.m_session; },
m_calId: null,
get calId() {
var userId = this.session.userId; // assure being logged in
return this.m_calId || userId;
},
// 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_overriddencalId: null,
m_calId: null,
get calId() {
return this.m_overriddencalId || this.calId_;
},
get calId_() { // the original (static) calId of this calendar
var userId = this.session.userId; // assure being logged in
return this.m_calId || userId;
},
set calId( id ) {
this.log( "setting calId to " + id );
this.m_calId = id;
this.log( "overriding calId to " + id );
this.m_overriddencalId = id;
},
get description() {
var ar = this.getCalendarProperties("X-NSCP-CALPROPS-DESCRIPTION", {});
if (ar.length < 1) {
return this.calId; // fallback
// fallback to display name:
return this.displayName;
}
return ar[0];
},
get displayName() {
var ar = this.getCalendarProperties("X-NSCP-CALPROPS-NAME", {});
if (ar.length < 1) {
// fallback to common name:
ar = this.getCalendarProperties(
"X-S1CS-CALPROPS-COMMON-NAME", {});
if (ar.length < 1) {
return this.calId_; // fallback, xxx todo calId_
}
}
return ar[0];
},
@ -239,7 +257,9 @@ calWcapCalendar.prototype = {
try {
if (this.m_calProps == null) {
var url = this.session.getCommandUrl( "get_calprops" );
url += ("&calid=" + encodeURIComponent(this.calId));
// xxx todo: for now this alwas gets the description of
// the original calId_
url += ("&calid=" + encodeURIComponent(this.calId_));
url += "&fmt-out=text%2Fxml";
var this_ = this;
function resp( wcapResponse ) {

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

@ -226,8 +226,8 @@ calWcapCalendar.prototype.getStoreUrl = function( item )
case "FINAL": url += "&status=7"; break;
default:
url += "&status=3"; // NEEDS-ACTION
this.logError( "getStoreUrl(): unexpected item status=" +
item.status );
// this.logError( "getStoreUrl(): unexpected item status=" +
// item.status );
break;
}
}
@ -281,8 +281,8 @@ calWcapCalendar.prototype.getStoreUrl = function( item )
var attendees = item.getAttendees({});
var forceRSVP = false;
var dtstart;
var dtend; // for alarmRelated
var dtstart = null;
var dtend = null; // for alarmRelated
if (bIsEvent) {
if (attendees != null && attendees.length > 0) {
@ -320,25 +320,17 @@ calWcapCalendar.prototype.getStoreUrl = function( item )
url += "&isAllDay=1";
}
else { // calITodo:
// xxx todo:
// dtstart and due are mandatory for cs, so if those are
// undefined, assume an allDay todo:
// xxx todo: dtstart is mandatory for cs, so if this is
// undefined, assume an allDay todo???
dtstart = item.entryDate;
if (!dtstart) {
dtstart = getTime();
dtstart.isDate = true; // => all day
}
dtend = item.dueDate;
if (!dtend) {
// xxx todo:
this.logError( "getStoreUrl(): no sensible default for due date!" );
dtend = dtstart; // is due today
}
url += ("&due=" + getIcalUTC(dtend));
if (dtend) {
url += ("&due=" + getIcalUTC(dtend));
// url += ("&X-NSCP-DUE-TZID=" + encodeURIComponent(
// this.getAlignedTimezone(dtend.timezone)));
}
// xxx todo: missing duration
if (dtstart.isDate)
if (dtstart && dtstart.isDate)
url += "&isAllDay=1";
if (item.isCompleted)
url += "&percent=100";
@ -355,43 +347,52 @@ calWcapCalendar.prototype.getStoreUrl = function( item )
// xxx todo: sentBy sentUID fields in cs: missing in cal api
}
// important to provide tz info with entry date for proper
// occurrence calculation (daylight savings)
url += ("&dtstart=" + getIcalUTC(dtstart));
// xxx todo: setting X-NSCP- does not work.
// i.e. no separate tz for start/end. WTF.
if (dtstart) {
// important to provide tz info with entry date for proper
// occurrence calculation (daylight savings)
url += ("&dtstart=" + getIcalUTC(dtstart));
// xxx todo: setting X-NSCP- does not work.
// i.e. no separate tz for start/end. WTF.
// url += ("&X-NSCP-DTSTART-TZID=" +
// encodeURIComponent(this.getAlignedTimezone(dtstart.timezone)));
// currently the only way to influence X-NSCP-DTSTART-TZID:
url += ("&tzid=" + encodeURIComponent(
this.getAlignedTimezone(dtstart.timezone)));
// currently the only way to influence X-NSCP-DTSTART-TZID:
url += ("&tzid=" + encodeURIComponent(
this.getAlignedTimezone(dtstart.timezone)));
}
// alarm support:
var alarmOffset = item.alarmOffset;
if (alarmOffset) {
var alarmStart;
var alarmStart = null;
if (item.alarmRelated ==
Components.interfaces.calIItemBase.ALARM_RELATED_END) {
alarmStart = dtend.clone();
alarmOffset = alarmOffset.clone();
alarmOffset.isNegative = !alarmOffset.isNegative;
if (!dtend)
this.logError("no end date (no end nor due) for alarm!");
else {
alarmStart = dtend.clone();
alarmOffset = alarmOffset.clone();
alarmOffset.isNegative = !alarmOffset.isNegative;
}
}
else
else if (dtstart)
alarmStart = dtstart.clone(); // default
alarmStart.addDuration(alarmOffset);
var zalarmStart = getIcalUTC(alarmStart);
url += ("&alarmStart=" + zalarmStart);
// xxx todo: verify ;-separated addresses
url += "&alarmEmails=";
if (item.hasProperty( "alarmEmailAddress" )) {
url += encodeURIComponent( item.getProperty("alarmEmailAddress") );
if (alarmStart != null) {
alarmStart.addDuration(alarmOffset);
var zalarmStart = getIcalUTC(alarmStart);
url += ("&alarmStart=" + zalarmStart);
// xxx todo: verify ;-separated addresses
url += "&alarmEmails=";
if (item.hasProperty( "alarmEmailAddress" )) {
url += encodeURIComponent(
item.getProperty("alarmEmailAddress") );
}
else {
// xxx todo: popup exor emails can be currently specified...
url += ("&alarmPopup=" + zalarmStart);
}
// xxx todo: missing: alarm triggers for flashing, etc.
}
else {
// xxx todo: popup exor emails can be currently specified...
url += ("&alarmPopup=" + zalarmStart);
}
// xxx todo: missing: alarm triggers for flashing, etc.
}
else {
// clear alarm:

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

@ -113,7 +113,7 @@ var calWcapCalendarModule = {
// break;
default:
cal = new calWcapCalendar(
null /* calId: indicates default calendar */,
null /* calId: null indicates default calendar */,
new calWcapSession() );
cal.session.defaultCalendar = cal;
break;

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

@ -202,7 +202,7 @@ function errorToString( err )
return wcapErrorToString(err);
}
catch (exc) {
return ("[" + err + "] Unknown error code.");
return ("[" + err + "] Unknown error.");
}
}
}

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

@ -306,53 +306,77 @@ calWcapSession.prototype = {
}
if (this.m_sessionId == null || this.m_sessionId == timedOutSessionId) {
// xxx todo: ask dmose how to do better...
// possible HACK here, because of lack of sync possibilities:
// when we run into executing dialogs, the js runtime
// concurrently executes (another getItems() request).
// That concurrent request needs to wait for the first login
// attempt to finish.
// Creating a thread event queue somehow hinders the js engine
// from scheduling another js execution.
// sync all execution for login to UI thread, using nsIRunnable:
// change from MOZILLA_1_8_BRANCH->TRUNK: probe xxx todo: test
var eventQueueService =
Components.classes["@mozilla.org/event-queue-service;1"]
.getService(Components.interfaces.nsIEventQueueService);
var eventQueue = eventQueueService.pushThreadEventQueue();
try {
if (this.m_sessionId == null ||
this.m_sessionId == timedOutSessionId)
{
if (timedOutSessionId != null) {
this.m_sessionId = null;
this.log( "session timeout; prompting to reconnect." );
var prompt = getWindowWatcher().getNewPrompter(null);
var bundle = getBundle();
if (!prompt.confirm(
bundle.GetStringFromName(
"reconnectConfirmation.label" ),
bundle.formatStringFromName(
"reconnectConfirmation.text",
[this.uri.hostPort], 1 ) )) {
this.m_bNoLoginsAnymore = true;
var target; // eventQueue or eventTarget
if (eventQueueService == null) {
// we are on the TRUNK:
var threadManager =
Components.classes["@mozilla.org/thread-manager;1"]
.getService(Components.interfaces.nsIThreadManager);
target = threadManager.mainThread;
}
else {
target = eventQueueService.getSpecialEventQueue(
Components.interfaces.
nsIEventQueueService.UI_THREAD_EVENT_QUEUE );
}
var proxyObjectManager =
Components.classes["@mozilla.org/xpcomproxy;1"]
.getService(Components.interfaces.nsIProxyObjectManager);
var this_ = this;
var proxy = proxyObjectManager.getProxyForObject(
target, Components.interfaces.nsIRunnable,
{ // need to implemented QueryInterface, because object param
// is not associated with iid:
QueryInterface: function( iid ) {
if (Components.interfaces.nsIRunnable.equals(iid) ||
Components.interfaces.nsISupports.equals(iid))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
},
// nsIRunnable:
run: function() {
if (this_.m_sessionId == null ||
this_.m_sessionId == timedOutSessionId)
{
if (timedOutSessionId != null) {
this_.m_sessionId = null;
this_.log( "session timeout; " +
"prompting to reconnect." );
var prompt =
getWindowWatcher().getNewPrompter(null);
var bundle = getBundle();
if (!prompt.confirm(
bundle.GetStringFromName(
"reconnectConfirmation.label" ),
bundle.formatStringFromName(
"reconnectConfirmation.text",
[this_.uri.hostPort], 1 ) )) {
this_.m_bNoLoginsAnymore = true;
}
}
if (!this_.m_bNoLoginsAnymore)
this_.getSessionId_();
this_.getSupportedTimezones(true /* refresh */);
this_.getServerTimeDiff(true /* refresh */);
// preread calprops for subscribed calendars:
var cals = this_.getSubscribedCalendars({});
for each ( cal in cals ) {
cal.getCalProps_(true /* async */);
}
}
}
if (!this.m_bNoLoginsAnymore)
this.getSessionId_();
this.getSupportedTimezones( true /* refresh */ );
this.getServerTimeDiff( true /* refresh */ );
// preread calprops for subscribed calendars:
var cals = this.getSubscribedCalendars({});
for each ( cal in cals ) {
cal.getCalProps_(true /* async */);
}
}
}
catch (exc) {
eventQueueService.popThreadEventQueue( eventQueue );
throw exc;
}
eventQueueService.popThreadEventQueue( eventQueue );
},
Components.interfaces.nsIProxyObjectManager.INVOKE_SYNC );
// xxx todo: are rc/exceptions forwarded to current thread?
proxy.run();
}
if (this.m_sessionId == null) {
throw Components.interfaces.calIWcapErrors.WCAP_LOGIN_FAILED;
@ -703,7 +727,9 @@ calWcapSession.prototype = {
m_userId: null,
get userId() { return this.m_userId; },
get isLoggedIn() { return this.m_sessionId != null; },
login:
function()
{
@ -733,11 +759,13 @@ calWcapSession.prototype = {
}
this.m_userId = null;
// ask next time we log in:
var this_ = this;
g_httpHosts = g_httpHosts.filter(
function(hostEntry) {
return (hostEntry.m_host != this_.uri.hostPort); } );
this.m_bNoLoginsAnymore = false;
if (this.uri != null) {
var this_ = this;
g_httpHosts = g_httpHosts.filter(
function(hostEntry) {
return (hostEntry.m_host != this_.uri.hostPort); } );
}
},
getWcapErrorString:
@ -747,7 +775,7 @@ calWcapSession.prototype = {
},
get defaultCalendar() {
return this.getCalendarByCalId(this.userId);
return this.getCalendarByCalId(null);
},
set defaultCalendar(cal) {
this.m_defaultCalendar = cal;
@ -758,20 +786,21 @@ calWcapSession.prototype = {
getCalendarByCalId:
function( calId )
{
var ret;
if (calId == null || this.userId == calId) {
if (this.m_defaultCalendar == null)
this.m_defaultCalendar = new calWcapCalendar(this.userId);
return this.m_defaultCalendar;
this.m_defaultCalendar = new calWcapCalendar(this.userId, this);
ret = this.m_defaultCalendar;
}
else {
var key = encodeURIComponent(calId);
var ret = this.m_calIdToCalendar[key];
ret = this.m_calIdToCalendar[key];
if (!ret) {
ret = new calWcapCalendar( calId, this );
ret = new calWcapCalendar(calId, this);
this.m_calIdToCalendar[key] = ret;
}
return ret;
}
return ret;
},
getCalendars:

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

@ -117,6 +117,14 @@ function init()
logLevel = prefCalBranch.getIntPref( "wcap.log_level" );
}
catch (exc) {
var calLog = false;
try {
calLog = prefCalBranch.getBoolPref( "debug.log" );
}
catch (exc) {
}
if (calLog)
logLevel = 1; // basic logging
}
if (logLevel > LOG_LEVEL) {
LOG_LEVEL = logLevel;

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

@ -51,21 +51,26 @@ interface calIWcapCalendar : calICalendar
*/
readonly attribute calIWcapSession session;
/**
* Calendar description.
*/
readonly attribute string description;
/**
* Current calId the calendar instance acts on; defaults to userId.
*/
/*readonly xxx todo*/ attribute string calId;
readonly attribute string calId;
/**
* Whether the currently selected calendar belongs to user.
*/
readonly attribute boolean isOwnedCalendar;
/**
* Calendar description.
*/
readonly attribute string description;
/**
* Calendar display name.
*/
readonly attribute string displayName;
// /**
// * Gets or sets this calendar's (calId) default timezone.
// */
@ -93,30 +98,35 @@ interface calIWcapCalendar : calICalendar
* user and the current user has declined the invitation.
*/
const unsigned long ITEM_FILTER_REPLY_DECLINED = 1 << 24;
/**
* Scope: Attendee
* The event or todo is an invitation from another
* user and the current user has accepted the invitation.
*/
/**
* Scope: Attendee
* The event or todo is an invitation from another
* user and the current user has accepted the invitation.
*/
const unsigned long ITEM_FILTER_REPLY_ACCEPTED = 1 << 25;
/**
* Scope: Organizer
* The event or todo is an invitation from the current
* user to other invitees, and all invitees have replied.
*/
const unsigned long ITEM_FILTER_REQUEST_COMPLETED = 1 << 26;
/**
* Scope: Attendee
* The event or todo is an invitation from another
* user and the current user has not replied to it yet.
* */
*/
const unsigned long ITEM_FILTER_REQUEST_NEEDS_ACTION = 1 << 27;
/**
* Scope: Attendee
* The event or todo is an invitation from another
* user and the current user is not required to reply.
*/
const unsigned long ITEM_FILTER_REQUEST_NEEDSNOACTION = 1 << 28;
/**
* Scope: Organizer
* The event or todo is an invitation from the current
@ -124,13 +134,14 @@ interface calIWcapCalendar : calICalendar
* process of sending out invitations.
*/
const unsigned long ITEM_FILTER_REQUEST_PENDING = 1 << 29;
/**
* Scope: Organizer
* The event or todo is an invitation from the current
* user to other invitees, and is currently awaiting.
*/
const unsigned long ITEM_FILTER_REQUEST_WAITFORREPLY = 1 << 30;
/* xxx todo sync feature: separate into own interface? */
/** xxx todo: to be moved to calIOperationListener?

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

@ -58,12 +58,18 @@ interface calIWcapSession : nsISupports
* An error is notified to all registered calIObservers, then thrown.
*/
readonly attribute string userId;
/**
* Determines whether the user is currentl logged in.
* Does _not_ check whether the user's ticket has timed out!
*/
readonly attribute boolean isLoggedIn;
/**
* Explicitly performs a session establishment.
* Commonly not needed, because any attempt to get a calendar instance
* will establish a session automatically.
* If the user is alread logged in, she will be logged out before.
* If the user is already logged in, she will be logged out before.
* UI will prompt for a userId and password.
* An error is notified to all registered calIObservers, then thrown.
*/