зеркало из https://github.com/mozilla/pjs.git
Bug 340949: fixing attendee partstat UPDATE, empty VCALENDAR problem, orgUID, minor bugs, changing resource ids
This commit is contained in:
Родитель
ae54000881
Коммит
ad2bdcb6c1
|
@ -45,7 +45,7 @@ mandatoryHttpsError.text=Server %1$S needs to support HTTPS!
|
|||
|
||||
# args: host
|
||||
noHttpsConfirmation.text=Insecure login on %1$S! Server does not support HTTPS. Continue?
|
||||
noHttpsConfirmation.check=Don't ask again.
|
||||
noHttpsConfirmation.check.text=Don't ask again.
|
||||
noHttpsConfirmation.label=Warning!
|
||||
|
||||
# args: host
|
||||
|
@ -57,9 +57,9 @@ insufficientWcapVersionError.text=Server %1$S (%2$S, v%3$S) has insufficient WCA
|
|||
|
||||
# args: host, prodId, serverVersion, wcapVersion
|
||||
loginDialog.text=Server: %1$S (%2$S, v%3$S, WCAP v%4$S)
|
||||
loginDialog.savePW.label=Save Password
|
||||
loginDialog.check.text=Save Password
|
||||
loginDialog.label=Sun Java System Calendar Server WCAP login
|
||||
|
||||
privateItem.title=Private
|
||||
confidentialItem.title=Confidential
|
||||
busyItem.title=Busy
|
||||
privateItem.title.text=Private
|
||||
confidentialItem.title.text=Confidential
|
||||
busyItem.title.text=Busy
|
||||
|
|
|
@ -116,8 +116,7 @@ calWcapCalendar.prototype = {
|
|||
function()
|
||||
{
|
||||
var str = this.session.toString();
|
||||
if (this.calId != this.session.userId)
|
||||
str += (", calId=" + this.calId);
|
||||
str += (", calId=" + this.calId);
|
||||
return str;
|
||||
},
|
||||
log:
|
||||
|
@ -184,8 +183,7 @@ calWcapCalendar.prototype = {
|
|||
|
||||
// xxx todo: rework like in
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=257428
|
||||
m_bSuppressAlarms: true /* xxx todo:
|
||||
off for now until all problems are solved */,
|
||||
m_bSuppressAlarms: false,
|
||||
get suppressAlarms() {
|
||||
return (this.m_bSuppressAlarms || this.readOnly);
|
||||
},
|
||||
|
@ -209,18 +207,28 @@ calWcapCalendar.prototype = {
|
|||
// 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( "overriding calId to " + id );
|
||||
this.m_overriddencalId = id;
|
||||
this.log( "setting calId to " + id );
|
||||
this.m_calId = id;
|
||||
// refresh calprops:
|
||||
this.m_calProps = null;
|
||||
this.getCalProps_( true /* async */ );
|
||||
},
|
||||
|
||||
get ownerId() {
|
||||
var ar = this.getCalendarProperties("X-NSCP-CALPROPS-PRIMARY-OWNER",{});
|
||||
if (ar.length < 1) {
|
||||
this.notifyError(
|
||||
"cannot determine primary owner of calendar " + this.calId );
|
||||
// fallback to userId:
|
||||
return this.session.userId;
|
||||
}
|
||||
return ar[0];
|
||||
},
|
||||
|
||||
get description() {
|
||||
|
@ -239,16 +247,16 @@ calWcapCalendar.prototype = {
|
|||
ar = this.getCalendarProperties(
|
||||
"X-S1CS-CALPROPS-COMMON-NAME", {});
|
||||
if (ar.length < 1) {
|
||||
return this.calId_; // fallback, xxx todo calId_
|
||||
return this.calId;
|
||||
}
|
||||
}
|
||||
return ar[0];
|
||||
},
|
||||
|
||||
get isOwnedCalendar() {
|
||||
var userId = this.session.userId;
|
||||
return (this.calId == userId ||
|
||||
this.calId.indexOf(userId + ":") == 0);
|
||||
var ownerId = this.ownerId;
|
||||
return (this.calId == ownerId ||
|
||||
this.calId.indexOf(ownerId + ":") == 0);
|
||||
},
|
||||
|
||||
getCalendarProperties:
|
||||
|
@ -272,9 +280,7 @@ calWcapCalendar.prototype = {
|
|||
try {
|
||||
if (this.m_calProps == null) {
|
||||
var url = this.session.getCommandUrl( "get_calprops" );
|
||||
// xxx todo: for now this alwas gets the description of
|
||||
// the original calId_
|
||||
url += ("&calid=" + encodeURIComponent(this.calId_));
|
||||
url += ("&calid=" + encodeURIComponent(this.calId));
|
||||
url += "&fmt-out=text%2Fxml";
|
||||
var this_ = this;
|
||||
function resp( wcapResponse ) {
|
||||
|
|
|
@ -191,7 +191,7 @@ calWcapCalendar.prototype.getRecurrenceParams = function(
|
|||
}
|
||||
};
|
||||
|
||||
calWcapCalendar.prototype.getStoreUrl = function( item )
|
||||
calWcapCalendar.prototype.getStoreUrl = function( item, oldItem )
|
||||
{
|
||||
var bIsEvent = isEvent(item);
|
||||
var url = this.session.getCommandUrl( bIsEvent ? "storeevents"
|
||||
|
@ -199,12 +199,10 @@ calWcapCalendar.prototype.getStoreUrl = function( item )
|
|||
url += "&fetch=1&compressed=1&recurring=1";
|
||||
url += ("&calid=" + encodeURIComponent(this.calId));
|
||||
|
||||
// it is always safe to use orgCalId,
|
||||
// because every user has a calId == userId
|
||||
var orgCalid = ((item.organizer == null || item.organizer.id == null)
|
||||
? this.calId // sensible default
|
||||
: item.organizer.id);
|
||||
url += ("&orgCalid=" + encodeURIComponent(orgCalid));
|
||||
var ownerId = this.ownerId;
|
||||
var orgUID = ((item.organizer == null || item.organizer.id == null)
|
||||
? ownerId : item.organizer.id);
|
||||
url += ("&orgUID=" + encodeURIComponent(orgUID));
|
||||
|
||||
// xxx todo: default prio is 0 (5 in sjs cs)
|
||||
url += ("&priority=" + item.priority);
|
||||
|
@ -277,40 +275,10 @@ calWcapCalendar.prototype.getStoreUrl = function( item )
|
|||
url += encodeURIComponent( item.getProperty( "URL" ) );
|
||||
}
|
||||
|
||||
// attendees:
|
||||
var attendees = item.getAttendees({});
|
||||
var forceRSVP = false;
|
||||
|
||||
var dtstart = null;
|
||||
var dtend = null; // for alarmRelated
|
||||
|
||||
if (bIsEvent) {
|
||||
if (attendees != null && attendees.length > 0) {
|
||||
// ORGANIZER is this cal?
|
||||
if (orgCalid == this.calId) {
|
||||
url += "&method=2"; // REQUEST
|
||||
forceRSVP = true;
|
||||
}
|
||||
else {
|
||||
var userId = this.session.userId;
|
||||
if (userId == null)
|
||||
userId = this.calId; // fallback
|
||||
var i = 0;
|
||||
for ( ; i < attendees.length; ++i ) {
|
||||
if (attendees[i].id == userId) {
|
||||
// REPLY for just this user:
|
||||
url += "&method=4";
|
||||
attendees = [ attendees[i] ];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= attendees.length) {
|
||||
// user not in list, don't write attendee list:
|
||||
attendees = null;
|
||||
}
|
||||
}
|
||||
} // else just PUBLISH (default)
|
||||
|
||||
dtstart = item.startDate;
|
||||
var dtend = item.endDate;
|
||||
url += ("&dtend=" + getIcalUTC(dtend));
|
||||
|
@ -407,14 +375,53 @@ calWcapCalendar.prototype.getStoreUrl = function( item )
|
|||
}
|
||||
|
||||
// attendees:
|
||||
url += "&attendees=";
|
||||
if (attendees != null) {
|
||||
for ( var i = 0; i < attendees.length; ++i ) {
|
||||
if (i > 0)
|
||||
url += ";";
|
||||
url += this.encodeAttendee( attendees[i], forceRSVP );
|
||||
var attendees = item.getAttendees({});
|
||||
if (attendees.length > 0) {
|
||||
// ORGANIZER is owner fo this cal?
|
||||
if (!oldItem || orgUID == ownerId) {
|
||||
url += "&method=2"; // REQUEST
|
||||
url += "&attendees=";
|
||||
for ( var i = 0; i < attendees.length; ++i ) {
|
||||
if (i > 0)
|
||||
url += ";";
|
||||
url += this.encodeAttendee( attendees[i], true /*forceRSVP*/ );
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // attendee's calendar:
|
||||
var attendee = item.getAttendeeById(ownerId);
|
||||
if (attendee == null) {
|
||||
this.logError( "not in attendee list, but in my cal?" );
|
||||
}
|
||||
else {
|
||||
this.log( "attendee: " + attendee.icalProperty.icalString );
|
||||
var oldAttendee = oldItem.getAttendeeById(ownerId);
|
||||
if (!oldAttendee ||
|
||||
attendee.participationStatus !=
|
||||
oldAttendee.participationStatus) {
|
||||
// REPLY for just this calendar owner:
|
||||
url += "&method=4";
|
||||
url += ("&attendees=PARTSTAT=" +
|
||||
attendee.participationStatus);
|
||||
url += ("^" + ownerId);
|
||||
}
|
||||
else {
|
||||
// UPDATE attendee's copy of item:
|
||||
url += "&method=256";
|
||||
}
|
||||
}
|
||||
}
|
||||
} // else use just PUBLISH (method=1)
|
||||
|
||||
// xxx todo: however, sometimes socs just returns an empty calendar when
|
||||
// nothing or only optional props like attendee ROLE has changed,
|
||||
// although fetch=1.
|
||||
// This also occurs when the event organizer is in the attendees
|
||||
// list and switches its PARTSTAT too often...
|
||||
// hack: ever changing dummy prop, then the cs engine seems to write
|
||||
// every time. WTF.
|
||||
url += ("&X-MOZ-WCAP-DUMMY=" +
|
||||
"X-NSCP-ORIGINAL-OPERATION=X-NSCP-WCAP-PROPERTY-REPLACE^" +
|
||||
getIcalUTC(getTime()));
|
||||
|
||||
return url;
|
||||
};
|
||||
|
@ -473,7 +480,7 @@ calWcapCalendar.prototype.adoptItem = function( item, iListener )
|
|||
// will most probably lead to error => existing parent
|
||||
}
|
||||
|
||||
var url = this.getStoreUrl( item );
|
||||
var url = this.getStoreUrl( item, null );
|
||||
url += this.encodeRecurrenceParams( item );
|
||||
// (WCAP_STORE_TYPE_CREATE) error if existing item:
|
||||
url += "&storetype=1";
|
||||
|
@ -503,9 +510,9 @@ calWcapCalendar.prototype.addItem = function( item, iListener )
|
|||
};
|
||||
|
||||
calWcapCalendar.prototype.modifyItem_resp = function(
|
||||
wcapResponse, newItem_, oldItem, iListener )
|
||||
wcapResponse, oldItem, iListener )
|
||||
{
|
||||
var newItem = null;
|
||||
var item = null;
|
||||
try {
|
||||
var icalRootComp = wcapResponse.data; // first statement, may throw
|
||||
|
||||
|
@ -513,26 +520,19 @@ calWcapCalendar.prototype.modifyItem_resp = function(
|
|||
icalRootComp,
|
||||
Components.interfaces.calICalendar.ITEM_FILTER_ALL_ITEMS,
|
||||
0, null, null );
|
||||
if (items.length < 1)
|
||||
throw new Error("empty VCALENDAR returned!");
|
||||
if (items.length > 1)
|
||||
this.notifyError( "unexpected number of items: " + items.length );
|
||||
if (items.length < 1) {
|
||||
// however, sometimes socs just returns an empty calendar when
|
||||
// nothing has changed, although fetch=1.
|
||||
// This also occurs when the event organizer is in the attendees
|
||||
// list and switches its PARTSTAT too often... WTF.
|
||||
this.log( "empty VCALENDAR returned!" );
|
||||
newItem = newItem_; // fallback, assuming item has been written
|
||||
}
|
||||
else
|
||||
newItem = items[0];
|
||||
item = items[0];
|
||||
|
||||
if (iListener != null) {
|
||||
iListener.onOperationComplete(
|
||||
this.superCalendar, Components.results.NS_OK,
|
||||
Components.interfaces.calIOperationListener.MODIFY,
|
||||
newItem.id, newItem );
|
||||
item.id, item );
|
||||
}
|
||||
this.notifyObservers( "onModifyItem", [newItem, oldItem] );
|
||||
this.notifyObservers( "onModifyItem", [item, oldItem] );
|
||||
// xxx todo: maybe log request status
|
||||
}
|
||||
catch (exc) {
|
||||
|
@ -540,7 +540,7 @@ calWcapCalendar.prototype.modifyItem_resp = function(
|
|||
iListener.onOperationComplete(
|
||||
this.superCalendar, Components.results.NS_ERROR_FAILURE,
|
||||
Components.interfaces.calIOperationListener.MODIFY,
|
||||
newItem == null ? null : newItem.id, exc );
|
||||
item == null ? null : item.id, exc );
|
||||
}
|
||||
this.notifyError( exc );
|
||||
}
|
||||
|
@ -557,7 +557,7 @@ calWcapCalendar.prototype.modifyItem = function(
|
|||
if (!newItem.id)
|
||||
throw new Error("new item has no id!");
|
||||
|
||||
var url = this.getStoreUrl( newItem );
|
||||
var url = this.getStoreUrl( newItem, oldItem );
|
||||
url += ("&uid=" + newItem.id);
|
||||
if (newItem.parentItem == newItem) { // is master
|
||||
// (WCAP_STORE_TYPE_MODIFY) error if not existing:
|
||||
|
@ -577,8 +577,7 @@ calWcapCalendar.prototype.modifyItem = function(
|
|||
this.session.issueAsyncRequest(
|
||||
url + "&fmt-out=text%2Fcalendar", stringToIcal,
|
||||
function( wcapResponse ) {
|
||||
this_.modifyItem_resp( wcapResponse,
|
||||
newItem, oldItem, iListener );
|
||||
this_.modifyItem_resp( wcapResponse, oldItem, iListener );
|
||||
} );
|
||||
}
|
||||
catch (exc) {
|
||||
|
@ -1239,8 +1238,8 @@ calWcapCalendar.prototype.syncChangesTo = function(
|
|||
function( item ) {
|
||||
syncState.acquire();
|
||||
this_.log( "adding " + item.id );
|
||||
// xxx todo: verify whether exceptions
|
||||
// are written:
|
||||
// xxx todo: verify whether exceptions have been
|
||||
// written
|
||||
destCal.addItem( item, addItemListener );
|
||||
} );
|
||||
} );
|
||||
|
@ -1268,7 +1267,7 @@ calWcapCalendar.prototype.syncChangesTo = function(
|
|||
modifiedItems.push( item.id );
|
||||
if (bAdd) {
|
||||
// xxx todo: verify whether exceptions
|
||||
// are written:
|
||||
// have been written
|
||||
this_.log( "adding " + item.id );
|
||||
destCal.addItem( item, addItemListener );
|
||||
}
|
||||
|
|
|
@ -183,7 +183,7 @@ function wcapErrorToString( rc )
|
|||
|
||||
function errorToString( err )
|
||||
{
|
||||
if (err instanceof String)
|
||||
if (typeof(err) == "string")
|
||||
return err;
|
||||
if (err instanceof Error)
|
||||
return err.message;
|
||||
|
|
|
@ -518,7 +518,7 @@ calWcapSession.prototype = {
|
|||
"loginDialog.label"),
|
||||
loginText, outUser, outPW,
|
||||
getWcapBundle().GetStringFromName(
|
||||
"loginDialog.savePW.label" ),
|
||||
"loginDialog.check.text"),
|
||||
savePW ))
|
||||
{
|
||||
try {
|
||||
|
@ -784,9 +784,13 @@ calWcapSession.prototype = {
|
|||
function( calId )
|
||||
{
|
||||
var ret;
|
||||
if (calId == null || this.userId == calId) {
|
||||
if (this.m_defaultCalendar == null)
|
||||
this.m_defaultCalendar = createWcapCalendar(this.userId, this);
|
||||
// xxx todo: for now the default calendar (calId=null)
|
||||
// is separated (own instance) from subscribed calendars
|
||||
if (calId == null /*|| this.userId == calId*/) {
|
||||
if (this.m_defaultCalendar == null) {
|
||||
this.m_defaultCalendar = createWcapCalendar(
|
||||
null/*this.userId*/, this);
|
||||
}
|
||||
ret = this.m_defaultCalendar;
|
||||
}
|
||||
else {
|
||||
|
@ -1053,7 +1057,7 @@ function confirmInsecureLogin( uri )
|
|||
var bConfirmed = prompt.confirmCheck(
|
||||
bundle.GetStringFromName("noHttpsConfirmation.label"),
|
||||
bundle.formatStringFromName("noHttpsConfirmation.text", [host], 1),
|
||||
bundle.GetStringFromName("noHttpsConfirmation.check"),
|
||||
bundle.GetStringFromName("noHttpsConfirmation.check.text"),
|
||||
dontAskAgain );
|
||||
|
||||
if (dontAskAgain.value) {
|
||||
|
|
|
@ -347,9 +347,11 @@ catch (exc) {
|
|||
}
|
||||
|
||||
// some string resources:
|
||||
var g_privateItemTitle = getWcapBundle().GetStringFromName("privateItem.title");
|
||||
var g_privateItemTitle = getWcapBundle().GetStringFromName(
|
||||
"privateItem.title.text");
|
||||
var g_confidentialItemTitle = getWcapBundle().GetStringFromName(
|
||||
"confidentialItem.title");
|
||||
var g_busyItemTitle = getWcapBundle().GetStringFromName("busyItem.title");
|
||||
"confidentialItem.title.text");
|
||||
var g_busyItemTitle = getWcapBundle().GetStringFromName(
|
||||
"busyItem.title.text");
|
||||
var g_busyPhantomItemUuidPrefix = ("PHANTOM_uuid" + getTime().icalString);
|
||||
|
||||
|
|
|
@ -56,6 +56,11 @@ interface calIWcapCalendar : calICalendar
|
|||
*/
|
||||
readonly attribute string calId;
|
||||
|
||||
/**
|
||||
* UserId of primary owner of this calendar instance.
|
||||
*/
|
||||
readonly attribute string ownerId;
|
||||
|
||||
/**
|
||||
* Whether the currently selected calendar belongs to user.
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче