diff --git a/ChangeLog b/ChangeLog index a0bdc0adc..da16d0ee2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,236 @@ +2011-04-28 Ludovic Marcotte + + * SoObjects/SOGo/SQLSource.{h,m}: Added resources support, + just like for LDAP-based sources. + * SoObjects/SOGo/SOGoParentFolder.m (_createPersonalFolder): + We now also autocreate database tables if the "user" + is a resource. + +2011-04-25 Francis Lachapelle + + * UI/WebServerResources/SchedulerUI.js (onFolderUnsubscribeCB): + select the personal calendar to avoid trying creating an event or + a task in the calendar to which the user has just unsubscribed. + +2011-04-25 Ludovic Marcotte + + * Added the concept of "resources" in SOGo in order + to avoid double-bookings (if not more) and also, handle + auto-accepts. This works for the web interface and + over DAV - generating 403 errors in case of a conflict. + +2011-04-21 Ludovic Marcotte + + * Added the possibility of translating IMAP namespaces + and we now extract the full name the mailbox owner under + the "Other Users" namespace. + +2011-04-21 Francis Lachapelle + + * UI/WebServerResources/SchedulerUI.js (deleteEvent): we now show + in the confirmation dialog box which events will be deleted. + + * UI/WebServerResources/generic.js (createDialog): the legend + argument can now be a string or an element. + (isWebKit): was isSafari; now consider all WebKit-based browsers together. + + * UI/WebServerResources/UIxMailToSelection.js: various + improvements to behave like in Thunderbird. + + * UI/WebServerResources/SOGoAutoCompletion.js: idem. + + * UI/WebServerResources/UIxMailEditor.js (initAddresses): was + initTabIndex. We were not handling the tab indexes properly which + was causing incorrect behavior in IE. + +2011-04-19 Wolfgang Sourdeau + + * OpenChange/MAPIStoreMailAttachment.m (-): binary properties are + represented by a struct Binary_r. + + * OpenChange/NSObject+MAPIStore.m + (-getMAPIValue:forTag:inMemCtx:): binary properties are + represented by a struct Binary_r. + + * OpenChange/MAPIStoreTypes.m (NSObjectFromMAPISPropValue) + (NSObjectFromSPropValue): we now support PT_SVREID and handle it + exactly as PT_BINARY. + + * OpenChange/MAPIStoreMessage.m (-attachmentTable): as all the + subclasses were using the same MAPIStoreAttachmentTable + implementation, this method now performs the same operation and + thereby no longer requires subclasssing. + + * OpenChange/MAPIStoreObject.m (-getProperty:withTag:): compute + the method selector and pass it as argument to the IMP of the + property getter, as would be with any regular method invocation. + + * OpenChange/MAPIStoreMailMessage.m (-getPrBody:): no longer check + the size of the returned content, as streams are now handled + internally by OpenChange. + (-getPrHtml): same as above. + + * OpenChange/MAPIStoreTypes.m (NSObjectFromStreamData): removed + helper function as it's no longer used. + + * OpenChange/MAPIStoreSOGo.m (sogo_op_set_property_from_fd) + (sogo_op_get_property_into_fd): those backend methods are no + longer used, as OpenChange handles the property streams internally + now. + + * OpenChange/gen-property-selectors.py: added code to generate + MAPIStoreSupportedProperties as the array of properties that are + handled by OpenChange and MAPIStoreSupportedPropertiesCount as the + count of those properties. + + * OpenChange/MAPIStoreObject.m (+getAvailableProperties): ObjC + corollary of the "sogo_pocop_get_available_properties" backend + method. + (-getAvailableProperties): proxy to the class method of the same + name. + + * OpenChange/MAPIStoreTable.m (+childObjectClass): new mandatory + method that returns the Class of the objects represented in the + rows of the table. + (-getAvailableProperties:): ObjC corollary of the + "sogo_pocop_get_available_table_properties" backend method. + + * OpenChange/MAPIStoreSOGo.m + (sogo_pocop_get_available_table_properties): new backend getter + that returns the list of properties that can be queried on the + table rows. + (sogo_pocop_get_available_properties): new backend getter + that returns the list of properties that can be queried on the + discrete object passed as parameter. + + * OpenChange/code-MAPIStorePropertySelectors.m + (MAPIStorePropertyGettersForClass): use the + "MAPIStoreProeprtyGetter" type rather than IMP as result type. + + * OpenChange/MAPIStoreFolderTable.m (-restrictedChildKeys): no + longer a mandatory method, returns [self childKeys] when not + overriden and issue an error message. + + * OpenChange/MAPIStoreFolder.m (-createMessage): no longer a + mandatory method. Returns nil when not overriden. + +2011-04-19 Francis Lachapelle + + * SoObjects/Appointments/SOGoAppointmentFolder.m + (-_flattenCycleRecord:forRange:intoArray:): fixed the + verification of the event's timezone. + +2011-04-15 Francis Lachapelle + + * SoObjects/Appointments/iCalEvent+SOGo.m (-firstOccurenceRange): + we now compute the end date by looking at the occurrence + interval. This way, we support events with an end date or a duration. + + * SoObjects/Appointments/SOGoAppointmentFolder.m + (-_flattenCycleRecord:forRange:intoArray:): also compute the end + date by looking at the occurrence interval. + (-importCalendar:): added a duration to events with no end date nor duration. + + * SoObjects/Appointments/SOGoAppointmentObject.m + (-_adjustEventsInRequest:): new method to verify the vCalendar for + any inconsistency or missing attributes. Currently, it only adds a + duration if no end date nor duration is found. + + * UI/WebServerResources/ckeditor/config.js: Changed the default + enter mode to use BR instead of P. This matches the behavior of Thunderbird. + +2011-04-14 Francis Lachapelle + + * UI/WebServerResources/UIxContactEditor.js + (validateContactEditor): now uses the regexp defined in generic.js + (emailRE) to validate the email addresses. This fixes an issue + with valid addresses starting with an underscore (bug #1246). + + * UI/MailerUI/UIxMailAccountActions.m (-composeAction): properly decode + submitted recipients and subjects (URL-encoded). + + * SoObjects/SOGo/SOGoUserManager.m (-getImapLoginForUID:): we now + consider the source parameter IMAPLoginFieldName. We continue to support + SOGoForceIMAPLoginWithEmail at the domain/system level. + + * SoObjects/SOGo/LDAPSource.m: we can now define a new parameter + named IMAPLoginFieldName to specify which field to use for IMAP + authentication. By default, we use the value of the UIDFieldName. + + * SoObjects/SOGo/SQLSource.m + (-checkLogin:password:perr:expire:grace:): if the defaults parameter + authenticationFilter is defined, we add it to the SQL where clause. + (_lookupContactEntry:considerEmail:): we add a new key + (canAuthenticate) to the returned dictionary that specifies if the + user can authenticate or not. We also add c_imaplogin when the + user must authenticate with a different username to the IMAP server. + + * SoObjects/SOGo/SOGoUser.m (-canAuthenticate): new method that + returns true if the user can authenticate, based on the + authentication filter associated to the source. + + * SoObjects/SOGo/SOGoGCSFolder.m (-ocsFolder): don't automatically + create the folder if the user can't authenticate. + + * UI/Contacts/UIxContactsListActions.m: was + UIxContactsListView.m. The new method contactsListAction now + returns a JSON representation of the addressbook. + + * UI/Contacts/UIxContactFoldersView.m (-personalContactInfos): new + method used to populate the wox template with the personal + addressbook. The addressbook module is now pre-loaded with it, + eliminating an Ajax query. + + * UI/WebServerResources/ContactsUI.js (initContacts): delegate + all events to the table instead of each row. + (contactsListCallback): we now receive a JSON representation of + the contacts and reuse the existing table rows instead of + overwriting the table. + +2011-04-13 Wolfgang Sourdeau + + * OpenChange/MAPIStoreObject.m: make use of the IMP cache methods + available in MAPIStorePropertySelectors to query object + properties. + * OpenChange/*{Message,Folder}.m: replaced the implementations of + -getProperty:withTag: with equivalent property getter methods. + + * OpenChange/MAPIStoreContext.m (-url): new method that returns + the context url. + + * OpenChange/gen-property-selectors.py: new generator script that + outputs MAPIStorePropertySelectors.[hm], which is a helper + module that provides methods for handling of cached + property method IMPs. + +2011-04-12 Wolfgang Sourdeau + + * SoObjects/Mailer/SOGoDraftObject.m + (-bodyPartForAttachmentWithName:): don't choose "quoted-printable" + if the mimetype is anything else than "text/plain" or "text/html", + to avoid issues with filenames attached with a wrong mime type. + +2011-04-12 Francis Lachapelle + + * SoObjects/Appointments/SOGoAppointmentFolder.m + (-importCalendar:): we now associate the proper vtimezone to each + event found in the calendar. + +2011-04-11 Francis Lachapelle + + * UI/WebServerResources/UIxMailToSelection.js + (addressFieldLostFocus): split content separated by commas + or semi-colons. + +2011-04-08 Wolfgang Sourdeau + + * Tests/Unit/TestNSString+URLEscaping.m: new test module. + (-test_stringByEscapingURL): new test method for -[NSString + stringByEscapingURL]. + + * Tests/Unit/sogo-tests.m (main): added volatile user defaults for + utf8 url encoding. + 2011-04-07 Francis Lachapelle * UI/WebServerResources/MailerUI.js (onMenuRenameFolderConfirm): diff --git a/Documentation/SOGo Installation Guide.odt b/Documentation/SOGo Installation Guide.odt index 269e39c1f..b8bce7e52 100644 Binary files a/Documentation/SOGo Installation Guide.odt and b/Documentation/SOGo Installation Guide.odt differ diff --git a/Documentation/SOGo Mobile Devices Configuration.odt b/Documentation/SOGo Mobile Devices Configuration.odt index 1d11c05f8..421f394c7 100644 Binary files a/Documentation/SOGo Mobile Devices Configuration.odt and b/Documentation/SOGo Mobile Devices Configuration.odt differ diff --git a/Documentation/SOGo Mozilla Thunderbird Configuration.odt b/Documentation/SOGo Mozilla Thunderbird Configuration.odt index 58e3172c5..23e33335f 100644 Binary files a/Documentation/SOGo Mozilla Thunderbird Configuration.odt and b/Documentation/SOGo Mozilla Thunderbird Configuration.odt differ diff --git a/NEWS b/NEWS index 0a843f23e..38c02dab8 100644 --- a/NEWS +++ b/NEWS @@ -1,7 +1,24 @@ -1.3-2011MMDD (1.3.6) +1.3-201004XX (1.3.7) +--------------------- +New Features + - IMAP namespaces are now translated and the full name of the + mailbox owner is extracted under "Other Users" + - added the "authenticationFilter" parameter for SQL-based + sources to limit who can authenticate to a local SOGo instance + - added support for resources like projectors, conference rooms + and more which allows SOGo to avoid double-booking of them + and also allows SOGo to automatically accept invitations for them + +Enhancements + +Bug Fixes + + +1.3-20110408 (1.3.6) -------------------- New Features - added Norwegian translation - thanks to Altibox + Enhancements - updated Italian translation - updated Ukranian translation @@ -14,12 +31,14 @@ Enhancements - alarms are no longer exported to DAV clients for calendars where the alarms are configured to be disabled - IMAP connection pooling is disabled by default to avoid flooding the IMAP - servers in multi-process environments + servers in multi-process environments (NGImap4DisableIMAP4Pooling now set + to "YES" by default) - sogo-tool: the remove-doubles command now makes use of the card complete - names + names - sope-appserver: added the ability to configure the minutes timeout per - request after which child processes are killed, via - WOWatchDogRequestTimeout (default: 10) + request after which child processes are killed, via + WOWatchDogRequestTimeout (default: 10) + Bug Fixes - restored the automatic expunge of IMAP folders - various mutli-domain fixes @@ -29,12 +48,12 @@ Bug Fixes - sogo-tool: now works in multi-domain environments - sogo-tool: now retrieves list of users from the folder info table - sogo-tool: the remove-doubles command is now compatible with the - synchronization mechanisms + synchronization mechanisms - sope-mime: fixed some parsing problems occurring with dbmail - sope-mime: fixed the fetching of mail body parts when other untagged - responses are received + responses are received - sope-appserver: fixed a bug leaving child processes performing the watchdog - safety belt cleanup + safety belt cleanup 1.3-20110125 (1.3.5) -------------------- diff --git a/OpenChange/GNUmakefile b/OpenChange/GNUmakefile index 8d751febe..8d8c49bb0 100644 --- a/OpenChange/GNUmakefile +++ b/OpenChange/GNUmakefile @@ -30,6 +30,7 @@ $(SOGOBACKEND)_OBJC_FILES += \ MAPIStoreAuthenticator.m \ MAPIStoreMapping.m \ MAPIStoreTypes.m \ + MAPIStorePropertySelectors.m \ \ SOGoMAPIFSFolder.m \ SOGoMAPIFSMessage.m \ diff --git a/OpenChange/GNUmakefile.preamble b/OpenChange/GNUmakefile.preamble new file mode 100644 index 000000000..74046108b --- /dev/null +++ b/OpenChange/GNUmakefile.preamble @@ -0,0 +1,5 @@ +all:: MAPIStorePropertySelectors.m MAPIStorePropertySelectors.h + +MAPIStorePropertySelectors.m MAPIStorePropertySelectors.h: gen-property-selectors.py code-MAPIStorePropertySelectors.m code-MAPIStorePropertySelectors.h + @echo " Auto-generating MAPIStorePropertySelectors.[hm]..." + @./gen-property-selectors.py -o MAPIStorePropertySelectors $(LIBMAPISTORE_CFLAGS) diff --git a/OpenChange/MAPIStoreCalendarMessage.h b/OpenChange/MAPIStoreCalendarMessage.h index 0c78c05e3..04a92712b 100644 --- a/OpenChange/MAPIStoreCalendarMessage.h +++ b/OpenChange/MAPIStoreCalendarMessage.h @@ -25,7 +25,13 @@ #import "MAPIStoreGCSMessage.h" +@class iCalEvent; + @interface MAPIStoreCalendarMessage : MAPIStoreGCSMessage +{ + iCalEvent *event; +} + @end #endif /* MAPISTORECALENDARMESSAGE_H */ diff --git a/OpenChange/MAPIStoreCalendarMessage.m b/OpenChange/MAPIStoreCalendarMessage.m index 4c26e478b..11ffcfd25 100644 --- a/OpenChange/MAPIStoreCalendarMessage.m +++ b/OpenChange/MAPIStoreCalendarMessage.m @@ -40,7 +40,6 @@ #import #import -#import "MAPIStoreAttachmentTable.h" #import "MAPIStoreCalendarAttachment.h" #import "MAPIStoreContext.h" #import "MAPIStoreRecurrenceUtils.h" @@ -73,17 +72,36 @@ static NSTimeZone *utcTZ; [utcTZ retain]; } +- (id) initWithSOGoObject: (id) newSOGoObject + inContainer: (MAPIStoreObject *) newContainer +{ + if ((self = [super initWithSOGoObject: newSOGoObject + inContainer: newContainer])) + { + ASSIGN (event, [newSOGoObject component: NO secure: NO]); + } + + return self; +} + - (id) init { if ((self = [super init])) { attachmentKeys = [NSMutableArray new]; attachmentParts = [NSMutableDictionary new]; + event = nil; } return self; } +- (void) dealloc +{ + [event release]; + [super dealloc]; +} + - (NSTimeZone *) ownerTimeZone { NSString *owner; @@ -100,7 +118,6 @@ static NSTimeZone *utcTZ; } - (void) _setupRecurrenceInCalendar: (iCalCalendar *) calendar - withMasterEvent: (iCalEvent *) vEvent fromData: (NSData *) mapiRecurrenceData { struct Binary_r *blob; @@ -109,13 +126,13 @@ static NSTimeZone *utcTZ; /* cleanup */ otherEvents = [[calendar events] mutableCopy]; - [otherEvents removeObject: vEvent]; + [otherEvents removeObject: event]; [calendar removeChildren: otherEvents]; [otherEvents release]; blob = [mapiRecurrenceData asBinaryInMemCtx: memCtx]; pattern = get_AppointmentRecurrencePattern (memCtx, blob); - [calendar setupRecurrenceWithMasterEntity: vEvent + [calendar setupRecurrenceWithMasterEntity: event fromRecurrencePattern: &pattern->RecurrencePattern]; talloc_free (pattern); talloc_free (blob); @@ -150,21 +167,19 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, struct Binary_r *bin; struct SBinary_short *sBin; NSCalendarDate *firstStartDate; - iCalEvent *vEvent; iCalRecurrenceRule *rule; - vEvent = [sogoObject component: NO secure: NO]; - rule = [[vEvent recurrenceRules] objectAtIndex: 0]; + rule = [[event recurrenceRules] objectAtIndex: 0]; - firstStartDate = [vEvent firstRecurrenceStartDate]; + firstStartDate = [event firstRecurrenceStartDate]; if (firstStartDate) { [firstStartDate setTimeZone: [self ownerTimeZone]]; arp = talloc_zero (memCtx, struct AppointmentRecurrencePattern); _fillAppointmentRecurrencePattern (arp, firstStartDate, - [vEvent durationAsTimeInterval], - [vEvent lastPossibleRecurrenceStartDate], + [event durationAsTimeInterval], + [event lastPossibleRecurrenceStartDate], rule); sBin = talloc_zero (memCtx, struct SBinary_short); bin = set_AppointmentRecurrencePattern (sBin, arp); @@ -184,146 +199,182 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, return sBin; } -- (enum MAPISTATUS) getProperty: (void **) data - withTag: (enum MAPITAGS) propTag +/* getters */ +- (int) getPrIconIndex: (void **) data // TODO +{ + uint32_t longValue; + + /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */ + // *longValue = 0x00000401 for recurring event + // *longValue = 0x00000402 for meeting + // *longValue = 0x00000403 for recurring meeting + // *longValue = 0x00000404 for invitation + + longValue = 0x0400; + if ([event isRecurrent]) + longValue |= 0x0001; + if ([[event attendees] count] > 0) + longValue |= 0x0002; + + *data = MAPILongValue (memCtx, longValue); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMessageClass: (void **) data +{ + *data = talloc_strdup(memCtx, "IPM.Appointment"); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrStartDate: (void **) data +{ + NSCalendarDate *dateValue; + + if ([event isRecurrent]) + dateValue = [event firstRecurrenceStartDate]; + else + dateValue = [event startDate]; + [dateValue setTimeZone: utcTZ]; + *data = [dateValue asFileTimeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidAppointmentStartWhole: (void **) data +{ + return [self getPrStartDate: data]; +} + +- (int) getPidLidCommonStart: (void **) data +{ + return [self getPrStartDate: data]; +} + +- (int) getPrEndDate: (void **) data +{ + NSCalendarDate *dateValue; + + if ([event isRecurrent]) + dateValue = [event firstRecurrenceStartDate]; + else + dateValue = [event startDate]; + dateValue + = [dateValue dateByAddingYears: 0 months: 0 days: 0 + hours: 0 minutes: 0 + seconds: (NSInteger) [event + durationAsTimeInterval]]; + [dateValue setTimeZone: utcTZ]; + *data = [dateValue asFileTimeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidAppointmentEndWhole: (void **) data +{ + return [self getPrEndDate: data]; +} + +- (int) getPidLidCommonEnd: (void **) data +{ + return [self getPrEndDate: data]; +} + +- (int) getPidLidAppointmentDuration: (void **) data { NSTimeInterval timeValue; - id event; - uint32_t longValue; - NSCalendarDate *dateValue; - int rc; - rc = MAPI_E_SUCCESS; - switch ((uint32_t) propTag) - { - case PR_ICON_INDEX: // TODO - /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */ - // *longValue = 0x00000401 for recurring event - // *longValue = 0x00000402 for meeting - // *longValue = 0x00000403 for recurring meeting - // *longValue = 0x00000404 for invitation + timeValue = [[event endDate] timeIntervalSinceDate: [event startDate]]; + *data = MAPILongValue (memCtx, (uint32_t) (timeValue / 60)); - event = [sogoObject component: NO secure: NO]; - longValue = 0x0400; - if ([event isRecurrent]) - longValue |= 0x0001; - if ([[event attendees] count] > 0) - longValue |= 0x0002; + return MAPISTORE_SUCCESS; +} - *data = MAPILongValue (memCtx, longValue); - break; - case PR_MESSAGE_CLASS_UNICODE: - *data = talloc_strdup(memCtx, "IPM.Appointment"); - break; - case PR_START_DATE: - case PidLidAppointmentStartWhole: - case PidLidCommonStart: - event = [sogoObject component: NO secure: NO]; - if ([event isRecurrent]) - dateValue = [event firstRecurrenceStartDate]; - else - dateValue = [event startDate]; - [dateValue setTimeZone: utcTZ]; - *data = [dateValue asFileTimeInMemCtx: memCtx]; - break; - case PR_END_DATE: - case PidLidAppointmentEndWhole: - case PidLidCommonEnd: - event = [sogoObject component: NO secure: NO]; - if ([event isRecurrent]) - dateValue = [event firstRecurrenceStartDate]; - else - dateValue = [event startDate]; - dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: - (NSInteger) [event durationAsTimeInterval]]; - [dateValue setTimeZone: utcTZ]; - *data = [dateValue asFileTimeInMemCtx: memCtx]; - break; - case PidLidAppointmentDuration: - event = [sogoObject component: NO secure: NO]; - timeValue = [[event endDate] timeIntervalSinceDate: [event startDate]]; - *data = MAPILongValue (memCtx, (uint32_t) (timeValue / 60)); - break; - case PidLidAppointmentSubType: - event = [sogoObject component: NO secure: NO]; - *data = MAPIBoolValue (memCtx, [event isAllDay]); - break; - case PidLidBusyStatus: // TODO - *data = MAPILongValue (memCtx, 0x02); - break; +- (int) getPidLidAppointmentSubType: (void **) data +{ + *data = MAPIBoolValue (memCtx, [event isAllDay]); - // case 0x82410003: // TODO - // *data = MAPILongValue (memCtx, 0); - // break; - case PR_SUBJECT_UNICODE: // SUMMARY - event = [sogoObject component: NO secure: NO]; - *data = [[event summary] asUnicodeInMemCtx: memCtx]; - break; - case PidLidLocation: // LOCATION - event = [sogoObject component: NO secure: NO]; - *data = [[event location] asUnicodeInMemCtx: memCtx]; - break; - case PidLidPrivate: // private (bool), should depend on CLASS and permissions - *data = MAPIBoolValue (memCtx, NO); - break; - case PR_SENSITIVITY: // not implemented, depends on CLASS - // normal = 0, personal?? = 1, private = 2, confidential = 3 - *data = MAPILongValue (memCtx, 0); - break; - case PR_CREATION_TIME: - event = [sogoObject component: NO secure: NO]; - *data = [[event created] asFileTimeInMemCtx: memCtx]; - break; + return MAPISTORE_SUCCESS; +} - case PR_IMPORTANCE: - { - unsigned int v; +- (int) getPidLidBusyStatus: (void **) data // TODO +{ + *data = MAPILongValue (memCtx, 0x02); - event = [sogoObject component: NO secure: NO]; + return MAPISTORE_SUCCESS; +} - if ([[event priority] isEqualToString: @"9"]) - v = 0x0; - else if ([[event priority] isEqualToString: @"1"]) - v = 0x2; - else - v = 0x1; +- (int) getPrSubject: (void **) data // SUMMARY +{ + *data = [[event summary] asUnicodeInMemCtx: memCtx]; - *data = MAPILongValue (memCtx, v); - } - break; + return MAPISTORE_SUCCESS; +} +- (int) getPidLidLocation: (void **) data // LOCATION +{ + *data = [[event location] asUnicodeInMemCtx: memCtx]; - /* Recurrence */ - case PidLidIsRecurring: - case PidLidRecurring: - event = [sogoObject component: NO secure: NO]; - *data = MAPIBoolValue (memCtx, [event isRecurrent]); - break; - case PidLidAppointmentRecur: - event = [sogoObject component: NO secure: NO]; - if ([event isRecurrent]) - *data = [self _computeAppointmentRecur]; - else - rc = MAPISTORE_ERR_NOT_FOUND; - break; + return MAPISTORE_SUCCESS; +} - // case PidLidTimeZoneStruct: - // case PR_VD_NAME_UNICODE: - // *data = talloc_strdup(memCtx, "PR_VD_NAME_UNICODE"); - // break; - // case PR_EMS_AB_DXA_REMOTE_CLIENT_UNICODE: "Home:" ??? - // *data = talloc_strdup(memCtx, "PR_EMS..."); - // break; - default: - rc = [super getProperty: data - withTag: propTag]; - } +- (int) getPidLidPrivate: (void **) data // private (bool), should depend on CLASS and permissions +{ + return [self getNo: data]; +} - // #define PR_REPLY_TIME PROP_TAG(PT_SYSTIME , 0x0030) /* 0x00300040 */ - // #define PR_INTERNET_MESSAGE_ID_UNICODE PROP_TAG(PT_UNICODE , 0x1035) /* 0x1035001f */ - // #define PR_FLAG_STATUS PROP_TAG(PT_LONG , 0x1090) /* 0x10900003 */ +- (int) getPrSensitivity: (void **) data // not implemented, depends on CLASS +{ + // normal = 0, personal?? = 1, private = 2, confidential = 3 + return [self getLongZero: data]; +} + +- (int) getPrCreationTime: (void **) data +{ + *data = [[event created] asFileTimeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrImportance: (void **) data +{ + uint32_t v; + + if ([[event priority] isEqualToString: @"9"]) + v = 0x0; + else if ([[event priority] isEqualToString: @"1"]) + v = 0x2; + else + v = 0x1; + + *data = MAPILongValue (memCtx, v); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidIsRecurring: (void **) data +{ + *data = MAPIBoolValue (memCtx, [event isRecurrent]); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidRecurring: (void **) data +{ + *data = MAPIBoolValue (memCtx, [event isRecurrent]); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidAppointmentRecur: (void **) data +{ + int rc = MAPISTORE_SUCCESS; + + if ([event isRecurrent]) + *data = [self _computeAppointmentRecur]; + else + rc = MAPISTORE_ERR_NOT_FOUND; return rc; } @@ -333,12 +384,10 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, NSString *name, *email; NSArray *attendees; iCalPerson *person; - id event; struct SRowSet *recipients; int count, max; [super openMessage: msg]; - event = [sogoObject component: NO secure: NO]; attendees = [event attendees]; max = [attendees count]; @@ -382,11 +431,11 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, { WOContext *woContext; iCalCalendar *vCalendar; - iCalEvent *vEvent; iCalDateTime *start, *end; iCalTimeZone *tz; NSCalendarDate *now; NSString *content, *tzName; + iCalEvent *newEvent; id value; [self logWithFormat: @"-save, event props:"]; @@ -395,25 +444,29 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, content = [sogoObject contentAsString]; if (![content length]) { - vEvent = [sogoObject component: YES secure: NO]; - vCalendar = [vEvent parent]; + newEvent = [sogoObject component: YES secure: NO]; + if (newEvent != event) + ASSIGN (event, newEvent); + vCalendar = [event parent]; [vCalendar setProdID: @"-//Inverse inc.//OpenChange+SOGo//EN"]; content = [vCalendar versitString]; } vCalendar = [iCalCalendar parseSingleFromSource: content]; - vEvent = [[vCalendar events] objectAtIndex: 0]; + newEvent = [[vCalendar events] objectAtIndex: 0]; + if (newEvent != event) + ASSIGN (event, newEvent); // summary value = [newProperties objectForKey: MAPIPropertyKey (PR_NORMALIZED_SUBJECT_UNICODE)]; if (value) - [vEvent setSummary: value]; + [event setSummary: value]; // Location value = [newProperties objectForKey: MAPIPropertyKey (PidLidLocation)]; if (value) - [vEvent setLocation: value]; + [event setLocation: value]; tzName = [[self ownerTimeZone] name]; tz = [iCalTimeZone timeZoneForName: tzName]; @@ -425,7 +478,7 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, value = [newProperties objectForKey: MAPIPropertyKey (PidLidAppointmentStartWhole)]; if (value) { - start = (iCalDateTime *) [vEvent uniqueChildWithTag: @"dtstart"]; + start = (iCalDateTime *) [event uniqueChildWithTag: @"dtstart"]; [start setTimeZone: tz]; [start setDateTime: value]; } @@ -436,7 +489,7 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, value = [newProperties objectForKey: MAPIPropertyKey (PidLidAppointmentEndWhole)]; if (value) { - end = (iCalDateTime *) [vEvent uniqueChildWithTag: @"dtend"]; + end = (iCalDateTime *) [event uniqueChildWithTag: @"dtend"]; [end setTimeZone: tz]; [end setDateTime: value]; } @@ -444,9 +497,9 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, now = [NSCalendarDate date]; if ([sogoObject isNew]) { - [vEvent setCreated: now]; + [event setCreated: now]; } - [vEvent setTimeStampAsDate: now]; + [event setTimeStampAsDate: now]; // Organizer and attendees value = [newProperties objectForKey: @"recipients"]; @@ -463,7 +516,7 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, person = [iCalPerson new]; [person setCn: [dict objectForKey: @"fullName"]]; [person setEmail: [dict objectForKey: @"email"]]; - [vEvent setOrganizer: person]; + [event setOrganizer: person]; [person release]; recipients = [value objectForKey: @"to"]; @@ -480,8 +533,8 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, [person setRole: @"REQ-PARTICIPANT"]; // FIXME: We must NOT always rely on this - if (![vEvent isAttendee: [person rfc822Email]]) - [vEvent addToAttendees: person]; + if (![event isAttendee: [person rfc822Email]]) + [event addToAttendees: person]; [person release]; } @@ -492,11 +545,10 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, objectForKey: MAPIPropertyKey (PidLidAppointmentRecur)]; if (value) [self _setupRecurrenceInCalendar: vCalendar - withMasterEvent: vEvent fromData: value]; // [sogoObject saveContentString: [vCalendar versitString]]; - [sogoObject saveComponent: vEvent]; + [sogoObject saveComponent: event]; } /* TODO: those are stubs meant to prevent OpenChange from crashing when a @@ -513,11 +565,6 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, return [attachmentParts objectForKey: childKey]; } -- (MAPIStoreAttachmentTable *) attachmentTable -{ - return [MAPIStoreAttachmentTable tableForContainer: self]; -} - - (MAPIStoreAttachment *) createAttachment { MAPIStoreCalendarAttachment *newAttachment; diff --git a/OpenChange/MAPIStoreContactsMessage.m b/OpenChange/MAPIStoreContactsMessage.m index 013fc2ae4..ddeca15c1 100644 --- a/OpenChange/MAPIStoreContactsMessage.m +++ b/OpenChange/MAPIStoreContactsMessage.m @@ -29,6 +29,7 @@ #import #import +#import "MAPIStorePropertySelectors.h" #import "MAPIStoreTypes.h" #import "NSArray+MAPIStore.h" #import "NSCalendarDate+MAPIStore.h" @@ -46,461 +47,466 @@ @implementation MAPIStoreContactsMessage -- (CardElement *) _element: (NSString *) elementTag - ofType: (NSString *) aType - excluding: (NSString *) aTypeToExclude - inCard: (NGVCard *) card +- (int) getPrIconIndex: (void **) data // TODO +{ + /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */ + *data = MAPILongValue (memCtx, 0x00000200); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMessageClass: (void **) data +{ + *data = talloc_strdup (memCtx, "IPM.Contact"); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrOabName: (void **) data +{ + *data = talloc_strdup (memCtx, "PR_OAB_NAME_UNICODE"); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrOabLangid: (void **) data +{ + /* see http://msdn.microsoft.com/en-us/goglobal/bb895996.asxp */ + /* English US */ + *data = MAPILongValue (memCtx, 0x0409); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrTitle: (void **) data +{ + NSString *stringValue; + + stringValue = [[sogoObject vCard] title]; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrCompanyName: (void **) data +{ + NSArray *values; + NSString *stringValue; + + values = [[sogoObject vCard] org]; + stringValue = nil; + + if ([values count] > 0) + stringValue = [values objectAtIndex: 0]; + else + stringValue = @""; + + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrDepartmentName: (void **) data +{ + NSArray *values; + NSString *stringValue; + + values = [[sogoObject vCard] org]; + stringValue = nil; + + if ([values count] > 1) + stringValue = [values objectAtIndex: 1]; + else + stringValue = @""; + + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrSendInternetEncoding: (void **) data +{ + *data = MAPILongValue (memCtx, 0x00065001); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrSubject: (void **) data +{ + return [self getPrDisplayName: data]; +} + +- (int) getPidLidFileUnder: (void **) data +{ + return [self getPrDisplayName: data]; +} + +- (int) getPidLidFileUnderId: (void **) data +{ + *data = MAPILongValue (memCtx, 0xffffffff); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidEmail1DisplayName: (void **) data +{ + NGVCard *vCard; + NSString *fn, *email; + + vCard = [sogoObject vCard]; + fn = [vCard fn]; + email = [vCard preferredEMail]; + *data = [[NSString stringWithFormat: @"%@ <%@>", fn, email] + asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidEmail1OriginalDisplayName: (void **) data +{ + return [self getPidLidEmail1DisplayName: data]; +} + +- (int) getPidLidEmail1EmailAddress: (void **) data +{ + NSString *stringValue; + + stringValue = [[sogoObject vCard] preferredEMail]; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrAccount: (void **) data +{ + return [self getPidLidEmail1EmailAddress: data]; +} + +- (int) getPrContactEmailAddresses: (void **) data +{ + NSString *stringValue; + + stringValue = [[sogoObject vCard] preferredEMail]; + if (!stringValue) + stringValue = @""; + *data = [[NSArray arrayWithObject: stringValue] + asArrayOfUnicodeStringsInCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrEmsAbTargetAddress: (void **) data +{ + NSString *stringValue; + + stringValue = [[sogoObject vCard] preferredEMail]; + *data = [[NSString stringWithFormat: @"SMTP:%@", stringValue] + asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrSearchKey: (void **) data // TODO +{ + NSString *stringValue; + + stringValue = [[sogoObject vCard] preferredEMail]; + *data = [[stringValue dataUsingEncoding: NSASCIIStringEncoding] + asBinaryInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMailPermission: (void **) data +{ + return [self getYes: data]; +} + +- (int) getPidLidEmail2EmailAddress: (void **) data +{ + NSMutableArray *emails; + NSString *email, *stringValue; + NGVCard *card; + NSUInteger count, max; + + emails = [NSMutableArray array]; + stringValue = nil; + + card = [sogoObject vCard]; + [emails addObjectsFromArray: [card childrenWithTag: @"email"]]; + [emails removeObjectsInArray: [card childrenWithTag: @"email" + andAttribute: @"type" + havingValue: @"pref"]]; + + max = [emails count]; + for (count = 0; !stringValue && count < max; count++) + { + email = [[emails objectAtIndex: count] value: 0]; + + if ([email caseInsensitiveCompare: [card preferredEMail]] != NSOrderedSame) + stringValue = email; + } + + if (!stringValue) + stringValue = @""; + + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidEmail2OriginalDisplayName: (void **) data // Other email +{ + return [self getPidLidEmail2EmailAddress: data]; +} + +- (int) getPrBody: (void **) data +{ + NSString *stringValue; + + stringValue = [[sogoObject vCard] note]; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) _getElement: (NSString *) elementTag + ofType: (NSString *) aType + excluding: (NSString *) aTypeToExclude + atPos: (NSUInteger) pos + inData: (void **) data { NSArray *elements; - CardElement *ce, *found; + CardElement *ce; NSUInteger count, max; + NGVCard *vCard; + NSString *stringValue; - found = nil; + stringValue = nil; - elements = [[card childrenWithTag: elementTag] + vCard = [sogoObject vCard]; + elements = [[vCard childrenWithTag: elementTag] cardElementsWithAttribute: @"type" havingValue: aType]; max = [elements count]; - for (count = 0; !found && count < max; count++) + for (count = 0; !stringValue && count < max; count++) { ce = [elements objectAtIndex: count]; if (!aTypeToExclude || ![ce hasAttribute: @"type" havingValue: aTypeToExclude]) - found = ce; + stringValue = [ce value: pos]; } - return found; + if (!stringValue) + stringValue = @""; + + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; } -- (enum MAPISTATUS) getProperty: (void **) data - withTag: (enum MAPITAGS) proptag +- (int) getPrOfficeTelephoneNumber: (void **) data { - NSString *stringValue, *stringValue2; + return [self _getElement: @"tel" ofType: @"work" excluding: @"fax" + atPos: 0 inData: data]; +} + +- (int) getPrHomeTelephoneNumber: (void **) data +{ + return [self _getElement: @"tel" ofType: @"home" excluding: @"fax" + atPos: 0 inData: data]; +} + +- (int) getPrMobileTelephoneNumber: (void **) data +{ + return [self _getElement: @"tel" ofType: @"cell" excluding: nil + atPos: 0 inData: data]; +} + +- (int) getPrPrimaryTelephoneNumber: (void **) data +{ + return [self _getElement: @"tel" ofType: @"pref" excluding: nil + atPos: 0 inData: data]; +} + +- (int) getPrBusinessHomePage: (void **) data +{ + return [self _getElement: @"url" ofType: @"work" excluding: nil + atPos: 0 inData: data]; +} + +- (int) getPrPersonalHomePage: (void **) data +{ + return [self _getElement: @"url" ofType: @"home" excluding: nil + atPos: 0 inData: data]; +} + +- (int) getPidLidEmail1AddressType: (void **) data +{ + return [self getSMTPAddrType: data]; +} + +- (int) getPidLidEmail2AddressType: (void **) data +{ + return [self getSMTPAddrType: data]; +} + +- (int) getPidLidEmail3AddressType: (void **) data +{ + return [self getSMTPAddrType: data]; +} + +- (int) getPidLidInstantMessagingAddress: (void **) data +{ + NSString *stringValue; + + stringValue = [[[sogoObject vCard] uniqueChildWithTag: @"x-aim"] + value: 0]; + if (!stringValue) + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidPostalAddressId: (void **) data +{ + NSArray *elements; CardElement *element; - uint32_t longValue; + uint32_t longValue = 0; NGVCard *vCard; - enum MAPISTATUS rc; - rc = MAPISTORE_SUCCESS; - switch ((uint32_t) proptag) + vCard = [sogoObject vCard]; + elements = [[vCard childrenWithTag: @"adr"] + cardElementsWithAttribute: @"type" + havingValue: @"pref"]; + if ([elements count] > 0) { - case PR_ICON_INDEX: // TODO - /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */ - *data = MAPILongValue (memCtx, 0x00000200); - break; - case PR_MESSAGE_CLASS_UNICODE: - *data = talloc_strdup (memCtx, "IPM.Contact"); - break; - // case PR_VD_NAME_UNICODE: - // *data = talloc_strdup (memCtx, "PR_VD_NAME_UNICODE"); - // break; - // case PR_EMS_AB_DXA_REMOTE_CLIENT_UNICODE: "Home:" ??? - // *data = talloc_strdup (memCtx, "PR_EMS..."); - // break; - case PR_OAB_NAME_UNICODE: - *data = talloc_strdup (memCtx, "PR_OAB_NAME_UNICODE"); - break; - case PR_OAB_LANGID: - /* see http://msdn.microsoft.com/en-us/goglobal/bb895996.asxp */ - /* English US */ - *data = MAPILongValue (memCtx, 0x0409); - break; - - case PR_TITLE_UNICODE: - stringValue = [[sogoObject vCard] title]; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - - case PR_COMPANY_NAME_UNICODE: - case PR_DEPARTMENT_NAME_UNICODE: - { - NSArray *values; - - values = [[sogoObject vCard] org]; - stringValue = nil; - - if (proptag == PR_COMPANY_NAME_UNICODE && [values count] > 0) - stringValue = [values objectAtIndex: 0]; - else if (proptag == PR_DEPARTMENT_NAME_UNICODE && [values count] > 1) - stringValue = [values objectAtIndex: 1]; - - if (!stringValue) - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - } - break; - - case PR_SEND_INTERNET_ENCODING: - *data = MAPILongValue (memCtx, 0x00065001); - break; - - case PR_SUBJECT_UNICODE: - case PR_DISPLAY_NAME_UNICODE: // Full Name - case PidLidFileUnder: // contact block title name - rc = [super getProperty: data - withTag: PR_DISPLAY_NAME_UNICODE]; - break; - case PidLidFileUnderId: - *data = MAPILongValue (memCtx, 0xffffffff); - break; - - case PidLidEmail1OriginalDisplayName: - case PidLidEmail1DisplayName: - vCard = [sogoObject vCard]; - stringValue = [vCard fn]; - stringValue2 = [vCard preferredEMail]; - *data = [[NSString stringWithFormat: @"%@ <%@>", - stringValue, stringValue2] - asUnicodeInMemCtx: memCtx]; - break; - - case PidLidEmail1EmailAddress: - case PR_ACCOUNT_UNICODE: - stringValue = [[sogoObject vCard] preferredEMail]; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - - case PR_CONTACT_EMAIL_ADDRESSES_UNICODE: - stringValue = [[sogoObject vCard] preferredEMail]; - if (!stringValue) - stringValue = @""; - *data = [[NSArray arrayWithObject: stringValue] - asArrayOfUnicodeStringsInCtx: memCtx]; - break; - - case PR_EMS_AB_TARGET_ADDRESS_UNICODE: - stringValue = [[sogoObject vCard] preferredEMail]; - *data = [[NSString stringWithFormat: @"SMTP:%@", stringValue] - asUnicodeInMemCtx: memCtx]; - break; - - case PR_SEARCH_KEY: // TODO - stringValue = [[sogoObject vCard] preferredEMail]; - *data = [[stringValue dataUsingEncoding: NSASCIIStringEncoding] - asBinaryInMemCtx: memCtx]; - break; - - case PR_MAIL_PERMISSION: - *data = MAPIBoolValue (memCtx, YES); - break; - - // - // TODO - same logic as -secondaryEmail in UI/Contacts/UIxContactView.m - // We should eventually merge that in order to not duplicate the code. - // We should also eventually handle PidLidEmail3OriginalDisplayName in - // SOGo, Thunderbird, etc. - // - case PidLidEmail2EmailAddress: - case PidLidEmail2OriginalDisplayName: // Other email - { - NSMutableArray *emails; - NSString *email; - NGVCard *card; - - emails = [NSMutableArray array]; - stringValue = nil; - - card = [sogoObject vCard]; - [emails addObjectsFromArray: [card childrenWithTag: @"email"]]; - [emails removeObjectsInArray: [card childrenWithTag: @"email" - andAttribute: @"type" - havingValue: @"pref"]]; - - if ([emails count] > 0) - { - int i; - - for (i = 0; i < [emails count]; i++) - { - email = [[emails objectAtIndex: i] value: 0]; - - if ([email caseInsensitiveCompare: [card preferredEMail]] != NSOrderedSame) - { - stringValue = email; - break; - } - } - } - - if (!stringValue) - stringValue = @""; - - *data = [stringValue asUnicodeInMemCtx: memCtx]; - } - break; - - // FIXME: this property does NOT work - case PR_BODY_UNICODE: - stringValue = [[sogoObject vCard] note]; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - - case PR_OFFICE_TELEPHONE_NUMBER_UNICODE: - element = [self _element: @"tel" ofType: @"work" - excluding: @"fax" - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 0]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_HOME_TELEPHONE_NUMBER_UNICODE: - element = [self _element: @"tel" ofType: @"home" - excluding: @"fax" - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 0]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_MOBILE_TELEPHONE_NUMBER_UNICODE: - element = [self _element: @"tel" ofType: @"cell" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 0]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_PRIMARY_TELEPHONE_NUMBER_UNICODE: - element = [self _element: @"tel" ofType: @"pref" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 0]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - - case PR_BUSINESS_HOME_PAGE_UNICODE: - case PR_PERSONAL_HOME_PAGE_UNICODE: - { - NSString *type; - - type = (proptag == PR_BUSINESS_HOME_PAGE_UNICODE ? @"work" : @"home"); - element = [self _element: @"url" ofType: type - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 0]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - } - break; - - case PidLidEmail1AddressType: - case PidLidEmail2AddressType: - case PidLidEmail3AddressType: - *data = [@"SMTP" asUnicodeInMemCtx: memCtx]; - break; - - case PidLidInstantMessagingAddress: - stringValue = [[[sogoObject vCard] uniqueChildWithTag: @"x-aim"] value: 0]; - - if (!stringValue) - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - - // - // We don't handle 0x00000003 - The Other Address is the mailing address. - // See: http://msdn.microsoft.com/en-us/library/cc815430.aspx - // - case PidLidPostalAddressId: - element = [self _element: @"adr" ofType: @"pref" - excluding: nil - inCard: [sogoObject vCard]]; + element = [elements objectAtIndex: 0]; if ([element hasAttribute: @"type" - havingValue: @"home"]) - longValue = 1; // The Home Address is the mailing address. + havingValue: @"home"]) + longValue = 1; // The Home Address is the mailing address. else if ([element hasAttribute: @"type" - havingValue: @"work"]) - longValue = 2; // The Work Address is the mailing address. - else - longValue = 0; // No address is selected as the mailing address. - *data = MAPILongValue (memCtx, longValue); - break; - - /* preferred address */ - case PR_POSTAL_ADDRESS_UNICODE: - element = [self _element: @"label" ofType: @"pref" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 0]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_POST_OFFICE_BOX_UNICODE: - element = [self _element: @"adr" ofType: @"pref" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 0]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_STREET_ADDRESS_UNICODE: - element = [self _element: @"adr" ofType: @"pref" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 2]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_LOCALITY_UNICODE: - element = [self _element: @"adr" ofType: @"pref" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 3]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_STATE_OR_PROVINCE_UNICODE: - element = [self _element: @"adr" ofType: @"pref" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 4]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_POSTAL_CODE_UNICODE: - element = [self _element: @"adr" ofType: @"pref" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 5]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_COUNTRY_UNICODE: - element = [self _element: @"adr" ofType: @"pref" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 6]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - - // case PidLidAddressCountryCode: - - case PidLidWorkAddress: - element = [self _element: @"label" ofType: @"work" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 0]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - - case PidLidWorkAddressPostOfficeBox: - element = [self _element: @"adr" ofType: @"work" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 0]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PidLidWorkAddressStreet: - element = [self _element: @"adr" ofType: @"work" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 2]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PidLidWorkAddressCity: - element = [self _element: @"adr" ofType: @"work" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 3]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PidLidWorkAddressState: - element = [self _element: @"adr" ofType: @"work" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 4]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PidLidWorkAddressPostalCode: - element = [self _element: @"adr" ofType: @"work" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 5]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PidLidWorkAddressCountry: - element = [self _element: @"adr" ofType: @"work" - excluding: nil - inCard: [sogoObject vCard]]; - if (element) - stringValue = [element value: 6]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - - // PidTagNickname - case PR_NICKNAME_UNICODE: - stringValue = [[sogoObject vCard] nickname]; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - - case PR_BIRTHDAY: - { - NSCalendarDate *dateValue; - - stringValue = [[sogoObject vCard] bday]; - - if (stringValue) - { - dateValue = [NSCalendarDate dateWithString: stringValue - calendarFormat: @"%Y-%m-%d"]; - // FIXME: We add a day, otherwise Outlook 2003 will display at day earlier - dateValue = [dateValue addYear: 0 month: 0 day: 1 hour: 0 minute: 0 second: 0]; - *data = [dateValue asFileTimeInMemCtx: memCtx]; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - } - break; - - default: - rc = [super getProperty: data withTag: proptag]; + havingValue: @"work"]) + longValue = 2; // The Work Address is the mailing address. } - + *data = MAPILongValue (memCtx, longValue); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrPostalAddress: (void **) data +{ + return [self _getElement: @"label" ofType: @"pref" excluding: nil + atPos: 0 inData: data]; +} + +- (int) getPrPostOfficeBox: (void **) data +{ + return [self _getElement: @"adr" ofType: @"pref" excluding: nil + atPos: 0 inData: data]; +} + +- (int) getPrStreetAddress: (void **) data +{ + return [self _getElement: @"adr" ofType: @"pref" excluding: nil + atPos: 2 inData: data]; +} + +- (int) getPrLocality: (void **) data +{ + return [self _getElement: @"adr" ofType: @"pref" excluding: nil + atPos: 3 inData: data]; +} + +- (int) getPrStateOrProvince: (void **) data +{ + return [self _getElement: @"adr" ofType: @"pref" excluding: nil + atPos: 4 inData: data]; +} + +- (int) getPrPostalCode: (void **) data +{ + return [self _getElement: @"adr" ofType: @"pref" excluding: nil + atPos: 5 inData: data]; +} + +- (int) getPrCountry: (void **) data +{ + return [self _getElement: @"adr" ofType: @"pref" excluding: nil + atPos: 6 inData: data]; +} + +- (int) getPidLidWorkAddress: (void **) data +{ + return [self _getElement: @"label" ofType: @"work" excluding: nil + atPos: 0 inData: data]; +} + +- (int) getPidLidWorkAddressPostOfficeBox: (void **) data +{ + return [self _getElement: @"adr" ofType: @"work" excluding: nil + atPos: 0 inData: data]; +} + +- (int) getPidLidWorkAddressStreet: (void **) data +{ + return [self _getElement: @"adr" ofType: @"work" excluding: nil + atPos: 2 inData: data]; +} + +- (int) getPidLidWorkAddressCity: (void **) data +{ + return [self _getElement: @"adr" ofType: @"work" excluding: nil + atPos: 3 inData: data]; +} + +- (int) getPidLidWorkAddressState: (void **) data +{ + return [self _getElement: @"adr" ofType: @"work" excluding: nil + atPos: 4 inData: data]; +} + +- (int) getPidLidWorkAddressPostalCode: (void **) data +{ + return [self _getElement: @"adr" ofType: @"work" excluding: nil + atPos: 5 inData: data]; +} + +- (int) getPidLidWorkAddressCountry: (void **) data +{ + return [self _getElement: @"adr" ofType: @"work" excluding: nil + atPos: 6 inData: data]; +} + +- (int) getPrNickname: (void **) data +{ + NSString *stringValue; + + stringValue = [[sogoObject vCard] nickname]; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrBirthday: (void **) data +{ + NSCalendarDate *dateValue; + NSString *stringValue; + int rc = MAPISTORE_SUCCESS; + + stringValue = [[sogoObject vCard] bday]; + if (stringValue) + { + dateValue = [NSCalendarDate dateWithString: stringValue + calendarFormat: @"%Y-%m-%d"]; + // FIXME: We add a day, otherwise Outlook 2003 will display at day earlier + dateValue = [dateValue addYear: 0 month: 0 day: 1 hour: 0 minute: 0 second: 0]; + *data = [dateValue asFileTimeInMemCtx: memCtx]; + } + else + rc = MAPISTORE_ERR_NOT_FOUND; + return rc; } diff --git a/OpenChange/MAPIStoreContext.h b/OpenChange/MAPIStoreContext.h index a7b408729..bd0296071 100644 --- a/OpenChange/MAPIStoreContext.h +++ b/OpenChange/MAPIStoreContext.h @@ -72,6 +72,8 @@ - (void) setAuthenticator: (MAPIStoreAuthenticator *) newAuthenticator; - (MAPIStoreAuthenticator *) authenticator; +- (NSURL *) url; + - (WOContext *) woContext; - (void) setupRequest; @@ -131,14 +133,6 @@ - (int) setPropertiesWithFMID: (uint64_t) fmid ofTableType: (uint8_t) tableType inRow: (struct SRow *) aRow; -- (int) setProperty: (enum MAPITAGS) property - withFMID: (uint64_t) fmid - ofTableType: (uint8_t) tableType - fromFile: (NSFileHandle *) aFile; -- (int) getProperty: (enum MAPITAGS) property - withFMID: (uint64_t) fmid - ofTableType: (uint8_t) tableType - intoFile: (NSFileHandle *) aFile; - (int) modifyRecipientsWithMID: (uint64_t) mid inRows: (struct ModifyRecipientRow *) rows withCount: (NSUInteger) max; diff --git a/OpenChange/MAPIStoreContext.m b/OpenChange/MAPIStoreContext.m index 8f6ebe824..9d942ed3e 100644 --- a/OpenChange/MAPIStoreContext.m +++ b/OpenChange/MAPIStoreContext.m @@ -21,7 +21,6 @@ */ #import -#import #import #import #import @@ -258,6 +257,11 @@ _prepareContextClass (struct mapistore_context *newMemCtx, return authenticator; } +- (NSURL *) url +{ + return contextUrl; +} + - (void) setupRequest { NSMutableDictionary *info; @@ -843,14 +847,14 @@ _prepareContextClass (struct mapistore_context *newMemCtx, { if (propRc == MAPISTORE_ERR_NOT_FOUND) propRc = MAPI_E_NOT_FOUND; - else if (propRc == MAPISTORE_ERR_NO_MEMORY) - propRc = MAPI_E_NOT_ENOUGH_MEMORY; + // else if (propRc == MAPISTORE_ERR_NO_MEMORY) + // propRc = MAPI_E_NOT_ENOUGH_MEMORY; if (propValue) talloc_free (propValue); propValue = MAPILongValue (memCtx, propRc); tag = (tag & 0xffff0000) | 0x000a; } - set_SPropValue_proptag (aRow->lpProps + count, tag, propValue); + set_SPropValue_proptag (aRow->lpProps + count, tag, propValue); } } talloc_free (data); @@ -977,120 +981,6 @@ _prepareContextClass (struct mapistore_context *newMemCtx, return rc; } -- (int) setProperty: (enum MAPITAGS) property - withFMID: (uint64_t) fmid - ofTableType: (uint8_t) tableType - fromFile: (NSFileHandle *) aFile -{ - MAPIStoreMessage *message; - NSNumber *midKey; - NSData *fileData; - const char *propName; - int rc; - - propName = get_proptag_name (property); - if (!propName) - propName = ""; - [self logWithFormat: @"METHOD '%s' -- property: %s(%.8x), fmid: 0x%.16x, tableType: %d", - __FUNCTION__, propName, property, fmid, tableType]; - - fileData = [aFile readDataToEndOfFile]; - switch (tableType) - { - case MAPISTORE_MESSAGE: - midKey = [NSNumber numberWithUnsignedLongLong: fmid]; - message = [messages objectForKey: midKey]; - if (message) - { - [message addNewProperties: - [NSDictionary - dictionaryWithObject: NSObjectFromStreamData (property, - fileData) - forKey: MAPIPropertyKey (property)]]; - rc = MAPISTORE_SUCCESS; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - break; - case MAPISTORE_FOLDER: - default: - [self errorWithFormat: @"%s: value of tableType not handled: %d", - __FUNCTION__, tableType]; - rc = MAPISTORE_ERROR; - } - - return rc; -} - -- (int) getProperty: (enum MAPITAGS) property - withFMID: (uint64_t) fmid - ofTableType: (uint8_t) tableType - intoFile: (NSFileHandle *) aFile -{ - MAPIStoreMessage *message; - NSNumber *midKey; - NSData *fileData; - const char *propName; - enum MAPISTATUS rc; - - propName = get_proptag_name (property); - if (!propName) - propName = ""; - [self logWithFormat: @"METHOD '%s' -- property: %s(%.8x), fmid: 0x%.16x, tableType: %d", - __FUNCTION__, propName, property, fmid, tableType]; - - switch (tableType) - { - case MAPISTORE_MESSAGE: - midKey = [NSNumber numberWithUnsignedLongLong: fmid]; - message = [messages objectForKey: midKey]; - if (message) - { - fileData = [[message newProperties] objectForKey: MAPIPropertyKey (property)]; - if ([fileData isKindOfClass: NSStringK]) - fileData = [fileData dataUsingEncoding: NSUTF16LittleEndianStringEncoding]; - if (fileData) - { - if (![fileData isKindOfClass: NSDataK]) - [self - errorWithFormat: @"data class not handled for streams: %@", - NSStringFromClass ([fileData class])]; - [aFile writeData: fileData]; - rc = MAPI_E_SUCCESS; - } - else - { - [self errorWithFormat: @"no data for property %s(%.8x)" - @" in mid %.16x", propName, property, fmid]; - rc = MAPI_E_NOT_FOUND; - } - } - else - { - [self errorWithFormat: @"no message found with mid %.16x", fmid]; - rc = MAPI_E_INVALID_OBJECT; - } - break; - - // [message setObject: NSObjectFromStreamData (property, fileData) - // forKey: MAPIPropertyNumber (property)]; - // rc = MAPISTORE_SUCCESS; - // } - // else - case MAPISTORE_FOLDER: - [self errorWithFormat: @"%s: folder properties not handled yet", - __FUNCTION__]; - rc = MAPI_E_NOT_FOUND; - break; - default: - [self errorWithFormat: @"%s: value of tableType not handled: %d", - __FUNCTION__, tableType]; - rc = MAPI_E_INVALID_OBJECT; - } - - return rc; -} - - (NSDictionary *) _convertRecipientFromRow: (struct RecipientRow *) row { NSMutableDictionary *recipient; diff --git a/OpenChange/MAPIStoreDraftsMessage.m b/OpenChange/MAPIStoreDraftsMessage.m index 4135df6c0..82b51fcc2 100644 --- a/OpenChange/MAPIStoreDraftsMessage.m +++ b/OpenChange/MAPIStoreDraftsMessage.m @@ -29,7 +29,6 @@ #import #import -#import "MAPIStoreAttachmentTable.h" #import "MAPIStoreContext.h" #import "MAPIStoreDraftsAttachment.h" #import "MAPIStoreTypes.h" @@ -165,11 +164,6 @@ e) [self _saveAttachment: [attachmentKeys objectAtIndex: count]]; } -- (MAPIStoreAttachmentTable *) attachmentTable -{ - return [MAPIStoreAttachmentTable tableForContainer: self]; -} - - (MAPIStoreAttachment *) createAttachment { MAPIStoreDraftsAttachment *newAttachment; diff --git a/OpenChange/MAPIStoreFSMessage.m b/OpenChange/MAPIStoreFSMessage.m index 06ee5ac77..441cf9002 100644 --- a/OpenChange/MAPIStoreFSMessage.m +++ b/OpenChange/MAPIStoreFSMessage.m @@ -35,7 +35,7 @@ { id value; enum MAPISTATUS rc; - + value = [[sogoObject properties] objectForKey: MAPIPropertyKey (propTag)]; if (value) rc = [value getMAPIValue: data forTag: propTag inMemCtx: memCtx]; diff --git a/OpenChange/MAPIStoreFolder.m b/OpenChange/MAPIStoreFolder.m index d2093eb34..903b7082d 100644 --- a/OpenChange/MAPIStoreFolder.m +++ b/OpenChange/MAPIStoreFolder.m @@ -395,8 +395,7 @@ Class NSExceptionK, MAPIStoreMessageTableK, MAPIStoreFAIMessageTableK, MAPIStore - (MAPIStoreMessage *) createMessage { - [self subclassResponsibility: _cmd]; - + [self logWithFormat: @"ignored method: %s", __PRETTY_FUNCTION__]; return nil; } diff --git a/OpenChange/MAPIStoreFolderTable.m b/OpenChange/MAPIStoreFolderTable.m index b34b07015..e492369f0 100644 --- a/OpenChange/MAPIStoreFolderTable.m +++ b/OpenChange/MAPIStoreFolderTable.m @@ -59,7 +59,7 @@ static MAPIStoreMapping *mapping; - (NSArray *) restrictedChildKeys { - [self errorWithFormat: @"restrictions are ignored on folder tables"]; + /* FIXME: restrictions are ignored on folder tables */ return [self childKeys]; } diff --git a/OpenChange/MAPIStoreMailAttachment.m b/OpenChange/MAPIStoreMailAttachment.m index 8c43085dd..56ed0086b 100644 --- a/OpenChange/MAPIStoreMailAttachment.m +++ b/OpenChange/MAPIStoreMailAttachment.m @@ -86,7 +86,7 @@ break; case PR_ATTACH_TAG: *data = [[self mimeAttachTag] - asShortBinaryInMemCtx: memCtx]; + asBinaryInMemCtx: memCtx]; break; case PR_ATTACH_SIZE: longValue = [[bodyInfo objectForKey: @"size"] longValue]; @@ -95,7 +95,7 @@ case PR_RECORD_KEY: *data = [[NSData dataWithBytes: recordBytes length: 16] - asShortBinaryInMemCtx: memCtx]; + asBinaryInMemCtx: memCtx]; break; // PR_RECORD_KEY (0xFF90102) D9 D8 11 A3 E2 90 18 41 9E 04 58 46 9D 6D 1B 68 @@ -152,7 +152,7 @@ break; case PR_ATTACH_DATA_BIN: - *data = [[sogoObject fetchBLOB] asShortBinaryInMemCtx: memCtx]; + *data = [[sogoObject fetchBLOB] asBinaryInMemCtx: memCtx]; break; default: diff --git a/OpenChange/MAPIStoreMailMessage.m b/OpenChange/MAPIStoreMailMessage.m index 67fb9ea23..8a731cc03 100644 --- a/OpenChange/MAPIStoreMailMessage.m +++ b/OpenChange/MAPIStoreMailMessage.m @@ -35,6 +35,7 @@ #import "NSString+MAPIStore.h" #import "MAPIStoreContext.h" #import "MAPIStoreFolder.h" +#import "MAPIStoreMailFolder.h" #import "MAPIStoreTypes.h" #import "MAPIStoreMailAttachment.h" @@ -47,7 +48,7 @@ #include #include -static Class NSExceptionK; +static Class NSExceptionK, MAPIStoreSentItemsFolderK, MAPIStoreDraftsFolderK; @interface NSString (MAPIStoreMIME) @@ -81,472 +82,584 @@ static Class NSExceptionK; + (void) initialize { NSExceptionK = [NSException class]; + MAPIStoreSentItemsFolderK = [MAPIStoreSentItemsFolder class]; + MAPIStoreDraftsFolderK = [MAPIStoreDraftsFolder class]; } -- (MAPIStoreAttachmentTable *) attachmentTable +- (int) getPrIconIndex: (void **) data { - return [MAPIStoreAttachmentTable tableForContainer: self]; + uint32_t longValue; + + /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */ + if ([sogoObject isNewMail]) + longValue = 0xffffffff; + else if ([sogoObject replied]) + longValue = 0x105; + else if ([sogoObject forwarded]) + longValue = 0x106; + else if ([sogoObject read]) + longValue = 0x100; + else + longValue = 0x101; + *data = MAPILongValue (memCtx, longValue); + + return MAPISTORE_SUCCESS; } -- (enum MAPISTATUS) getProperty: (void **) data - withTag: (enum MAPITAGS) propTag +- (int) getPidLidImapDeleted: (void **) data { - NSString *subject, *stringValue; - NSInteger colIdx; - uint32_t intValue; - enum MAPISTATUS rc; + uint32_t longValue; - rc = MAPISTORE_SUCCESS; - switch ((uint32_t) propTag) + if ([sogoObject deleted]) + longValue = 1; + else + longValue = 0; + *data = MAPILongValue (memCtx, longValue); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrSubject: (void **) data +{ + NSString *stringValue; + + stringValue = [sogoObject decodedSubject]; + if (!stringValue) + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrSubjectPrefix: (void **) data +{ + NSString *subject; + NSUInteger colIdx; + NSString *stringValue; + + subject = [sogoObject decodedSubject]; + colIdx = [subject rangeOfString: @":"].location; + if (colIdx != NSNotFound && colIdx < 4) + stringValue = [NSString stringWithFormat: @"%@: ", + [subject substringToIndex: colIdx]]; + else + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrNormalizedSubject: (void **) data +{ + NSString *subject; + NSUInteger colIdx; + NSString *stringValue; + + subject = [sogoObject decodedSubject]; + colIdx = [subject rangeOfString: @":"].location; + if (colIdx != NSNotFound && colIdx < 4) + stringValue = [[subject substringFromIndex: colIdx + 1] + stringByTrimmingLeadSpaces]; + else + stringValue = subject; + if (!stringValue) + stringValue = @""; + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMessageClass: (void **) data +{ + *data = talloc_strdup (memCtx, "IPM.Note"); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrReplyRequested: (void **) data // TODO +{ + return [self getNo: data]; +} + +- (int) getPrResponseRequested: (void **) data // TODO +{ + *data = MAPIBoolValue (memCtx, NO); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrCreationTime: (void **) data // DOUBT +{ + *data = [[sogoObject date] asFileTimeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrLastModificationTime: (void **) data // DOUBT +{ + return [self getPrCreationTime: data]; +} + +- (int) getPrLatestDeliveryTime: (void **) data // DOUBT +{ + return [self getPrCreationTime: data]; +} + +- (int) getPrOriginalSubmitTime: (void **) data +{ + return [self getPrCreationTime: data]; +} + +- (int) getPrClientSubmitTime: (void **) data +{ + return [self getPrCreationTime: data]; +} + +- (int) getPrMessageDeliveryTime: (void **) data +{ + return [self getPrCreationTime: data]; +} + +- (int) getPrMessageFlags: (void **) data // TODO +{ + NSDictionary *coreInfos; + NSArray *flags; + unsigned int v = 0; + + coreInfos = [sogoObject fetchCoreInfos]; + flags = [coreInfos objectForKey: @"flags"]; + + if ([container isKindOfClass: MAPIStoreSentItemsFolderK] + || [container isKindOfClass: MAPIStoreDraftsFolderK]) + v |= MSGFLAG_FROMME; + if ([flags containsObject: @"seen"]) + v |= MSGFLAG_READ; + if ([[self childKeysMatchingQualifier: nil + andSortOrderings: nil] count] > 0) + v |= MSGFLAG_HASATTACH; + + *data = MAPILongValue (memCtx, v); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrFlagStatus: (void **) data +{ + NSDictionary *coreInfos; + NSArray *flags; + unsigned int v; + + coreInfos = [sogoObject fetchCoreInfos]; + + flags = [coreInfos objectForKey: @"flags"]; + if ([flags containsObject: @"flagged"]) + v = 2; + else + v = 0; + + *data = MAPILongValue (memCtx, v); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrFollowupIcon: (void **) data +{ + NSDictionary *coreInfos; + NSArray *flags; + unsigned int v; + + coreInfos = [sogoObject fetchCoreInfos]; + + flags = [coreInfos objectForKey: @"flags"]; + if ([flags containsObject: @"flagged"]) + v = 6; + else + v = 0; + + *data = MAPILongValue (memCtx, v); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrSensitivity: (void **) data // TODO +{ + return [self getLongZero: data]; +} + +- (int) getProriginalSensitivity: (void **) data // TODO +{ + return [self getPrSensitivity: data]; +} + +- (int) getPrExpiryTime: (void **) data // TODO +{ + *data = [[NSCalendarDate date] asFileTimeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +// - (int) getPrReplyTime: (void **) data // TODO +// { +// *data = [[NSCalendarDate date] asFileTimeInMemCtx: memCtx]; + +// return MAPISTORE_SUCCESS; +// } + +- (int) getPrSentRepresentingAddrtype: (void **) data +{ + return [self getSMTPAddrType: data]; +} + +- (int) getPrRcvdRepresentingAddrtype: (void **) data +{ + return [self getSMTPAddrType: data]; +} + +- (int) getPrReceivedByAddrtype: (void **) data +{ + return [self getSMTPAddrType: data]; +} + +- (int) getPrSenderAddrtype: (void **) data +{ + return [self getSMTPAddrType: data]; +} + +- (int) getPrSenderEmailAddress: (void **) data +{ + NSString *stringValue; + + stringValue = [sogoObject from]; + if (!stringValue) + stringValue = @""; + + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrSenderName: (void **) data +{ + return [self getPrSenderEmailAddress: data]; +} + +- (int) getPrOriginalAuthorName: (void **) data +{ + return [self getPrSenderEmailAddress: data]; +} + +- (int) getPrSentRepresentingEmailAddress: (void **) data +{ + return [self getPrSenderEmailAddress: data]; +} + +- (int) getPrSentRepresentingName: (void **) data +{ + return [self getPrSenderEmailAddress: data]; +} + +- (int) getPrReceivedByEmailAddress: (void **) data +{ + NSString *stringValue; + + stringValue = [sogoObject to]; + if (!stringValue) + stringValue = @""; + + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrReceivedByName: (void **) data +{ + return [self getPrReceivedByEmailAddress: data]; +} + +- (int) getPrRcvdRepresentingName: (void **) data +{ + return [self getPrReceivedByEmailAddress: data]; +} + +- (int) getPrRcvdRepresentingEmailAddress: (void **) data +{ + return [self getPrReceivedByEmailAddress: data]; +} + +- (int) getPrDisplayTo: (void **) data +{ + return [self getPrReceivedByEmailAddress: data]; +} + +- (int) getPrOriginalDisplayTo: (void **) data +{ + return [self getPrDisplayTo: data]; +} + +- (int) getPrDisplayCc: (void **) data +{ + NSString *stringValue; + + stringValue = [sogoObject cc]; + if (!stringValue) + stringValue = @""; + + *data = [stringValue asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrOriginalDisplayCc: (void **) data +{ + return [self getPrDisplayCc: data]; +} + +- (int) getPrDisplayBcc: (void **) data +{ + return [self getEmptyString: data]; +} + +- (int) getPrOriginalDisplayBcc: (void **) data +{ + return [self getPrDisplayBcc: data]; +} + +- (int) getPidNameContentType: (void **) data +{ + *data = [@"message/rfc822" asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrImportance: (void **) data +{ + uint32_t v; + NSString *s; + + s = [[sogoObject mailHeaders] objectForKey: @"x-priority"]; + v = 0x1; + + if ([s hasPrefix: @"1"]) v = 0x2; + else if ([s hasPrefix: @"2"]) v = 0x2; + else if ([s hasPrefix: @"4"]) v = 0x0; + else if ([s hasPrefix: @"5"]) v = 0x0; + + *data = MAPILongValue (memCtx, v); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrInternetCpid: (void **) data +{ + /* ref: + http://msdn.microsoft.com/en-us/library/dd317756%28v=vs.85%29.aspx + + minimal list that should be handled: + us-ascii: 20127 + iso-8859-1: 28591 + iso-8859-15: 28605 + utf-8: 65001 */ + *data = MAPILongValue(memCtx, 65001); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrBody: (void **) data +{ + NSMutableArray *keys; + id result; + NSData *content; + NSDictionary *partHeaderData; + NSString *partKey, *encoding, *charset, *stringValue; + int rc = MAPISTORE_SUCCESS; + + keys = [NSMutableArray array]; + [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] + path: @"" toArray: keys + acceptedTypes: [NSArray arrayWithObject: + @"text/html"]]; + if ([keys count] > 0) { - case PR_ICON_INDEX: - /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */ - if ([sogoObject isNewMail]) - intValue = 0xffffffff; - else if ([sogoObject replied]) - intValue = 0x105; - else if ([sogoObject forwarded]) - intValue = 0x106; - else if ([sogoObject read]) - intValue = 0x100; - else - intValue = 0x101; - *data = MAPILongValue (memCtx, intValue); - break; - case PidLidImapDeleted: - if ([sogoObject deleted]) - intValue = 1; - else - intValue = 0; - *data = MAPILongValue (memCtx, intValue); - break; - case PR_SUBJECT_UNICODE: - stringValue = [sogoObject decodedSubject]; - if (!stringValue) - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_SUBJECT_PREFIX_UNICODE: - subject = [sogoObject decodedSubject]; - colIdx = [subject rangeOfString: @":"].location; - if (colIdx != NSNotFound && colIdx < 4) - stringValue = [NSString stringWithFormat: @"%@: ", - [subject substringToIndex: colIdx]]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_NORMALIZED_SUBJECT_UNICODE: - subject = [sogoObject decodedSubject]; - colIdx = [subject rangeOfString: @":"].location; - if (colIdx != NSNotFound && colIdx < 4) - stringValue = [[subject substringFromIndex: colIdx + 1] - stringByTrimmingLeadSpaces]; - else - stringValue = subject; - if (!stringValue) - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - - case PR_MESSAGE_CLASS_UNICODE: - case PR_ORIG_MESSAGE_CLASS_UNICODE: - *data = talloc_strdup (memCtx, "IPM.Note"); - break; - // case PidLidRemoteAttachment: // TODO - case PR_REPLY_REQUESTED: // TODO - case PR_RESPONSE_REQUESTED: // TODO - *data = MAPIBoolValue (memCtx, NO); - break; - // case PidLidHeaderItem: - // *data = MAPILongValue (memCtx, 0x00000001); - // break; - // case PidLidRemoteTransferSize: - // rc = [self getChildProperty: data - // forKey: childKey - // withTag: PR_MESSAGE_SIZE]; - // break; - case PR_CREATION_TIME: // DOUBT - case PR_LAST_MODIFICATION_TIME: // DOUBT - case PR_LATEST_DELIVERY_TIME: // DOUBT - case PR_ORIGINAL_SUBMIT_TIME: - case PR_CLIENT_SUBMIT_TIME: - case PR_MESSAGE_DELIVERY_TIME: - // offsetDate = [[sogoObject date] addYear: -1 month: 0 day: 0 - // hour: 0 minute: 0 second: 0]; - // *data = [offsetDate asFileTimeInMemCtx: memCtx]; - *data = [[sogoObject date] asFileTimeInMemCtx: memCtx]; - break; - case PR_MESSAGE_FLAGS: // TODO - { - NSDictionary *coreInfos; - NSArray *flags; - unsigned int v; - - coreInfos = [sogoObject fetchCoreInfos]; - - flags = [coreInfos objectForKey: @"flags"]; - v = MSGFLAG_FROMME; - - if ([flags containsObject: @"seen"]) - v |= MSGFLAG_READ; - - *data = MAPILongValue (memCtx, v); - } - break; - - case PR_FLAG_STATUS: - { - NSDictionary *coreInfos; - NSArray *flags; - unsigned int v; - - coreInfos = [sogoObject fetchCoreInfos]; - - flags = [coreInfos objectForKey: @"flags"]; - if ([flags containsObject: @"flagged"]) - v = 2; - else - v = 0; - - *data = MAPILongValue (memCtx, v); - } - break; - - case PR_FOLLOWUP_ICON: - { - NSDictionary *coreInfos; - NSArray *flags; - unsigned int v; - - coreInfos = [sogoObject fetchCoreInfos]; - - flags = [coreInfos objectForKey: @"flags"]; - if ([flags containsObject: @"flagged"]) - v = 6; - else - v = 0; - - *data = MAPILongValue (memCtx, v); - } - break; - - case PR_SENSITIVITY: // TODO - case PR_ORIGINAL_SENSITIVITY: // TODO - *data = MAPILongValue (memCtx, 0); - break; - - case PR_EXPIRY_TIME: // TODO - case PR_REPLY_TIME: - *data = [[NSCalendarDate date] asFileTimeInMemCtx: memCtx]; - break; - - case PR_SENT_REPRESENTING_ADDRTYPE_UNICODE: - case PR_RCVD_REPRESENTING_ADDRTYPE_UNICODE: - case PR_RECEIVED_BY_ADDRTYPE_UNICODE: - case PR_SENDER_ADDRTYPE_UNICODE: - *data = [@"SMTP" asUnicodeInMemCtx: memCtx]; - break; - case PR_ORIGINAL_AUTHOR_NAME_UNICODE: - case PR_SENDER_NAME_UNICODE: - case PR_SENDER_EMAIL_ADDRESS_UNICODE: - case PR_SENT_REPRESENTING_EMAIL_ADDRESS_UNICODE: - case PR_SENT_REPRESENTING_NAME_UNICODE: - *data = [[sogoObject from] asUnicodeInMemCtx: memCtx]; - break; - - /* TODO: some of the following are supposed to be display names, separated by a semicolumn */ - case PR_RECEIVED_BY_NAME_UNICODE: - case PR_RECEIVED_BY_EMAIL_ADDRESS_UNICODE: - case PR_RCVD_REPRESENTING_NAME_UNICODE: - case PR_RCVD_REPRESENTING_EMAIL_ADDRESS_UNICODE: - case PR_DISPLAY_TO_UNICODE: - case PR_ORIGINAL_DISPLAY_TO_UNICODE: - stringValue = [sogoObject to]; - if (!stringValue) - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_DISPLAY_CC_UNICODE: - case PR_ORIGINAL_DISPLAY_CC_UNICODE: - stringValue = [sogoObject cc]; - if (!stringValue) - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - case PR_DISPLAY_BCC_UNICODE: - case PR_ORIGINAL_DISPLAY_BCC_UNICODE: - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - break; - - case PidNameContentType: - *data = [@"message/rfc822" asUnicodeInMemCtx: memCtx]; - break; - - - // - // TODO: Merge with the code in UI/MailerUI/UIxMailListActions.m: -messagePriority - // to avoid the duplication of the logic - // - case PR_IMPORTANCE: - { - unsigned int v; - NSString *s; - - s = [[sogoObject mailHeaders] objectForKey: @"x-priority"]; - v = 0x1; - - - if ([s hasPrefix: @"1"]) v = 0x2; - else if ([s hasPrefix: @"2"]) v = 0x2; - else if ([s hasPrefix: @"4"]) v = 0x0; - else if ([s hasPrefix: @"5"]) v = 0x0; - - *data = MAPILongValue (memCtx, v); - } - break; - - case PR_BODY_UNICODE: - { - NSMutableArray *keys; - - keys = [NSMutableArray array]; - [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] - path: @"" toArray: keys - acceptedTypes: [NSArray arrayWithObject: - @"text/html"]]; - if ([keys count] > 0) - { - *data = NULL; - rc = MAPISTORE_ERR_NOT_FOUND; - } - else - { - [keys removeAllObjects]; - [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] - path: @"" toArray: keys - acceptedTypes: [NSArray arrayWithObject: - @"text/plain"]]; - if ([keys count] > 0) - { - id result; - NSData *content; - NSDictionary *partHeaderData; - NSString *partKey, *encoding, *charset; - - result = [sogoObject fetchParts: [keys objectsForKey: @"key" - notFoundMarker: nil]]; - result = [[result valueForKey: @"RawResponse"] objectForKey: @"fetch"]; - partKey = [[keys objectAtIndex: 0] objectForKey: @"key"]; - content = [[result objectForKey: partKey] objectForKey: @"data"]; - - partHeaderData - = [sogoObject lookupInfoForBodyPart: [partKey _strippedBodyKey]]; - encoding = [partHeaderData objectForKey: @"encoding"]; - charset = [[partHeaderData objectForKey: @"parameterList"] - objectForKey: @"charset"]; - stringValue = [[content bodyDataFromEncoding: encoding] - bodyStringFromCharset: charset]; - - *data = [stringValue asUnicodeInMemCtx: memCtx]; - if (strlen (*data) > 16384) - { - /* TODO: currently a hack to transfer properties as - streams */ - [newProperties setObject: stringValue - forKey: MAPIPropertyKey (propTag)]; - *data = NULL; - rc = MAPI_E_NOT_ENOUGH_MEMORY; - [self logWithFormat: @"PR_BODY data too wide"]; - } - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - } - } - break; - - case PR_INTERNET_CPID: - /* ref: - http://msdn.microsoft.com/en-us/library/dd317756%28v=vs.85%29.aspx - - minimal list that should be handled: - us-ascii: 20127 - iso-8859-1: 28591 - iso-8859-15: 28605 - utf-8: 65001 */ - *data = MAPILongValue(memCtx, 65001); - break; - - case PR_HTML: - { - NSMutableArray *keys; - NSArray *acceptedTypes; - - acceptedTypes = [NSArray arrayWithObject: @"text/html"]; - keys = [NSMutableArray array]; - [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] - path: @"" toArray: keys acceptedTypes: acceptedTypes]; - if ([keys count] > 0) - { - id result; - NSData *content; - NSDictionary *partHeaderData; - NSString *key, *encoding; - char *oldBytes, *newBytes; - NSUInteger c, newC, max, newMax; - - result = [sogoObject fetchParts: [keys objectsForKey: @"key" - notFoundMarker: nil]]; - result = [[result valueForKey: @"RawResponse"] objectForKey: - @"fetch"]; - key = [[keys objectAtIndex: 0] objectForKey: @"key"]; - content = [[result objectForKey: key] objectForKey: @"data"]; - - max = [content length]; - newMax = max; - oldBytes = malloc (max); - newBytes = malloc (max * 2); - [content getBytes: oldBytes]; - newC = 0; - for (c = 0; c < max; c++) - { - if (*(oldBytes + c) == '\n') - { - *(newBytes + newC) = '\r'; - newC++; - newMax++; - } - *(newBytes + newC) = *(oldBytes + c); - newC++; - } - content = [[NSData alloc] initWithBytesNoCopy: newBytes - length: newMax];; - [content autorelease]; - - partHeaderData - = [sogoObject lookupInfoForBodyPart: [key _strippedBodyKey]]; - encoding = [partHeaderData objectForKey: @"encoding"]; - content = [content bodyDataFromEncoding: encoding]; - - if ([content length] > 16384) - { - /* TODO: currently a hack to transfer properties as - streams */ - [newProperties setObject: content - forKey: MAPIPropertyKey (propTag)]; - *data = NULL; - rc = MAPI_E_NOT_ENOUGH_MEMORY; - [self logWithFormat: @"PR_HTML data too wide"]; - } - else - *data = [content asBinaryInMemCtx: memCtx]; - } - else - { - *data = NULL; - rc = MAPISTORE_ERR_NOT_FOUND; - } - } - break; - - /* We don't handle any RTF content. */ - case PR_RTF_COMPRESSED: *data = NULL; rc = MAPISTORE_ERR_NOT_FOUND; - break; - case PR_RTF_IN_SYNC: - *data = MAPIBoolValue (memCtx, NO); - break; - case PR_INTERNET_MESSAGE_ID_UNICODE: - *data = [[sogoObject messageId] asUnicodeInMemCtx: memCtx]; - break; - case PR_READ_RECEIPT_REQUESTED: // TODO - case PR_DELETE_AFTER_SUBMIT: // TODO - *data = MAPIBoolValue (memCtx, NO); - break; - case PidLidPrivate: - *data = MAPIBoolValue (memCtx, NO); - break; - - case PR_MSG_EDITOR_FORMAT: - { - NSMutableArray *keys; - NSArray *acceptedTypes; - uint32_t format; - - format = 0; /* EDITOR_FORMAT_DONTKNOW */ - - acceptedTypes = [NSArray arrayWithObject: @"text/plain"]; - keys = [NSMutableArray array]; - [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] - path: @"" toArray: keys - acceptedTypes: acceptedTypes]; - if ([keys count] == 1) - format = EDITOR_FORMAT_PLAINTEXT; - - acceptedTypes = [NSArray arrayWithObject: @"text/html"]; - [keys removeAllObjects]; - [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] - path: @"" toArray: keys - acceptedTypes: acceptedTypes]; - if ([keys count] == 1) - format = EDITOR_FORMAT_HTML; - - *data = MAPILongValue (memCtx, format); - } - break; - - case PidLidReminderSet: // TODO - case PidLidUseTnef: // TODO - *data = MAPIBoolValue (memCtx, NO); - break; - case PidLidRemoteStatus: // TODO - *data = MAPILongValue (memCtx, 0); - break; - // case PidLidSmartNoAttach: // TODO - case PidLidAgingDontAgeMe: // TODO - *data = MAPIBoolValue (memCtx, YES); - break; - -// PidLidFlagRequest -// PidLidBillingInformation -// PidLidMileage -// PidLidCommonEnd -// PidLidCommonStart -// PidLidNonSendableBcc -// PidLidNonSendableCc -// PidLidNonSendtableTo -// PidLidNonSendBccTrackStatus -// PidLidNonSendCcTrackStatus -// PidLidNonSendToTrackStatus -// PidLidReminderDelta -// PidLidReminderFileParameter -// PidLidReminderSignalTime -// PidLidReminderOverride -// PidLidReminderPlaySound -// PidLidReminderTime -// PidLidReminderType -// PidLidSmartNoAttach -// PidLidTaskGlobalId -// PidLidTaskMode -// PidLidVerbResponse -// PidLidVerbStream -// PidLidInternetAccountName -// PidLidInternetAccountStamp -// PidLidContactLinkName -// PidLidContactLinkEntry -// PidLidContactLinkSearchKey -// PidLidSpamOriginalFolder - - default: - rc = [super getProperty: data withTag: propTag]; + } + else + { + [keys removeAllObjects]; + [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] + path: @"" toArray: keys + acceptedTypes: [NSArray arrayWithObject: + @"text/plain"]]; + if ([keys count] > 0) + { + result = [sogoObject fetchParts: [keys objectsForKey: @"key" + notFoundMarker: nil]]; + result = [[result valueForKey: @"RawResponse"] objectForKey: @"fetch"]; + partKey = [[keys objectAtIndex: 0] objectForKey: @"key"]; + content = [[result objectForKey: partKey] objectForKey: @"data"]; + + partHeaderData + = [sogoObject lookupInfoForBodyPart: [partKey _strippedBodyKey]]; + encoding = [partHeaderData objectForKey: @"encoding"]; + charset = [[partHeaderData objectForKey: @"parameterList"] + objectForKey: @"charset"]; + stringValue = [[content bodyDataFromEncoding: encoding] + bodyStringFromCharset: charset]; + + *data = [stringValue asUnicodeInMemCtx: memCtx]; + } + else + rc = MAPISTORE_ERR_NOT_FOUND; } return rc; } +- (int) getPrHtml: (void **) data +{ + id result; + NSData *content; + NSDictionary *partHeaderData; + NSString *key, *encoding; + char *oldBytes, *newBytes; + NSUInteger c, newC, max, newMax; + NSMutableArray *keys; + NSArray *acceptedTypes; + int rc = MAPISTORE_SUCCESS; + + acceptedTypes = [NSArray arrayWithObject: @"text/html"]; + keys = [NSMutableArray array]; + [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] + path: @"" toArray: keys + acceptedTypes: acceptedTypes]; + if ([keys count] > 0) + { + result = [sogoObject fetchParts: [keys objectsForKey: @"key" + notFoundMarker: nil]]; + result = [[result valueForKey: @"RawResponse"] objectForKey: + @"fetch"]; + key = [[keys objectAtIndex: 0] objectForKey: @"key"]; + content = [[result objectForKey: key] objectForKey: @"data"]; + + max = [content length]; + newMax = max; + oldBytes = malloc (max); + newBytes = malloc (max * 2); + [content getBytes: oldBytes]; + newC = 0; + for (c = 0; c < max; c++) + { + if (*(oldBytes + c) == '\n') + { + *(newBytes + newC) = '\r'; + newC++; + newMax++; + } + *(newBytes + newC) = *(oldBytes + c); + newC++; + } + content = [[NSData alloc] initWithBytesNoCopy: newBytes + length: newMax];; + [content autorelease]; + + partHeaderData + = [sogoObject lookupInfoForBodyPart: [key _strippedBodyKey]]; + encoding = [partHeaderData objectForKey: @"encoding"]; + content = [content bodyDataFromEncoding: encoding]; + *data = [content asBinaryInMemCtx: memCtx]; + } + else + { + *data = NULL; + rc = MAPISTORE_ERR_NOT_FOUND; + } + + return rc; +} + +- (int) getPrRtfCompressed: (void **) data +{ + *data = NULL; + + return MAPISTORE_ERR_NOT_FOUND; +} + +- (int) getPrRtfInSync: (void **) data +{ + return [self getNo: data]; +} + +- (int) getPrInternetMessageId: (void **) data +{ + *data = [[sogoObject messageId] asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrReadReceiptRequested: (void **) data // TODO +{ + return [self getNo: data]; +} + +- (int) getPrDeleteAfterSubmit: (void **) data // TODO +{ + return [self getNo: data]; +} + +- (int) getPidLidPrivate: (void **) data +{ + return [self getNo: data]; +} + +- (int) getPrMsgEditorFormat: (void **) data +{ + NSMutableArray *keys; + NSArray *acceptedTypes; + uint32_t format; + + format = 0; /* EDITOR_FORMAT_DONTKNOW */ + + acceptedTypes = [NSArray arrayWithObject: @"text/plain"]; + keys = [NSMutableArray array]; + [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] + path: @"" toArray: keys + acceptedTypes: acceptedTypes]; + if ([keys count] == 1) + format = EDITOR_FORMAT_PLAINTEXT; + + acceptedTypes = [NSArray arrayWithObject: @"text/html"]; + [keys removeAllObjects]; + [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] + path: @"" toArray: keys + acceptedTypes: acceptedTypes]; + if ([keys count] == 1) + format = EDITOR_FORMAT_HTML; + + *data = MAPILongValue (memCtx, format); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidReminderSet: (void **) data // TODO +{ + return [self getNo: data]; +} + +- (int) getPidLidUseTnef: (void **) data // TODO +{ + return [self getNo: data]; +} + +- (int) getPidLidRemoteStatus: (void **) data // TODO +{ + return [self getLongZero: data]; +} + +- (int) getPidLidAgingDontAgeMe: (void **) data // TODO +{ + return [self getYes: data]; +} + - (void) openMessage: (struct mapistore_message *) msg { struct SRowSet *recipients; diff --git a/OpenChange/MAPIStoreMessage.h b/OpenChange/MAPIStoreMessage.h index 0bed90bbc..73af085ab 100644 --- a/OpenChange/MAPIStoreMessage.h +++ b/OpenChange/MAPIStoreMessage.h @@ -48,6 +48,9 @@ - (void) openMessage: (struct mapistore_message *) msg; +/* helper getters */ +- (int) getSMTPAddrType: (void **) data; + /* subclasses */ - (void) submit; - (void) save; diff --git a/OpenChange/MAPIStoreMessage.m b/OpenChange/MAPIStoreMessage.m index 05953a4a5..1e524f512 100644 --- a/OpenChange/MAPIStoreMessage.m +++ b/OpenChange/MAPIStoreMessage.m @@ -22,9 +22,12 @@ #import #import +#import #import #import +#import "MAPIStoreAttachmentTable.h" +#import "MAPIStoreContext.h" #import "MAPIStoreTypes.h" #import "NSData+MAPIStore.h" #import "NSString+MAPIStore.h" @@ -127,146 +130,274 @@ msg->properties = properties; } -- (int) getProperty: (void **) data - withTag: (enum MAPITAGS) propTag +/* helper getters */ +- (int) getSMTPAddrType: (void **) data { - int rc; + *data = [@"SMTP" asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +/* getters */ +- (int) getPrInstId: (void **) data // TODO: DOUBT +{ + /* we return a unique id based on the key */ + *data = MAPILongLongValue (memCtx, [[sogoObject nameInContainer] hash]); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrInstanceNum: (void **) data // TODO: DOUBT +{ + return [self getLongZero: data]; +} + +- (int) getPrRowType: (void **) data // TODO: DOUBT +{ + *data = MAPILongValue (memCtx, TBL_LEAF_ROW); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrDepth: (void **) data // TODO: DOUBT +{ + *data = MAPILongLongValue (memCtx, 0); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrAccess: (void **) data // TODO +{ + *data = MAPILongValue (memCtx, 0x03); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrAccessLevel: (void **) data // TODO +{ + *data = MAPILongValue (memCtx, 0x01); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrViewStyle: (void **) data +{ + return [self getLongZero: data]; +} + +- (int) getPrViewMajorversion: (void **) data +{ + return [self getLongZero: data]; +} + +- (int) getPidLidSideEffects: (void **) data // TODO +{ + return [self getLongZero: data]; +} + +- (int) getPidLidCurrentVersion: (void **) data +{ + *data = MAPILongValue (memCtx, 115608); // Outlook 11.5608 + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidCurrentVersionName: (void **) data +{ + *data = [@"11.0" asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidAutoProcessState: (void **) data +{ + *data = MAPILongValue (memCtx, 0x00000000); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidNameContentClass: (void **) data +{ + *data = [@"Sharing" asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrFid: (void **) data +{ + *data = MAPILongLongValue (memCtx, [container objectId]); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMid: (void **) data +{ + *data = MAPILongLongValue (memCtx, [self objectId]); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMessageLocaleId: (void **) data +{ + *data = MAPILongValue (memCtx, 0x0409); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMessageFlags: (void **) data // TODO +{ + *data = MAPILongValue (memCtx, MSGFLAG_FROMME | MSGFLAG_READ | MSGFLAG_UNMODIFIED); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMessageSize: (void **) data // TODO +{ + /* TODO: choose another name in SOGo for that method */ + *data = MAPILongValue (memCtx, [[sogoObject davContentLength] intValue]); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMsgStatus: (void **) data // TODO +{ + return [self getLongZero: data]; +} + +- (int) getPrImportance: (void **) data // TODO -> subclass? +{ + *data = MAPILongValue (memCtx, 1); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrPriority: (void **) data // TODO -> subclass? +{ + return [self getLongZero: data]; +} + +- (int) getPrSensitivity: (void **) data // TODO -> subclass in calendar +{ + return [self getLongZero: data]; +} + +// TODO: PR_CHANGE_KEY is a GID based on the ReplGUID +- (int) getPrChangeKey: (void **) data +{ + int rc = MAPISTORE_SUCCESS; NSString *stringValue; NSUInteger length; - rc = MAPI_E_SUCCESS; - switch ((uint32_t) propTag) + stringValue = [sogoObject davEntityTag]; + if (stringValue) { - case PR_INST_ID: // TODO: DOUBT - /* we return a unique id based on the key */ - *data = MAPILongLongValue (memCtx, [[sogoObject nameInContainer] hash]); - break; - case PR_INSTANCE_NUM: // TODO: DOUBT - *data = MAPILongValue (memCtx, 0); - break; - case PR_ROW_TYPE: // TODO: DOUBT - *data = MAPILongValue (memCtx, TBL_LEAF_ROW); - break; - case PR_DEPTH: // TODO: DOUBT - *data = MAPILongLongValue (memCtx, 0); - break; - case PR_ACCESS: // TODO - *data = MAPILongValue (memCtx, 0x03); - break; - case PR_ACCESS_LEVEL: // TODO - *data = MAPILongValue (memCtx, 0x01); - break; - case PR_VIEW_STYLE: - case PR_VIEW_MAJORVERSION: - *data = MAPILongValue (memCtx, 0); - break; - case PidLidSideEffects: // TODO - *data = MAPILongValue (memCtx, 0x00000000); - break; - case PidLidCurrentVersion: - *data = MAPILongValue (memCtx, 115608); // Outlook 11.5608 - break; - case PidLidCurrentVersionName: - *data = [@"11.0" asUnicodeInMemCtx: memCtx]; - break; - case PidLidAutoProcessState: - *data = MAPILongValue (memCtx, 0x00000000); - break; - case PidNameContentClass: - *data = [@"Sharing" asUnicodeInMemCtx: memCtx]; - break; - case PR_FID: - *data = MAPILongLongValue (memCtx, [container objectId]); - break; - case PR_MID: - *data = MAPILongLongValue (memCtx, [self objectId]); - break; - case PR_MESSAGE_LOCALE_ID: - *data = MAPILongValue (memCtx, 0x0409); - break; - case PR_MESSAGE_FLAGS: // TODO - *data = MAPILongValue (memCtx, MSGFLAG_FROMME | MSGFLAG_READ | MSGFLAG_UNMODIFIED); - break; - case PR_MESSAGE_SIZE: // TODO - /* TODO: choose another name in SOGo for that method */ - *data = MAPILongValue (memCtx, [[sogoObject davContentLength] intValue]); - break; - case PR_MSG_STATUS: // TODO - *data = MAPILongValue (memCtx, 0); - break; - case PR_IMPORTANCE: // TODO -> subclass? - *data = MAPILongValue (memCtx, 1); - break; - case PR_PRIORITY: // TODO -> subclass? - *data = MAPILongValue (memCtx, 0); - break; - case PR_SENSITIVITY: // TODO -> subclass in calendar - *data = MAPILongValue (memCtx, 0); - break; - case PR_CHANGE_KEY: - stringValue = [sogoObject davEntityTag]; - if (stringValue) - { - stringValue = @"-1"; - length = [stringValue length]; - if (length < 6) /* guid = 16 bytes */ - { - length += 6; - stringValue = [NSString stringWithFormat: @"000000%@", - stringValue]; - } - if (length > 6) - stringValue = [stringValue substringFromIndex: length - 6]; - stringValue = [NSString stringWithFormat: @"SOGo%@%@%@", - stringValue, stringValue, stringValue]; - *data = [[stringValue dataUsingEncoding: NSASCIIStringEncoding] - asShortBinaryInMemCtx: memCtx]; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - break; - - case PR_ORIGINAL_SUBJECT_UNICODE: - case PR_CONVERSATION_TOPIC_UNICODE: - rc = [self getProperty: data withTag: PR_NORMALIZED_SUBJECT_UNICODE]; - break; - - case PR_SUBJECT_PREFIX_UNICODE: - *data = [@"" asUnicodeInMemCtx: memCtx]; - break; - case PR_NORMALIZED_SUBJECT_UNICODE: - rc = [self getProperty: data withTag: PR_SUBJECT_UNICODE]; - break; - - case PR_DISPLAY_TO_UNICODE: - case PR_DISPLAY_CC_UNICODE: - case PR_DISPLAY_BCC_UNICODE: - case PR_ORIGINAL_DISPLAY_TO_UNICODE: - case PR_ORIGINAL_DISPLAY_CC_UNICODE: - case PR_ORIGINAL_DISPLAY_BCC_UNICODE: - *data = [@"" asUnicodeInMemCtx: memCtx]; - break; - case PR_LAST_MODIFIER_NAME_UNICODE: - *data = [@"openchange" asUnicodeInMemCtx: memCtx]; - break; - - case PR_ORIG_MESSAGE_CLASS_UNICODE: - rc = [self getProperty: data withTag: PR_MESSAGE_CLASS_UNICODE]; - break; - - case PR_HASATTACH: - *data = MAPIBoolValue (memCtx, - [[self childKeysMatchingQualifier: nil - andSortOrderings: nil] count] > 0); - break; - - default: - rc = [super getProperty: data withTag: propTag]; + stringValue = @"-1"; + length = [stringValue length]; + if (length < 6) /* guid = 16 bytes */ + length += 6; + stringValue = [NSString stringWithFormat: @"000000%@", + stringValue]; + if (length > 6) + stringValue = [stringValue substringFromIndex: length - 6]; + stringValue = [NSString stringWithFormat: @"SOGo%@%@%@", + stringValue, stringValue, stringValue]; + *data = [[stringValue dataUsingEncoding: NSASCIIStringEncoding] + asBinaryInMemCtx: memCtx]; } + else + rc = MAPISTORE_ERR_NOT_FOUND; return rc; } +- (int) getPrSubject: (void **) data +{ + [self subclassResponsibility: _cmd]; + + return MAPISTORE_ERR_NOT_FOUND; +} + +- (int) getPrNormalizedSubject: (void **) data +{ + return [self getPrSubject: data]; +} + +- (int) getPrOriginalSubject: (void **) data +{ + return [self getPrNormalizedSubject: data]; +} + +- (int) getPrConversationTopic: (void **) data +{ + return [self getPrNormalizedSubject: data]; +} + +- (int) getPrSubjectPrefix: (void **) data +{ + return [self getEmptyString: data]; +} + +- (int) getPrDisplayTo: (void **) data +{ + return [self getEmptyString: data]; +} + +- (int) getPrDisplayCc: (void **) data +{ + return [self getEmptyString: data]; +} + +- (int) getPrDisplayBcc: (void **) data +{ + return [self getEmptyString: data]; +} + +- (int) getPrOriginalDisplayTo: (void **) data +{ + return [self getPrDisplayTo: data]; +} + +- (int) getPrOriginalDisplayCc: (void **) data +{ + return [self getPrDisplayCc: data]; +} + +- (int) getPrOriginalDisplayBcc: (void **) data +{ + return [self getPrDisplayBcc: data]; +} + +- (int) getPrLastModifierName: (void **) data +{ + NSURL *contextUrl; + + contextUrl = [[self context] url]; + *data = [[contextUrl user] asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMessageClass: (void **) data +{ + [self subclassResponsibility: _cmd]; + + return MAPISTORE_ERR_NOT_FOUND; +} + +- (int) getPrOrigMessageClass: (void **) data +{ + return [self getPrMessageClass: data]; +} + +- (int) getPrHasattach: (void **) data +{ + *data = MAPIBoolValue (memCtx, + [[self childKeysMatchingQualifier: nil + andSortOrderings: nil] count] > 0); + + return MAPISTORE_SUCCESS; +} + - (void) save { [self subclassResponsibility: _cmd]; @@ -286,9 +417,7 @@ - (MAPIStoreAttachmentTable *) attachmentTable { - [self subclassResponsibility: _cmd]; - - return nil; + return [MAPIStoreAttachmentTable tableForContainer: self]; } - (void) addActiveTable: (MAPIStoreTable *) activeTable diff --git a/OpenChange/MAPIStoreNotesMessage.m b/OpenChange/MAPIStoreNotesMessage.m index 51896f499..bb6821b81 100644 --- a/OpenChange/MAPIStoreNotesMessage.m +++ b/OpenChange/MAPIStoreNotesMessage.m @@ -24,35 +24,27 @@ #import "MAPIStoreNotesMessage.h" +#include + @implementation MAPIStoreNotesMessage -- (enum MAPISTATUS) getProperty: (void **) data - withTag: (enum MAPITAGS) propTag +- (int) getPrIconIndex: (void **) data // TODO { - int rc; + /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */ + // *longValue = 0x00000300 for blue + // *longValue = 0x00000301 for green + // *longValue = 0x00000302 for pink + // *longValue = 0x00000303 for yellow + // *longValue = 0x00000304 for white + *data = MAPILongValue (memCtx, 0x00000303); + + return MAPISTORE_SUCCESS; +} - rc = MAPI_E_SUCCESS; - switch (propTag) - { - case PR_ICON_INDEX: // TODO - /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */ - // *longValue = 0x00000300 for blue - // *longValue = 0x00000301 for green - // *longValue = 0x00000302 for pink - // *longValue = 0x00000303 for yellow - // *longValue = 0x00000304 for white - *data = MAPILongValue (memCtx, 0x00000303); - break; - - case PR_SUBJECT_UNICODE: - rc = [super getProperty: data - withTag: PR_NORMALIZED_SUBJECT_UNICODE]; - break; - default: - rc = [super getProperty: data withTag: propTag]; - } - - return rc; +- (int) getPrSubject: (void **) data +{ + return [self getProperty: data + withTag: PR_NORMALIZED_SUBJECT_UNICODE]; } @end diff --git a/OpenChange/MAPIStoreObject.h b/OpenChange/MAPIStoreObject.h index 3a9f061ca..c6916567d 100644 --- a/OpenChange/MAPIStoreObject.h +++ b/OpenChange/MAPIStoreObject.h @@ -36,6 +36,8 @@ @interface MAPIStoreObject : NSObject { + const IMP *classGetters; + NSMutableArray *parentContainersBag; MAPIStoreObject *container; id sogoObject; @@ -46,6 +48,8 @@ + (id) mapiStoreObjectWithSOGoObject: (id) newSOGoObject inContainer: (MAPIStoreObject *) newContainer; ++ (int) getAvailableProperties: (struct SPropTagArray *) properties; + - (id) initWithSOGoObject: (id) newSOGoObject inContainer: (MAPIStoreObject *) newFolder; @@ -74,6 +78,7 @@ - (void) resetNewProperties; /* ops */ +- (int) getAvailableProperties: (struct SPropTagArray *) properties; - (int) getProperties: (struct mapistore_property_data *) data withTags: (enum MAPITAGS *) tags andCount: (uint16_t) columnCount; @@ -83,6 +88,12 @@ - (int) getProperty: (void **) data withTag: (enum MAPITAGS) propTag; +/* helper getters */ +- (int) getEmptyString: (void **) data; +- (int) getLongZero: (void **) data; +- (int) getYes: (void **) data; +- (int) getNo: (void **) data; + /* subclasses */ - (id) lookupChild: (NSString *) childKey; - (NSArray *) childKeysMatchingQualifier: (EOQualifier *) qualifier diff --git a/OpenChange/MAPIStoreObject.m b/OpenChange/MAPIStoreObject.m index d06738945..f97014007 100644 --- a/OpenChange/MAPIStoreObject.m +++ b/OpenChange/MAPIStoreObject.m @@ -25,6 +25,7 @@ #import #import "MAPIStoreFolder.h" +#import "MAPIStorePropertySelectors.h" #import "MAPIStoreTypes.h" #import "NSData+MAPIStore.h" #import "NSString+MAPIStore.h" @@ -60,10 +61,35 @@ static Class NSExceptionK, MAPIStoreFolderK; return newObject; } ++ (int) getAvailableProperties: (struct SPropTagArray *) properties +{ + const MAPIStorePropertyGetter *classGetters; + NSUInteger count; + enum MAPITAGS propTag; + uint16_t propValue; + + properties->aulPropTag = talloc_array (properties, enum MAPITAGS, + MAPIStoreSupportedPropertiesCount); + classGetters = MAPIStorePropertyGettersForClass (self); + for (count = 0; count < MAPIStoreSupportedPropertiesCount; count++) + { + propTag = MAPIStoreSupportedProperties[count]; + propValue = (propTag & 0xffff0000) >> 16; + if (classGetters[propValue]) + { + properties->aulPropTag[properties->cValues] = propTag; + properties->cValues++; + } + } + + return 0; +} + - (id) init { if ((self = [super init])) { + classGetters = (IMP *) MAPIStorePropertyGettersForClass (isa); parentContainersBag = [NSMutableArray new]; container = nil; sogoObject = nil; @@ -190,53 +216,96 @@ static Class NSExceptionK, MAPIStoreFolderK; - (int) getProperty: (void **) data withTag: (enum MAPITAGS) propTag { - NSString *stringValue; - int rc; + MAPIStorePropertyGetter method = NULL; + uint16_t propValue; + SEL methodSel; const char *propName; + int rc = MAPISTORE_ERR_NOT_FOUND; - /* TODO: handle unsaved properties */ + propValue = (propTag & 0xffff0000) >> 16; + methodSel = MAPIStoreSelectorForPropertyGetter (propValue); - rc = MAPISTORE_SUCCESS; - switch (propTag) + method = (MAPIStorePropertyGetter) classGetters[propValue]; + if (method) + rc = method (self, methodSel, data); + else { - case PR_DISPLAY_NAME_UNICODE: - *data = [[sogoObject displayName] asUnicodeInMemCtx: memCtx]; - break; - case PR_SEARCH_KEY: // TODO - stringValue = [sogoObject nameInContainer]; - *data = [[stringValue dataUsingEncoding: NSASCIIStringEncoding] - asBinaryInMemCtx: memCtx]; - break; - case PR_GENERATE_EXCHANGE_VIEWS: // TODO - *data = MAPIBoolValue (memCtx, NO); - break; - - default: - propName = get_proptag_name (propTag); - if (!propName) - propName = ""; - [self warnWithFormat: - @"unhandled or NULL value: %s (0x%.8x), childKey: %@", - propName, propTag, [sogoObject nameInContainer]]; - // if ((propTag & 0x001F) == 0x001F) - // { - // stringValue = [NSString stringWithFormat: @"fake %s (0x.8x) value", - // propName, propTag]; - // *data = [stringValue asUnicodeInMemCtx: memCtx]; - // rc = MAPISTORE_SUCCESS; - // } - // else - // { - *data = NULL; - rc = MAPISTORE_ERR_NOT_FOUND; - // } - break; + *data = NULL; + + if (methodSel) + { + propName = get_proptag_name (propTag); + if (!propName) + propName = ""; + [self warnWithFormat: + @"unimplemented selector (%@) for %s (0x%.8x)", + NSStringFromSelector (methodSel), propName, propTag]; + } + else + [self warnWithFormat: @"unsupported property tag: 0x%.8x", propTag]; } return rc; } -/* MAPIStoreProperty protocol */ +/* helper getters */ +- (int) getEmptyString: (void **) data +{ + *data = [@"" asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getLongZero: (void **) data +{ + *data = MAPILongValue (memCtx, 0); + + return MAPISTORE_SUCCESS; +} + +- (int) getYes: (void **) data +{ + *data = MAPIBoolValue (memCtx, YES); + + return MAPISTORE_SUCCESS; +} + +- (int) getNo: (void **) data +{ + *data = MAPIBoolValue (memCtx, NO); + + return MAPISTORE_SUCCESS; +} + +/* getters */ + - (int) getPrDisplayName: (void **) data +{ + *data = [[sogoObject displayName] asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrSearchKey: (void **) data +{ + NSString *stringValue; + + stringValue = [sogoObject nameInContainer]; + *data = [[stringValue dataUsingEncoding: NSASCIIStringEncoding] + asBinaryInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrGenerateExchangeViews: (void **) data +{ + return [self getNo: data]; +} + +- (int) getAvailableProperties: (struct SPropTagArray *) properties +{ + return [isa getAvailableProperties: properties]; +} + - (int) getProperties: (struct mapistore_property_data *) data withTags: (enum MAPITAGS *) tags andCount: (uint16_t) columnCount @@ -277,8 +346,6 @@ static Class NSExceptionK, MAPIStoreFolderK; - (NSArray *) childKeysMatchingQualifier: (EOQualifier *) qualifier andSortOrderings: (NSArray *) sortOrderings { - [self subclassResponsibility: _cmd]; - return nil; } diff --git a/OpenChange/MAPIStoreSOGo.m b/OpenChange/MAPIStoreSOGo.m index b13303dc8..f9973c3a8 100644 --- a/OpenChange/MAPIStoreSOGo.m +++ b/OpenChange/MAPIStoreSOGo.m @@ -632,68 +632,6 @@ sogo_op_setprops(void *private_data, return rc; } -static int -sogo_op_set_property_from_fd(void *private_data, - uint64_t fmid, uint8_t type, - uint32_t property, int fd) -{ - NSAutoreleasePool *pool; - sogo_context *cContext; - MAPIStoreContext *context; - NSFileHandle *fileHandle; - int rc; - - DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__)); - - pool = [NSAutoreleasePool new]; - - cContext = private_data; - context = cContext->objcContext; - [context setupRequest]; - - fileHandle = [[NSFileHandle alloc] initWithFileDescriptor: fd - closeOnDealloc: NO]; - rc = [context setProperty: property withFMID: fmid ofTableType: type - fromFile: fileHandle]; - [fileHandle release]; - - [context tearDownRequest]; - [pool release]; - - return rc; -} - -static int -sogo_op_get_property_into_fd(void *private_data, - uint64_t fmid, uint8_t type, - uint32_t property, int fd) -{ - NSAutoreleasePool *pool; - sogo_context *cContext; - MAPIStoreContext *context; - NSFileHandle *fileHandle; - int rc; - - DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__)); - - pool = [NSAutoreleasePool new]; - - cContext = private_data; - context = cContext->objcContext; - [context setupRequest]; - - fileHandle = [[NSFileHandle alloc] initWithFileDescriptor: fd - closeOnDealloc: NO]; - rc = [context getProperty: property withFMID: fmid ofTableType: type - intoFile: fileHandle]; - [fileHandle release]; - - [context tearDownRequest]; - [pool release]; - - return rc; -} - static int sogo_op_modifyrecipients(void *private_data, uint64_t mid, @@ -1006,6 +944,30 @@ sogo_pocop_open_embedded_message (void *attachment_object, return rc; } +static int sogo_pocop_get_available_table_properties(void *table_object, struct SPropTagArray *properties) +{ + NSAutoreleasePool *pool; + MAPIStoreTable *table; + int rc; + + DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__)); + + table = table_object; + if (table) + { + pool = [NSAutoreleasePool new]; + rc = [table getAvailableProperties: properties]; + [pool release]; + } + else + { + NSLog (@" UNEXPECTED WEIRDNESS: RECEIVED NO DATA"); + rc = MAPI_E_NOT_FOUND; + } + + return rc; +} + static int sogo_pocop_set_table_columns (void *table_object, uint16_t count, enum MAPITAGS *properties) { @@ -1113,6 +1075,30 @@ sogo_pocop_get_table_row (void *table_object, enum table_query_type query_type, return rc; } +static int sogo_pocop_get_available_properties(void *object, struct SPropTagArray *properties) +{ + NSAutoreleasePool *pool; + MAPIStoreObject *propObject; + int rc; + + DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__)); + + propObject = object; + if (propObject) + { + pool = [NSAutoreleasePool new]; + rc = [propObject getAvailableProperties: properties]; + [pool release]; + } + else + { + NSLog (@" UNEXPECTED WEIRDNESS: RECEIVED NO DATA"); + rc = MAPI_E_NOT_FOUND; + } + + return rc; +} + static int sogo_pocop_get_properties (void *object, uint16_t count, enum MAPITAGS *properties, @@ -1243,8 +1229,6 @@ int mapistore_init_backend(void) backend.op_setprops = sogo_op_setprops; backend.op_getprops = sogo_op_getprops; - backend.op_set_property_from_fd = sogo_op_set_property_from_fd; - backend.op_get_property_into_fd = sogo_op_get_property_into_fd; /* proof of concept */ backend.folder.open_table = sogo_pocop_open_table; @@ -1252,10 +1236,12 @@ int mapistore_init_backend(void) backend.message.get_attachment = sogo_pocop_get_attachment; backend.message.create_attachment = sogo_pocop_create_attachment; backend.message.open_embedded_message = sogo_pocop_open_embedded_message; + backend.table.get_available_properties = sogo_pocop_get_available_table_properties; backend.table.set_restrictions = sogo_pocop_set_table_restrictions; backend.table.set_sort_order = sogo_pocop_set_table_sort_order; backend.table.set_columns = sogo_pocop_set_table_columns; backend.table.get_row = sogo_pocop_get_table_row; + backend.properties.get_available_properties = sogo_pocop_get_available_properties; backend.properties.get_properties = sogo_pocop_get_properties; backend.properties.set_properties = sogo_pocop_set_properties; backend.store.release = sogo_pocop_release; diff --git a/OpenChange/MAPIStoreTable.h b/OpenChange/MAPIStoreTable.h index 7774c3196..cf199c1ef 100644 --- a/OpenChange/MAPIStoreTable.h +++ b/OpenChange/MAPIStoreTable.h @@ -68,6 +68,7 @@ typedef enum { } + (id) tableForContainer: (MAPIStoreObject *) newContainer; ++ (Class) childObjectClass; - (id) initForContainer: (MAPIStoreObject *) newContainer; @@ -81,6 +82,7 @@ typedef enum { - (void) cleanupCaches; +- (int) getAvailableProperties: (struct SPropTagArray *) properties; - (void) setRestrictions: (const struct mapi_SRestriction *) res; - (int) setColumns: (enum MAPITAGS *) newColumns withCount: (uint16_t) newColumCount; diff --git a/OpenChange/MAPIStoreTable.m b/OpenChange/MAPIStoreTable.m index 9831142d2..210e4b3e0 100644 --- a/OpenChange/MAPIStoreTable.m +++ b/OpenChange/MAPIStoreTable.m @@ -26,6 +26,7 @@ #import #import "EOBitmaskQualifier.h" +#import "MAPIStoreObject.h" #import "MAPIStoreTypes.h" #import "NSData+MAPIStore.h" #import "NSString+MAPIStore.h" @@ -259,6 +260,13 @@ static Class NSDataK, NSStringK; return newTable; } ++ (Class) childObjectClass +{ + [self subclassResponsibility: _cmd]; + + return Nil; +} + - (id) init { if ((self = [super init])) @@ -358,6 +366,11 @@ static Class NSDataK, NSStringK; currentRow = (uint32_t) -1; } +- (int) getAvailableProperties: (struct SPropTagArray *) properties +{ + return [[isa childObjectClass] getAvailableProperties: properties]; +} + - (void) setRestrictions: (const struct mapi_SRestriction *) res { EOQualifier *oldRestriction; diff --git a/OpenChange/MAPIStoreTasksMessage.h b/OpenChange/MAPIStoreTasksMessage.h index 273cde7cb..ad3ddcd40 100644 --- a/OpenChange/MAPIStoreTasksMessage.h +++ b/OpenChange/MAPIStoreTasksMessage.h @@ -25,7 +25,12 @@ #import "MAPIStoreGCSMessage.h" +@class iCalToDo; + @interface MAPIStoreTasksMessage : MAPIStoreGCSMessage +{ + iCalToDo *task; +} @end diff --git a/OpenChange/MAPIStoreTasksMessage.m b/OpenChange/MAPIStoreTasksMessage.m index 581ab5c9b..b21bd5f67 100644 --- a/OpenChange/MAPIStoreTasksMessage.m +++ b/OpenChange/MAPIStoreTasksMessage.m @@ -49,221 +49,212 @@ @implementation MAPIStoreTasksMessage -- (enum MAPISTATUS) getProperty: (void **) data - withTag: (enum MAPITAGS) propTag +- (id) initWithSOGoObject: (id) newSOGoObject + inContainer: (MAPIStoreObject *) newContainer { - NSString *status; - iCalToDo *task; - int32_t statusValue; - NSCalendarDate *dateValue; - int rc; - double doubleValue; - - rc = MAPI_E_SUCCESS; - switch ((uint32_t) propTag) + if ((self = [super initWithSOGoObject: newSOGoObject + inContainer: newContainer])) { - case PR_ICON_INDEX: // TODO - /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */ - // Unassigned recurring task 0x00000501 - // Assignee's task 0x00000502 - // Assigner's task 0x00000503 - // Task request 0x00000504 - // Task acceptance 0x00000505 - // Task rejection 0x00000506 - *data = MAPILongValue (memCtx, 0x00000500); - break; - case PR_MESSAGE_CLASS_UNICODE: - *data = talloc_strdup(memCtx, "IPM.Task"); - break; - case PR_SUBJECT_UNICODE: // SUMMARY - task = [sogoObject component: NO secure: NO]; - *data = [[task summary] asUnicodeInMemCtx: memCtx]; - break; - - // - // Not to be confused with PR_PRIORITY - // - // IMPORTANCE_LOW = 0x0, IMPORTANCE_NORMAL = 0x1 and IMPORTANCE_HIGH = 0x2 - // - case PR_IMPORTANCE: - { - unsigned int v; - - task = [sogoObject component: NO secure: NO]; - - if ([[task priority] isEqualToString: @"9"]) - v = 0x0; - else if ([[task priority] isEqualToString: @"1"]) - v = 0x2; - else - v = 0x1; - - *data = MAPILongValue (memCtx, v); - } - break; - case PidLidTaskComplete: - task = [sogoObject component: NO secure: NO]; - *data = MAPIBoolValue (memCtx, - [[task status] isEqualToString: @"COMPLETED"]); - break; - case PidLidPercentComplete: - task = [sogoObject component: NO secure: NO]; - doubleValue = ((double) [[task percentComplete] intValue] / 100); - *data = MAPIDoubleValue (memCtx, doubleValue); - break; - case PidLidTaskDateCompleted: - task = [sogoObject component: NO secure: NO]; - dateValue = [task completed]; - if (dateValue) - *data = [dateValue asFileTimeInMemCtx: memCtx]; - else - rc = MAPISTORE_ERR_NOT_FOUND; - break; - // http://msdn.microsoft.com/en-us/library/cc765590.aspx - // It's important to have a proper value for PidLidTaskState - // as it'll affect the UI options of Outlook - making the - // task non-editable in some cases. - case PidLidTaskState: - *data = MAPILongValue (memCtx, 0x1); // not assigned - break; - case PidLidTaskMode: // TODO - *data = MAPILongValue (memCtx, 0x0); - break; - case PidLidTaskFRecurring: - case PidLidTaskAccepted: // TODO - *data = MAPIBoolValue (memCtx, NO); - break; - case PidLidTaskActualEffort: // TODO - case PidLidTaskEstimatedEffort: // TODO - *data = MAPILongValue (memCtx, 0); - break; - case PR_HASATTACH: - *data = MAPIBoolValue (memCtx, NO); - break; - - case PidLidTaskDueDate: - task = [sogoObject component: NO secure: NO]; - dateValue = [task due]; - if (dateValue) - *data = [dateValue asFileTimeInMemCtx: memCtx]; - else - rc = MAPISTORE_ERR_NOT_FOUND; - break; - - case PR_CREATION_TIME: - task = [sogoObject component: NO secure: NO]; - *data = [[task created] asFileTimeInMemCtx: memCtx]; - break; - case PR_MESSAGE_DELIVERY_TIME: - case PR_CLIENT_SUBMIT_TIME: - case PR_LOCAL_COMMIT_TIME: - case PR_LAST_MODIFICATION_TIME: - task = [sogoObject component: NO secure: NO]; - *data = [[task lastModified] asFileTimeInMemCtx: memCtx]; - break; - case PidLidTaskStatus: // status - task = [sogoObject component: NO secure: NO]; - status = [task status]; - if (![status length] - || [status isEqualToString: @"NEEDS-ACTION"]) - statusValue = 0; - else if ([status isEqualToString: @"IN-PROCESS"]) - statusValue = 1; - else if ([status isEqualToString: @"COMPLETED"]) - statusValue = 2; - else - statusValue = 0xff; - *data = MAPILongValue (memCtx, statusValue); - break; - /* Completed */ - // - 0x81380003 = -2000 - // + 0x81380003 = -4000 - - // 68330048 - // 68420102 - case 0x68340003: - case 0x683a0003: - case 0x68410003: - *data = MAPILongValue (memCtx, 0); - break; - - // FIXME - use the current user - case PidLidTaskOwner: - *data = [@"openchange@example.com" asUnicodeInMemCtx: memCtx]; - break; - - // See http://msdn.microsoft.com/en-us/library/cc842113.aspx - case PidLidTaskOwnership: - *data = MAPILongValue (memCtx, 0x0); // not assigned - break; - -// #define PidLidFlagRequest 0x9027001f -// #define PidNameContentType 0x905a001f -// #define PidLidBillingInformation 0x908b001f -// #define PidLidTaskStartDate 0x911e0040 -// #define PidLidTaskOwner 0x9122001f -// #define PidLidTaskDeadOccurrence 0x9127000b -// #define PidLidTaskMultipleRecipients 0x912a0003 -// #define PidLidTaskHistory 0x912b0003 -// #define PidLidAcceptanceState 0x912c0003 -// #define PidLidTaskLastUser 0x912d001f -// #define PidLidTaskLastUpdate 0x912e0040 -// #define PidLidTaskOwnership 0x912f0003 -// #define PidLidTaskNoCompute 0x9130000b -// #define PidLidTaskFFixOffline 0x9131000b -// #define PidLidTaskRole 0x9132001f -// #define PidLidTaskVersion 0x91330003 -// #define PidLidTaskAssigner 0x9134001f -// #define PidLidTeamTask 0x9135000b -// #define PidLidTaskRecurrence 0x91360102 -// #define PidLidTaskResetReminder 0x9137000b -// #define PidLidTaskOrdinal 0x91380003 -// #define PidLidMileage 0x914a001f -// #define PidLidAgingDontAgeMe 0x9185000b -// #define PidLidCommonEnd 0x91980040 -// #define PidLidCommonStart 0x91990040 -// #define PidLidNonSendableBcc 0x91d7001f -// #define PidLidNonSendableCc 0x91d8001f -// #define PidLidNonSendtableTo 0x91d9001f -// #define PidLidNonSendBccTrackStatus 0x91da1003 -// #define PidLidNonSendCcTrackStatus 0x91db1003 -// #define PidLidNonSendToTrackStatus 0x91dc1003 -// #define PidLidReminderDelta 0x91e90003 -// #define PidLidReminderFileParameter 0x91ea001f -// #define PidLidReminderSignalTime 0x91eb0040 -// #define PidLidReminderOverride 0x91ec000b -// #define PidLidReminderPlaySound 0x91ed000b -// #define PidLidReminderSet 0x91ee000b -// #define PidLidReminderTime 0x91ef0040 -// #define PidLidReminderType 0x91f20003 -// #define PidLidRemoteStatus 0x91f30003 -// #define PidLidSmartNoAttach 0x91fa000b -// #define PidLidTaskGlobalId 0x91fe0102 -// #define PidLidVerbResponse 0x9203001f -// #define PidLidVerbStream 0x92040102 -// #define PidLidPrivate 0x9224000b -// #define PidLidInternetAccountName 0x9225001f -// #define PidLidInternetAccountStamp 0x9226001f -// #define PidLidUseTnef 0x9227000b -// #define PidLidContactLinkName 0x9229001f -// #define PidLidContactLinkEntry 0x922a0102 -// #define PidLidContactLinkSearchKey 0x922b0102 -// #define PidLidSpamOriginalFolder 0x92370102 -// #define PidLidTaskUpdates 0x9345000b -// #define PidLidTaskStatusOnComplete 0x9346000b -// #define PidLidTaskLastDelegate 0x9347001f -// #define PidLidTaskAssigners 0x934a0102 -// #define PidLidTaskFCreator 0x934c000b -// #define PidLidImapDeleted 0x94e50003 -// #define PidLidHeaderItem 0x94e60003 - - default: - rc = [super getProperty: data withTag: propTag]; + ASSIGN (task, [newSOGoObject component: NO secure: NO]); } + return self; +} + +- (void) dealloc +{ + [task release]; + [super dealloc]; +} + +- (int) getPrIconIndex: (void **) data // TODO +{ + /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */ + // Unassigned recurring task 0x00000501 + // Assignee's task 0x00000502 + // Assigner's task 0x00000503 + // Task request 0x00000504 + // Task acceptance 0x00000505 + // Task rejection 0x00000506 + *data = MAPILongValue (memCtx, 0x00000500); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMessageClass: (void **) data +{ + *data = talloc_strdup(memCtx, "IPM.Task"); + + return MAPISTORE_SUCCESS; +} + +- (int) getPrSubject: (void **) data // SUMMARY +{ + *data = [[task summary] asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrImportance: (void **) data +{ + uint32_t v; + + if ([[task priority] isEqualToString: @"9"]) + v = 0x0; + else if ([[task priority] isEqualToString: @"1"]) + v = 0x2; + else + v = 0x1; + + *data = MAPILongValue (memCtx, v); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidTaskComplete: (void **) data +{ + *data = MAPIBoolValue (memCtx, + [[task status] isEqualToString: @"COMPLETED"]); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidPercentComplete: (void **) data +{ + double doubleValue; + + doubleValue = ((double) [[task percentComplete] intValue] / 100); + *data = MAPIDoubleValue (memCtx, doubleValue); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidTaskDateCompleted: (void **) data +{ + NSCalendarDate *dateValue; + int rc = MAPISTORE_SUCCESS; + + dateValue = [task completed]; + if (dateValue) + *data = [dateValue asFileTimeInMemCtx: memCtx]; + else + rc = MAPISTORE_ERR_NOT_FOUND; + return rc; } +- (int) getPidLidTaskState: (void **) data +{ + *data = MAPILongValue (memCtx, 0x1); // not assigned + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidTaskMode: (void **) data // TODO +{ + return [self getLongZero: data]; +} + +- (int) getPidLidTaskFRecurring: (void **) data +{ + return [self getNo: data]; +} + +- (int) getPidLidTaskAccepted: (void **) data // TODO +{ + return [self getNo: data]; +} + +- (int) getPidLidTaskActualEffort: (void **) data // TODO +{ + return [self getLongZero: data]; +} + +- (int) getPidLidTaskEstimatedEffort: (void **) data // TODO +{ + return [self getLongZero: data]; +} + +- (int) getPrHasattach: (void **) data +{ + return [self getNo: data]; +} + +- (int) getPidLidTaskDueDate: (void **) data +{ + NSCalendarDate *dateValue; + int rc = MAPISTORE_SUCCESS; + + dateValue = [task due]; + if (dateValue) + *data = [dateValue asFileTimeInMemCtx: memCtx]; + else + rc = MAPISTORE_ERR_NOT_FOUND; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrCreationTime: (void **) data +{ + *data = [[task created] asFileTimeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPrMessageDeliveryTime: (void **) data +{ + *data = [[task lastModified] asFileTimeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getClientSubmitTime: (void **) data +{ + return [self getPrMessageDeliveryTime: data]; +} + +- (int) getLocalCommitTime: (void **) data +{ + return [self getPrMessageDeliveryTime: data]; +} + +- (int) getLastModificationTime: (void **) data +{ + return [self getPrMessageDeliveryTime: data]; +} + +- (int) getPidLidTaskStatus: (void **) data // status +{ + NSString *status; + uint32_t longValue; + + status = [task status]; + if (![status length] + || [status isEqualToString: @"NEEDS-ACTION"]) + longValue = 0; + else if ([status isEqualToString: @"IN-PROCESS"]) + longValue = 1; + else if ([status isEqualToString: @"COMPLETED"]) + longValue = 2; + else + longValue = 0xff; + *data = MAPILongValue (memCtx, longValue); + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidTaskOwner: (void **) data +{ + *data = [@"openchange@example.com" asUnicodeInMemCtx: memCtx]; + + return MAPISTORE_SUCCESS; +} + +- (int) getPidLidTaskOwnership: (void **) data +{ + return [self getLongZero: data]; +} + - (void) save { iCalCalendar *vCalendar; diff --git a/OpenChange/MAPIStoreTypes.h b/OpenChange/MAPIStoreTypes.h index b6fd47bb2..fd20b8e73 100644 --- a/OpenChange/MAPIStoreTypes.h +++ b/OpenChange/MAPIStoreTypes.h @@ -38,7 +38,6 @@ double *MAPIDoubleValue (void *memCtx, double value); id NSObjectFromSPropValue (const struct SPropValue *); id NSObjectFromMAPISPropValue (const struct mapi_SPropValue *); -id NSObjectFromStreamData (enum MAPITAGS property, NSData *streamData); static inline NSNumber * MAPIPropertyKey (enum MAPITAGS propTag) diff --git a/OpenChange/MAPIStoreTypes.m b/OpenChange/MAPIStoreTypes.m index a4d35c024..5d61ca4b8 100644 --- a/OpenChange/MAPIStoreTypes.m +++ b/OpenChange/MAPIStoreTypes.m @@ -116,6 +116,7 @@ NSObjectFromMAPISPropValue (const struct mapi_SPropValue *value) result = [NSCalendarDate dateFromFileTime: &(value->value.ft)]; break; case PT_BINARY: + case PT_SVREID: result = [NSData dataWithShortBinary: &value->value.bin]; break; case PT_CLSID: @@ -175,6 +176,7 @@ NSObjectFromSPropValue (const struct SPropValue *value) result = [NSCalendarDate dateFromFileTime: &(value->value.ft)]; break; case PT_BINARY: + case PT_SVREID: // lpProps->value.bin = *((const struct Binary_r *)data); result @@ -204,36 +206,6 @@ NSObjectFromSPropValue (const struct SPropValue *value) return result; } -id NSObjectFromStreamData (enum MAPITAGS property, NSData* streamData) -{ - short int valueType; - id result; - - valueType = (property & 0xffff); - switch (valueType) - { - case PT_UNICODE: - case PT_STRING8: - result = [NSString stringWithCharacters: (unichar *) [streamData bytes] - length: [streamData length] / 2]; - break; - case PT_BINARY: - result = streamData; - break; - case PT_OBJECT: - result = [NSNull null]; - NSLog (@"%s: object type not handled: %d (0x%.4x)", - __PRETTY_FUNCTION__, valueType, valueType); - break; - default: - [NSException raise: @"MAPIStoreStreamTypeException" - format: @"invalid data type"]; - result = nil; - } - - return result; -} - void MAPIStoreDumpMessageProperties (NSDictionary *properties) { diff --git a/OpenChange/NSObject+MAPIStore.m b/OpenChange/NSObject+MAPIStore.m index ce058ea30..bee3734be 100644 --- a/OpenChange/NSObject+MAPIStore.m +++ b/OpenChange/NSObject+MAPIStore.m @@ -70,7 +70,7 @@ *data = [(NSCalendarDate * ) self asFileTimeInMemCtx: memCtx]; break; case PT_BINARY: - *data = [(NSData *) self asShortBinaryInMemCtx: memCtx]; + *data = [(NSData *) self asBinaryInMemCtx: memCtx]; break; case PT_CLSID: *data = [(NSData *) self asGUIDInMemCtx: memCtx]; diff --git a/OpenChange/code-MAPIStorePropertySelectors.h b/OpenChange/code-MAPIStorePropertySelectors.h new file mode 100644 index 000000000..0f7590ed5 --- /dev/null +++ b/OpenChange/code-MAPIStorePropertySelectors.h @@ -0,0 +1,26 @@ +/* code-MAPIStorePropertySelectors.h - this file is part of SOGo + * + * Copyright (C) 2011 Inverse inc + * + * Author: Wolfgang Sourdeau + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +typedef int (*MAPIStorePropertyGetter) (id inst, SEL _cmd, void **data); + +const MAPIStorePropertyGetter *MAPIStorePropertyGettersForClass (Class klass); +SEL MAPIStoreSelectorForPropertyGetter (uint16_t propertyId); diff --git a/OpenChange/code-MAPIStorePropertySelectors.m b/OpenChange/code-MAPIStorePropertySelectors.m new file mode 100644 index 000000000..f44bdbadc --- /dev/null +++ b/OpenChange/code-MAPIStorePropertySelectors.m @@ -0,0 +1,69 @@ +/* code-MAPIStorePropertySelectors.m - this file is part of SOGo + * + * Copyright (C) 2011 Inverse inc + * + * Author: Wolfgang Sourdeau + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#import +#import + +const MAPIStorePropertyGetter * +MAPIStorePropertyGettersForClass (Class klass) +{ + static NSMapTable *classesTable = nil; + MAPIStorePropertyGetter *getters; + MAPIStorePropertyGetter getter; + uint16_t count, idx; + SEL currentSel; + + if (!classesTable) + classesTable = NSCreateMapTable (NSNonOwnedPointerMapKeyCallBacks, + NSNonOwnedPointerMapValueCallBacks, + 0); + + getters = NSMapGet (classesTable, klass); + if (!getters) + { + getters = NSZoneCalloc (NULL, 65536, sizeof (MAPIStorePropertyGetter)); + for (count = 0; count < 65535; count++) + { + idx = MAPIStorePropertyGettersIdx[count]; + if (idx != 0xffff && !getters[count]) + { + currentSel = MAPIStorePropertyGetterSelectors[idx]; + if ([klass instancesRespondToSelector: currentSel]) + { + getter = (MAPIStorePropertyGetter) + [klass instanceMethodForSelector: currentSel]; + if (getter) + getters[count] = getter; + } + } + } + } + + return getters; +} + +SEL MAPIStoreSelectorForPropertyGetter (uint16_t propertyId) +{ + return ((MAPIStorePropertyGettersIdx[propertyId] != 0xffff) + ? MAPIStorePropertyGetterSelectors[MAPIStorePropertyGettersIdx[propertyId]] + : NULL); +} diff --git a/OpenChange/gen-property-selectors.py b/OpenChange/gen-property-selectors.py new file mode 100755 index 000000000..abd91f723 --- /dev/null +++ b/OpenChange/gen-property-selectors.py @@ -0,0 +1,270 @@ +#!/usr/bin/python + +include_dirs = [ "/usr/include" ] + +output = "-" + +import os +import sys + +m_template = """/* %(filename)s (auto-generated) - this file is part of SOGo + * + * Copyright (C) 2011 Inverse inc. + * + * Author: Wolfgang Sourdeau + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +#import "%(h_filename)s" + +const NSUInteger MAPIStorePropertyGettersCount = %(nbr_getters)d; +const NSUInteger MAPIStoreLastPropertyIdx = %(last_property)d; +const NSUInteger MAPIStoreSupportedPropertiesCount = %(nbr_supported_properties)d; + +const enum MAPITAGS MAPIStoreSupportedProperties[] = { +%(supported_properties)s +}; + +static const uint16_t MAPIStorePropertyGettersIdx[] = { +%(getters_idx)s +}; + +static const SEL MAPIStorePropertyGetterSelectors[] = { +%(getters)s +}; + +#include "code-%(filename)s" +""" + +h_template = """/* %(filename)s (auto-generated) - this file is part of SOGo + * + * Copyright (C) 2011 Inverse inc. + * + * Author: Wolfgang Sourdeau + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef %(h_exclusion)s +#define %(h_exclusion)s 1 + +#import + +#include +#include + +extern const NSUInteger MAPIStorePropertyGettersCount; +extern const NSUInteger MAPIStoreLastPropertyIdx; + +extern const NSUInteger MAPIStoreSupportedPropertiesCount; +extern const enum MAPITAGS MAPIStoreSupportedProperties[]; + +#import "MAPIStoreObject.h" + +@interface MAPIStoreObject (MAPIStorePropertySelectors) + +%(prototypes)s + +@end + +#include "code-%(filename)s" + +#endif /* %(h_exclusion)s */ +""" + +def ParseExchangeH(names, lines): + state = 0 + maxlines = len(lines) + x = 0 + while x < maxlines and state != 3: + stripped = lines[x].strip() + if state == 0: + if stripped == "enum MAPITAGS": + state = 1 + elif state == 1: + if stripped == "{": + state = 2 + elif state == 2: + if stripped == "}": + state = 3 + else: + ParseExchangeHDefinition(names, stripped) + x = x + 1 + +def GenExchangeHName(startname): + parts = startname.split("_") + newParts = [] + for part in parts: + newParts.append("%s%s" % (part[0].upper(), part[1:].lower())) + + return "".join(newParts) + +def ParseExchangeHDefinition(names, line): + stripped = line.strip() + eqIdx = stripped.find("=") + if eqIdx == -1: + raise Exception, "line does not contain a '='" + propName = GenExchangeHName(stripped[0:eqIdx]) + if not propName.endswith("_ERROR") and not propName.endswith("_UNICODE"): + intIdx = stripped.find("(int", eqIdx) + valueIdx = stripped.find("0x", intIdx + 1) + endIdx = stripped.find(")", valueIdx) + value = int(stripped[valueIdx:endIdx], 16) + + names[propName] = value + +def ParseMapistoreNameIDH(names, lines): + for line in lines: + stripped = line.strip() + if stripped.startswith("#define Pid"): + ParseMapistoreNameIDHDefinition(names, stripped) + +def ParseMapistoreNameIDHDefinition(names, line): + stripped = line.strip() + pidIdx = stripped.find("Pid") + if pidIdx == -1: + raise Exception, "line does not contain a 'Pid'" + valueIdx = stripped.find("0x") + propName = stripped[pidIdx:valueIdx].strip() + value = int(stripped[valueIdx:], 16) + + names[propName] = value + +def FindHFile(filename): + found = None + + for dirname in include_dirs: + full_filename = "%s/%s" % (dirname, filename) + if os.path.exists(full_filename): + found = full_filename + + if found is None: + raise Exception, "'%s' not found in include dirs" % filename + + return found + +def ProcessHeaders(names, hdict): + for filename in hdict.keys(): + header_filename = FindHFile(filename) + header_file = open(header_filename, "r") + lines = header_file.readlines() + header_file.close() + hdict[filename](names, lines) + +if __name__ == "__main__": + arg_count = len(sys.argv) + x = 0 + while x < arg_count: + arg = sys.argv[x] + argname = None + if arg.startswith("-"): + argname = arg[1] + if len(arg) == 2: + argvalue = sys.argv[x + 1] + x = x + 1 + else: + argvalue = arg[2:] + x = x + 1 + + if argname == "o": + output = argvalue + elif argname == "I": + include_dirs.append(argvalue) + + names = {} + ProcessHeaders(names, + { "gen_ndr/exchange.h": ParseExchangeH, + "mapistore/mapistore_nameid.h": ParseMapistoreNameIDH }) + + getters = [] + getters_idx = [] + # setters = [] + # preferred_types = [] + prototypes = [] + + for x in xrange(0x10000): + getters_idx.append(" 0xffff") + # setters.append(" NULL") + + all_keys = names.keys() + for name in all_keys: + prop_tag = names[name] + if (prop_tag & 0x001e): + prop_tag = (prop_tag & 0xffff0000) | 0x001f + names[name] = prop_tag + if (name.endswith("Error") + or name.endswith("Unicode")): + del names[name] + + supported_properties = [] + all_keys = names.keys() + current_getter_idx = 0 + highest_prop_idx = 0 + for name in all_keys: + prop_tag = names[name] + supported_properties.append(" 0x%.8x" % prop_tag); + prop_idx = (prop_tag & 0xffff0000) >> 16 + getters_idx[prop_idx] = " %d" % current_getter_idx + if prop_idx > highest_prop_idx: + highest_prop_idx = prop_idx + getters.append(" @selector (get%s:)" % name) + # preferred_types.append(" 0x%.4x" % (prop_tag & 0xffff)) + prototypes.append("- (int) get%s: (void **) data;" % name) + current_getter_idx = current_getter_idx + 1 + # setters[prop_idx] = " @selector (set%s:)" % name + # prototypes.append("- (int) set%s: (void **) data;" % name) + # prototypes.append("") + + filename = "%s.m" % output + h_filename = "%s.h" % output + outf = open(filename, "wb+") + outf.write(m_template % { "getters_idx": ",\n".join(getters_idx), + "getters": ",\n".join(getters), + "nbr_getters": len(getters), + "last_property": highest_prop_idx, + "nbr_supported_properties": len(supported_properties), + "supported_properties": ",\n".join(supported_properties), + "filename": filename, + "h_filename": h_filename }) + outf.close() + + outf = open(h_filename, "wb+") + exclusion = "" + for x in h_filename.upper(): + if ord(x) < 65 or ord(x) > 90: + x = "_" + exclusion = exclusion + x + outf.write(h_template % { "prototypes": "\n".join(prototypes), + "h_exclusion": exclusion, + "filename": h_filename }) + outf.close() diff --git a/SOPE/NGCards/iCalEvent.h b/SOPE/NGCards/iCalEvent.h index 4383a8d9f..05fe05c5b 100644 --- a/SOPE/NGCards/iCalEvent.h +++ b/SOPE/NGCards/iCalEvent.h @@ -51,6 +51,7 @@ - (BOOL) hasEndDate; - (NSString *) duration; +- (void) setDuration: (NSString *) _value; - (BOOL) hasDuration; - (NSTimeInterval) durationAsTimeInterval; diff --git a/SoObjects/Appointments/Catalan.lproj/Localizable.strings b/SoObjects/Appointments/Catalan.lproj/Localizable.strings index 6cd264e20..5516bf6f4 100644 --- a/SoObjects/Appointments/Catalan.lproj/Localizable.strings +++ b/SoObjects/Appointments/Catalan.lproj/Localizable.strings @@ -60,3 +60,5 @@ vtodo_class2 = "(Tasca confidencial)"; = "%{Attendee} %{SentByText}ha delegat la invitació en %{Delegate}."; "%{Attendee} %{SentByText}has not yet decided upon your event invitation." = "%{Attendee} %{SentByText}encara no s'ha decidit sobre la invitació a l'esdeveniment."; + +"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\"." = "Nombre màxim de reserves simultànies (%{NumberOfSimultaneousBookings}) assolit per al recurs \"%{Cn}{%SystemEmail}\"."; diff --git a/SoObjects/Appointments/English.lproj/Localizable.strings b/SoObjects/Appointments/English.lproj/Localizable.strings index 01a973e0c..1f432a7d9 100644 --- a/SoObjects/Appointments/English.lproj/Localizable.strings +++ b/SoObjects/Appointments/English.lproj/Localizable.strings @@ -60,3 +60,6 @@ vtodo_class2 = "(Confidential task)"; = "%{Attendee} %{SentByText}has delegated the invitation to %{Delegate}."; "%{Attendee} %{SentByText}has not yet decided upon your event invitation." = "%{Attendee} %{SentByText}has not yet decided upon your event invitation."; + +/* Resources */ +"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\"." = "Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\"."; \ No newline at end of file diff --git a/SoObjects/Appointments/French.lproj/Localizable.strings b/SoObjects/Appointments/French.lproj/Localizable.strings index bf6ef31f2..80be3f52d 100644 --- a/SoObjects/Appointments/French.lproj/Localizable.strings +++ b/SoObjects/Appointments/French.lproj/Localizable.strings @@ -60,3 +60,6 @@ vtodo_class2 = "(Tâche confidentielle)"; = "%{Attendee} %{SentByText}a délégué votre invitation à %{Delegate}."; "%{Attendee} %{SentByText}has not yet decided upon your event invitation." = "%{Attendee} %{SentByText}choisit de reporter sa décision par rapport à votre invitation."; + +/* Resources */ +"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\"." = "Le nombre maximum (%{NumberOfSimultaneousBookings}) de réservation(s) simultanée(s) a été atteint pour la ressource \"%{Cn} %{SystemEmail}\"."; \ No newline at end of file diff --git a/SoObjects/Appointments/German.lproj/Localizable.strings b/SoObjects/Appointments/German.lproj/Localizable.strings index b091b932b..f5b5d1840 100644 --- a/SoObjects/Appointments/German.lproj/Localizable.strings +++ b/SoObjects/Appointments/German.lproj/Localizable.strings @@ -60,3 +60,6 @@ vtodo_class2 = "(Vertrauliche Aufgabe)"; = "%{Attendee} %{SentByText}hat die Einladung delegiert an %{Delegate}."; "%{Attendee} %{SentByText}has not yet decided upon your event invitation." = "%{Attendee} %{SentByText}hat noch nicht über Ihre Termineinladung entschieden."; + +"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\"." = "Maximale Zahl simultaner Buchungen (%{NumberOfSimultaneousBookings}) erreicht für Ressource \"%{Cn} %{SystemEmail}\"."; + diff --git a/SoObjects/Appointments/Hungarian.lproj/Localizable.strings b/SoObjects/Appointments/Hungarian.lproj/Localizable.strings index a3640e7a7..4a89b8e1e 100644 --- a/SoObjects/Appointments/Hungarian.lproj/Localizable.strings +++ b/SoObjects/Appointments/Hungarian.lproj/Localizable.strings @@ -60,3 +60,5 @@ vtodo_class2 = "(Bizalmas feladat)"; = "%{Attendee} %{SentByText}has delegated the invitation to %{Delegate}."; "%{Attendee} %{SentByText}has not yet decided upon your event invitation." = "%{Attendee} %{SentByText}még meggondolja a meghívását."; + +"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\"." = "Az egyidejű foglalások száma (%{NumberOfSimultaneousBookings}) elérte a maximumot \"%{Cn} %{SystemEmail}\"."; diff --git a/SoObjects/Appointments/Russian.lproj/Localizable.strings b/SoObjects/Appointments/Russian.lproj/Localizable.strings index d33d98bca..2fde34301 100644 --- a/SoObjects/Appointments/Russian.lproj/Localizable.strings +++ b/SoObjects/Appointments/Russian.lproj/Localizable.strings @@ -60,3 +60,5 @@ vtodo_class2 = "(Confidential task)"; = "%{Attendee} %{SentByText}has delegated the invitation to %{Delegate}."; "%{Attendee} %{SentByText}has not yet decided upon your event invitation." = "%{Attendee} %{SentByText}не определился с желанием участвовать в запланированном мероприятии."; + +"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\"." = "Уже подано максимальное количество заявок (%{NumberOfSimultaneousBookings}) на ресурс \"%{Cn} %{SystemEmail}\"."; diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.m b/SoObjects/Appointments/SOGoAppointmentFolder.m index 78435eadb..16dc8da29 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.m +++ b/SoObjects/Appointments/SOGoAppointmentFolder.m @@ -2,14 +2,14 @@ Copyright (C) 2007-2011 Inverse inc. Copyright (C) 2004-2005 SKYRIX Software AG - This file is part of OpenGroupware.org. + This file is part of SOGo. - OGo is free software; you can redistribute it and/or modify it under + SOGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - OGo is distributed in the hope that it will be useful, but WITHOUT ANY + SOGo is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. @@ -73,6 +73,7 @@ #import #import "iCalRepeatableEntityObject+SOGo.h" +#import "iCalEvent+SOGo.h" #import "iCalPerson+SOGo.h" #import "SOGoAppointmentObject.h" #import "SOGoAppointmentFolders.h" @@ -622,6 +623,9 @@ static NSNumber *sharedYes = nil; return record; } +// +// +// - (NSArray *) fixupRecords: (NSArray *) theRecords { // TODO: is the result supposed to be sorted by date? @@ -801,6 +805,9 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir [self _fixExceptionRecord: newRecord fromRow: row]; } +// +// +// - (void) _appendCycleExceptionsFromRow: (NSDictionary *) row firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir forRange: (NGCalendarDateRange *) dateRange @@ -849,9 +856,9 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir NSArray *rules, *exRules, *exDates, *ranges; NSArray *elements, *components; NSString *content; - iCalRepeatableEntityObject *component; - id firstStartDate, firstEndDate; - NSCalendarDate *checkStartDate, *checkEndDate; + iCalDateTime *dtstart; + NSCalendarDate *checkStartDate, *checkEndDate, *firstStartDate, *firstEndDate; + iCalEvent *component; iCalTimeZone *eventTimeZone; unsigned count, max, offset; @@ -889,53 +896,55 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir { // Retrieve the range of the first/master event component = [components objectAtIndex: 0]; - firstStartDate = [component uniqueChildWithTag: @"dtstart"]; - firstEndDate = [component uniqueChildWithTag: @"dtend"]; - eventTimeZone = [(iCalDateTime*)firstStartDate timeZone]; - firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: [[[firstStartDate values] lastObject] asCalendarDate] - endDate: [[[firstEndDate values] lastObject] asCalendarDate]]; + dtstart = (iCalDateTime *)[component uniqueChildWithTag: @"dtstart"]; + firstStartDate = [[[dtstart values] lastObject] asCalendarDate]; + firstEndDate = [firstStartDate addTimeInterval: [component occurenceInterval]]; + + firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: firstStartDate + endDate: firstEndDate]; - if (eventTimeZone) - { - // Adjust the range to check with respect to the event timezone (extracted from the start date) - checkStartDate = [eventTimeZone computedDateForDate: [theRange startDate]]; - checkEndDate = [eventTimeZone computedDateForDate: [theRange endDate]]; - recurrenceRange = [NGCalendarDateRange calendarDateRangeWithStartDate: checkStartDate - endDate: checkEndDate]; - - // Adjust the exception dates - exDates = [eventTimeZone computedDatesForStrings: exDates]; - - // Adjust the recurrence rules "until" dates - rules = [component recurrenceRulesWithTimeZone: eventTimeZone]; - exRules = [component exceptionRulesWithTimeZone: eventTimeZone]; - } - else - { - recurrenceRange = theRange; - if ([[theRecord objectForKey: @"c_isallday"] boolValue]) - { - // The event lasts all-day and has no timezone (floating); we convert the range of the first event - // to the user's timezone - offset = [timeZone secondsFromGMTForDate: [firstRange startDate]]; - firstStartDate = (NSCalendarDate*)[[firstRange startDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 - seconds:-offset]; - firstEndDate = (NSCalendarDate*)[[firstRange endDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 - seconds:-offset]; - [firstStartDate setTimeZone: timeZone]; - [firstEndDate setTimeZone: timeZone]; - firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: firstStartDate - endDate: firstEndDate]; - } - } - - // Calculate the occurrences for the given range + eventTimeZone = [dtstart timeZone]; + if (eventTimeZone) + { + // Adjust the range to check with respect to the event timezone (extracted from the start date) + checkStartDate = [eventTimeZone computedDateForDate: [theRange startDate]]; + checkEndDate = [eventTimeZone computedDateForDate: [theRange endDate]]; + recurrenceRange = [NGCalendarDateRange calendarDateRangeWithStartDate: checkStartDate + endDate: checkEndDate]; + + // Adjust the exception dates + exDates = [eventTimeZone computedDatesForStrings: exDates]; + + // Adjust the recurrence rules "until" dates + rules = [component recurrenceRulesWithTimeZone: eventTimeZone]; + exRules = [component exceptionRulesWithTimeZone: eventTimeZone]; + } + else + { + recurrenceRange = theRange; + if ([[theRecord objectForKey: @"c_isallday"] boolValue]) + { + // The event lasts all-day and has no timezone (floating); we convert the range of the first event + // to the user's timezone + offset = [timeZone secondsFromGMTForDate: [firstRange startDate]]; + firstStartDate = [[firstRange startDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 + seconds:-offset]; + firstEndDate = [[firstRange endDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 + seconds:-offset]; + [firstStartDate setTimeZone: timeZone]; + [firstEndDate setTimeZone: timeZone]; + firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: firstStartDate + endDate: firstEndDate]; + } + } + + // Calculate the occurrences for the given range records = [NSMutableArray array]; - ranges = [iCalRecurrenceCalculator recurrenceRangesWithinCalendarDateRange: recurrenceRange - firstInstanceCalendarDateRange: firstRange + ranges = [iCalRecurrenceCalculator recurrenceRangesWithinCalendarDateRange: recurrenceRange + firstInstanceCalendarDateRange: firstRange recurrenceRules: rules - exceptionRules: exRules - exceptionDates: exDates]; + exceptionRules: exRules + exceptionDates: exDates]; max = [ranges count]; for (count = 0; count < max; count++) { @@ -947,15 +956,15 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir if (fixedRow) [records addObject: fixedRow]; } - + [self _appendCycleExceptionsFromRow: row firstInstanceCalendarDateRange: firstRange forRange: theRange toArray: records]; - + [theRecords addObjectsFromArray: records]; - } - } + } + } } else [self errorWithFormat:@"cyclic record doesn't have content -> %@", theRecord]; @@ -1504,7 +1513,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir order = [[container subFolders] indexOfObject: self]; - return [NSString stringWithFormat: @"%d", order]; + return [NSString stringWithFormat: @"%d", order+1]; } - (NSException *) setDavCalendarOrder: (NSString *) newColor @@ -2607,10 +2616,21 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir return ([object saveContentString: content] == nil); } +/** + * Import all components of a vCalendar. + * @param calendar the calendar to import + * @return the number of components imported + */ - (int) importCalendar: (iCalCalendar *) calendar { + NSArray *vtimezones; NSMutableArray *components; + NSMutableDictionary *timezones; NSString *tz; + iCalEntityObject *element; + iCalDateTime *startDate; + iCalTimeZone *timezone; + iCalEvent *event; int imported, count, i; @@ -2618,25 +2638,55 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir if (calendar) { + // Build a hash with the timezones includes in the calendar + vtimezones = [calendar timezones]; + count = [vtimezones count]; + timezones = [NSMutableDictionary dictionaryWithCapacity: count]; + for (i = 0; i < count; i++) + { + timezone = (iCalTimeZone *)[vtimezones objectAtIndex: i]; + [timezones setValue: [NSString stringWithFormat: @"%@\n", [timezone versitString]] + forKey: [timezone tzId]]; + } + + // Parse events/todos/journals and import them components = [[calendar events] mutableCopy]; [components autorelease]; [components addObjectsFromArray: [calendar todos]]; [components addObjectsFromArray: [calendar journals]]; [components addObjectsFromArray: [calendar freeBusys]]; - -#warning FIXME we might want to eventually support multiple timezone definitions and match the one used by the event - if ([[calendar timezones] count]) - tz = [NSString stringWithFormat: @"%@\n", - [[[calendar timezones] lastObject] versitString]]; - else - tz = @""; - count = [components count]; for (i = 0; i < count; i++) - if ([self importComponent: [components objectAtIndex: i] timezone: tz]) - imported++; + { + tz = nil; + element = [components objectAtIndex: i]; + // Use the timezone of the start date. + startDate = (iCalDateTime *)[element uniqueChildWithTag: @"dtstart"]; + if (startDate) + { + timezone = [startDate timeZone]; + tz = [timezones valueForKey: [timezone tzId]]; + if ([element isKindOfClass: [iCalEvent class]]) + { + event = (iCalEvent *)element; + if (![event hasEndDate] && ![event hasDuration]) + { + // No end date, no duration + if ([event isAllDay]) + [event setDuration: @"P1D"]; + else + [event setDuration: @"PT1H"]; + + [self errorWithFormat: @"Importing event with no end date; setting duration to %@", [event duration]]; + } + } + } + if ([self importComponent: element + timezone: (tz == nil? @"" : tz)]) + imported++; + } } - + return imported; } diff --git a/SoObjects/Appointments/SOGoAppointmentObject.h b/SoObjects/Appointments/SOGoAppointmentObject.h index 9f13025e4..290f568b9 100644 --- a/SoObjects/Appointments/SOGoAppointmentObject.h +++ b/SoObjects/Appointments/SOGoAppointmentObject.h @@ -1,15 +1,14 @@ /* - Copyright (C) 2004-2005 SKYRIX Software AG - Copyright (C) 2007-2010 Inverse inc. + Copyright (C) 2007-2011 Inverse inc. - This file is part of OpenGroupware.org. + This file is part of SOGo - OGo is free software; you can redistribute it and/or modify it under + SOGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - OGo is distributed in the hope that it will be useful, but WITHOUT ANY + SOGo is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. @@ -25,17 +24,6 @@ #import -/* - SOGoAppointmentObject - - Represents a single appointment. This SOPE controller object manages all the - attendee storages (that is, it might store into multiple folders for meeting - appointments!). - - Note: SOGoAppointmentObject do not need to exist yet. They can also be "new" - appointments with an externally generated unique key. -*/ - @class NSArray; @class NSException; @class NSString; @@ -61,13 +49,6 @@ - (NSArray *) postCalDAVEventReplyTo: (NSArray *) recipients from: (NSString *) originator; - (NSArray *) postCalDAVEventCancelTo: (NSArray *) recipients from: (NSString *) originator; -/* "iCal multifolder saves" */ - -// - (NSException *) saveContentString: (NSString *) _iCal -// baseSequence: (int) _v; -// - (NSException *) deleteWithBaseSequence: (int) _v; -// - (NSException *) saveContentString: (NSString *) _iCalString; - @end #endif /* __Appointments_SOGoAppointmentObject_H__ */ diff --git a/SoObjects/Appointments/SOGoAppointmentObject.m b/SoObjects/Appointments/SOGoAppointmentObject.m index bec825629..155ce6707 100644 --- a/SoObjects/Appointments/SOGoAppointmentObject.m +++ b/SoObjects/Appointments/SOGoAppointmentObject.m @@ -2,7 +2,7 @@ Copyright (C) 2007-2011 Inverse inc. Copyright (C) 2004-2005 SKYRIX Software AG - This file is part of OpenGroupware.org. + This file is part of SOGo SOGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the @@ -42,6 +42,7 @@ #import #import +#import #import #import #import @@ -198,7 +199,6 @@ // We check if the attendee that was added to a single occurence is // present in the master component. If not, we add it with a participation // status set to "DECLINED". - user = [SOGoUser userWithLogin: theUID]; person = [iCalPerson elementWithTag: @"attendee"]; [person setCn: [user cn]]; @@ -425,14 +425,117 @@ } // +// This methods scans the list of attendees. If they are +// considered as resource, it checks for conflicting +// dates for the event. +// +// We check for between startDate + 1 second and +// endDate - 1 second // // -- (void) _handleAddedUsers: (NSArray *) attendees - fromEvent: (iCalEvent *) newEvent +// It also CHANGES the participation status of resources +// depending on constraints defined on them. +// +// Note that it doesn't matter if it changes the participation +// status since in case of an error, nothing will get saved. +// +- (NSException *) _handleResourcesConflicts: (NSArray *) theAttendees + forEvent: (iCalEvent *) theEvent { - NSEnumerator *enumerator; iCalPerson *currentAttendee; + NSEnumerator *enumerator; NSString *currentUID; + SOGoUser *user; + + enumerator = [theAttendees objectEnumerator]; + + while ((currentAttendee = [enumerator nextObject])) + { + currentUID = [currentAttendee uid]; + + if (currentUID) + { + user = [SOGoUser userWithLogin: currentUID]; + + if ([user isResource]) + { + SOGoAppointmentFolder *folder; + NSCalendarDate *start, *end; + NSMutableArray *fbInfo; + int i; + + start = [[theEvent startDate] dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: 1]; + end = [[theEvent endDate] dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: -1]; + + folder = [[SOGoUser userWithLogin: currentUID] + personalCalendarFolderInContext: context]; + + + fbInfo = [NSMutableArray arrayWithArray: [folder fetchFreeBusyInfosFrom: start + to: end]]; + + // We first remove any occurences in the freebusy that corresponds to the + // current event. We do this to avoid raising a conflict if we move a 1 hour + // meeting from 12:00-13:00 to 12:15-13:15. We would overlap on ourself otherwise. + for (i = [fbInfo count]-1; i >= 0; i--) + { + if ([[[fbInfo objectAtIndex: i] objectForKey: @"c_uid"] compare: [theEvent uid]] == NSOrderedSame) + [fbInfo removeObjectAtIndex: i]; + } + + if ([fbInfo count]) + { + // If we always force the auto-accept if numberOfSimultaneousBookings == 0 (ie., no limit + // is imposed) or if numberOfSimultaneousBookings is greater than the number of + // overlapping events + if ([user numberOfSimultaneousBookings] == 0 || + [user numberOfSimultaneousBookings] > [fbInfo count]) + [currentAttendee setParticipationStatus: iCalPersonPartStatAccepted]; + else + { + NSDictionary *values; + NSString *reason; + + values = [NSDictionary dictionaryWithObjectsAndKeys: + [NSString stringWithFormat: @"%d", [user numberOfSimultaneousBookings]], @"NumberOfSimultaneousBookings", + [user cn], @"Cn", + [user systemEmail], @"SystemEmail", + nil]; + + reason = [values keysWithFormat: [self labelForKey: @"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\"."]]; + + return [NSException exceptionWithHTTPStatus:403 + reason: reason]; + } + } + else + { + // No conflict, we auto-accept. We do this for resources automatically if no + // double-booking is observed. If it's not the desired behavior, just don't + // set the resource as one! + [currentAttendee setParticipationStatus: iCalPersonPartStatAccepted]; + } + } + } + } + + return nil; +} + +// +// +// +- (NSException *) _handleAddedUsers: (NSArray *) attendees + fromEvent: (iCalEvent *) newEvent +{ + iCalPerson *currentAttendee; + NSEnumerator *enumerator; + NSString *currentUID; + NSException *e; + + // We check for conflicts + if ((e = [self _handleResourcesConflicts: attendees forEvent: newEvent])) + return e; enumerator = [attendees objectEnumerator]; while ((currentAttendee = [enumerator nextObject])) @@ -443,25 +546,31 @@ forUID: currentUID owner: owner]; } + + return nil; } // // // -- (void) _handleUpdatedEvent: (iCalEvent *) newEvent - fromOldEvent: (iCalEvent *) oldEvent +- (NSException *) _handleUpdatedEvent: (iCalEvent *) newEvent + fromOldEvent: (iCalEvent *) oldEvent { - NSArray *attendees; iCalEventChanges *changes; + NSArray *attendees; + NSException *ex; changes = [newEvent getChangesRelativeToEvent: oldEvent]; if ([changes sequenceShouldBeIncreased]) { // Set new attendees status to "needs action" and recompute changes when - // the list of attendees has changed. + // the list of attendees has changed. The list might have changed since + // by changing a major property of the event, we remove all the delegation + // chains to "other" attendees if ([self _requireResponseFromAttendees: newEvent]) changes = [newEvent getChangesRelativeToEvent: oldEvent]; } + attendees = [changes deletedAttendees]; if ([attendees count]) { @@ -475,6 +584,10 @@ forObject: newEvent to: attendees]; } + if ((ex = [self _handleResourcesConflicts: [newEvent attendees] + forEvent: newEvent])) + return ex; + attendees = [changes insertedAttendees]; if ([changes sequenceShouldBeIncreased]) { @@ -516,7 +629,9 @@ if ([attendees count]) { // Send an invitation to new attendees - [self _handleAddedUsers: attendees fromEvent: newEvent]; + if ((ex = [self _handleAddedUsers: attendees fromEvent: newEvent])) + return ex; + [self sendEMailUsingTemplateNamed: @"Invitation" forObject: [newEvent itipEntryWithMethod: @"request"] previousObject: oldEvent @@ -524,6 +639,8 @@ [self sendReceiptEmailUsingTemplateNamed: @"Invitation" forObject: newEvent to: attendees]; } + + return nil; } // @@ -551,14 +668,15 @@ // _updateAttendee:withDelegate:ownerUser:forEventUID:withRecurrenceId:withSequence:forUID:shouldAddSentBy: // // -- (void) saveComponent: (iCalEvent *) newEvent +- (NSException *) saveComponent: (iCalEvent *) newEvent { iCalEvent *oldEvent, *oldMasterEvent; - NSArray *attendees; NSCalendarDate *recurrenceId; NSString *recurrenceTime; SOGoUser *ownerUser; - + NSArray *attendees; + NSException *ex; + [[newEvent parent] setMethod: @""]; ownerUser = [SOGoUser userWithLogin: owner]; @@ -574,7 +692,11 @@ attendees = [newEvent attendeesWithoutUser: ownerUser]; if ([attendees count]) { - [self _handleAddedUsers: attendees fromEvent: newEvent]; + // We catch conflicts and abort the save process immediately + // in case of one with resources + if ((ex = [self _handleAddedUsers: attendees fromEvent: newEvent])) + return ex; + [self sendEMailUsingTemplateNamed: @"Invitation" forObject: [newEvent itipEntryWithMethod: @"request"] previousObject: nil @@ -586,6 +708,7 @@ else { BOOL hasOrganizer; + // Event is modified -- sent update status to all attendees // and modify their calendars. recurrenceId = [newEvent recurrenceId]; @@ -606,8 +729,10 @@ hasOrganizer = [[[oldMasterEvent organizer] email] length]; if (!hasOrganizer || [oldMasterEvent userIsOrganizer: ownerUser]) - // The owner is the organizer of the event; handle the modifications - [self _handleUpdatedEvent: newEvent fromOldEvent: oldEvent]; + // The owner is the organizer of the event; handle the modifications. We aslo + // catch conflicts just like when the events are created + if ((ex = [self _handleUpdatedEvent: newEvent fromOldEvent: oldEvent])) + return ex; } [super saveComponent: newEvent]; @@ -618,6 +743,8 @@ safeCalendar = nil; [originalCalendar release]; originalCalendar = nil; + + return nil; } // @@ -1336,6 +1463,44 @@ [rq setContent: [[calendar versitString] dataUsingEncoding: [rq contentEncoding]]]; } +/** + * Verify vCalendar for any inconsistency or missing attributes. + * Currently only check if the events have an end date or a duration. + * @param rq the HTTP PUT request + */ +- (void) _adjustEventsInRequest: (WORequest *) rq +{ + iCalCalendar *calendar; + NSArray *allEvents; + iCalEvent *event; + NSUInteger i; + BOOL modified; + + calendar = [iCalCalendar parseSingleFromSource: [rq contentAsString]]; + allEvents = [calendar events]; + modified = NO; + + for (i = 0; i < [allEvents count]; i++) + { + event = [allEvents objectAtIndex: i]; + + if (![event hasEndDate] && ![event hasDuration]) + { + // No end date, no duration + if ([event isAllDay]) + [event setDuration: @"P1D"]; + else + [event setDuration: @"PT1H"]; + + modified = YES; + [self errorWithFormat: @"Invalid event: no end date; setting duration to %@", [event duration]]; + } + } + + if (modified) + [rq setContent: [[calendar versitString] dataUsingEncoding: [rq contentEncoding]]]; +} + - (void) _decomposeGroupsInRequest: (WORequest *) rq { iCalCalendar *calendar; @@ -1441,6 +1606,7 @@ // - (id) PUTAction: (WOContext *) _ctx { + NSException *ex; NSArray *roles; WORequest *rq; id response; @@ -1471,6 +1637,8 @@ { [self _adjustTransparencyInRequest: rq]; } + + [self _adjustEventsInRequest: rq]; } // @@ -1500,7 +1668,9 @@ attendees = [event attendeesWithoutUser: ownerUser]; if ([attendees count]) { - [self _handleAddedUsers: attendees fromEvent: event]; + if ((ex = [self _handleAddedUsers: attendees fromEvent: event])) + return ex; + [self sendEMailUsingTemplateNamed: @"Invitation" forObject: [event itipEntryWithMethod: @"request"] previousObject: nil @@ -1640,8 +1810,9 @@ if ([uid caseInsensitiveCompare: owner] == NSOrderedSame) { - [self _handleUpdatedEvent: newEvent fromOldEvent: oldEvent]; - + if ((ex = [self _handleUpdatedEvent: newEvent fromOldEvent: oldEvent])) + return ex; + // A RECURRENCE-ID was removed so there has to be a change in the master event // We could also have an EXDATE added in the master component of the attendees // so we always compare the MASTER event. diff --git a/SoObjects/Appointments/SOGoCalendarComponent.h b/SoObjects/Appointments/SOGoCalendarComponent.h index 1cc355f7b..84ab6034f 100644 --- a/SoObjects/Appointments/SOGoCalendarComponent.h +++ b/SoObjects/Appointments/SOGoCalendarComponent.h @@ -60,7 +60,7 @@ toFolder: (SOGoGCSFolder *) newFolder; - (void) updateComponent: (iCalRepeatableEntityObject *) newObject; -- (void) saveComponent: (iCalRepeatableEntityObject *) newObject; +- (NSException *) saveComponent: (iCalRepeatableEntityObject *) newObject; /* mail notifications */ - (void) sendEMailUsingTemplateNamed: (NSString *) pageName diff --git a/SoObjects/Appointments/SOGoCalendarComponent.m b/SoObjects/Appointments/SOGoCalendarComponent.m index 5a0f5fd8d..8a295c3aa 100644 --- a/SoObjects/Appointments/SOGoCalendarComponent.m +++ b/SoObjects/Appointments/SOGoCalendarComponent.m @@ -655,13 +655,15 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, } } -- (void) saveComponent: (iCalRepeatableEntityObject *) newObject +- (NSException *) saveComponent: (iCalRepeatableEntityObject *) newObject { NSString *newiCalString; newiCalString = [[newObject parent] versitString]; [self saveContentString: newiCalString]; + + return nil; } /* raw saving */ diff --git a/SoObjects/Appointments/SOGoFreeBusyObject.h b/SoObjects/Appointments/SOGoFreeBusyObject.h index c136d25b0..1a09a38f9 100644 --- a/SoObjects/Appointments/SOGoFreeBusyObject.h +++ b/SoObjects/Appointments/SOGoFreeBusyObject.h @@ -1,14 +1,15 @@ /* + Copyright (C) 2007-2011 Inverse inc. Copyright (C) 2000-2004 SKYRIX Software AG - This file is part of OGo + This file is part of SOGo - OGo is free software; you can redistribute it and/or modify it under + SOGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - OGo is distributed in the hope that it will be useful, but WITHOUT ANY + SOGo is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. diff --git a/SoObjects/Appointments/SOGoFreeBusyObject.m b/SoObjects/Appointments/SOGoFreeBusyObject.m index 9b302bc6a..28e76b15c 100644 --- a/SoObjects/Appointments/SOGoFreeBusyObject.m +++ b/SoObjects/Appointments/SOGoFreeBusyObject.m @@ -1,14 +1,15 @@ /* + Copyright (C) 2007-2011 Inverse inc. Copyright (C) 2000-2004 SKYRIX Software AG - This file is part of OGo + This file is part of SOGo - OGo is free software; you can redistribute it and/or modify it under + SOGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - OGo is distributed in the hope that it will be useful, but WITHOUT ANY + SOGo is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. diff --git a/SoObjects/Appointments/Spanish.lproj/Localizable.strings b/SoObjects/Appointments/Spanish.lproj/Localizable.strings index e05dc4c84..2b62986d3 100644 --- a/SoObjects/Appointments/Spanish.lproj/Localizable.strings +++ b/SoObjects/Appointments/Spanish.lproj/Localizable.strings @@ -60,3 +60,6 @@ vtodo_class2 = "(Tarea confidencial)"; = "%{Attendee} %{SentByText}has delegado la invitación para %{Delegate}."; "%{Attendee} %{SentByText}has not yet decided upon your event invitation." = "%{Attendee} %{SentByText}no ha tomado tadavia una decision sobre esta cita."; + +"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\"." = "Número máximo de reservas simultáneas (%{NumberOfSimultaneousBookings}) alcanzado para recurso \"%{Cn} %{SystemEmail}\"."; + diff --git a/SoObjects/Appointments/iCalEvent+SOGo.h b/SoObjects/Appointments/iCalEvent+SOGo.h index d7e970b5d..9d2ee9dd4 100644 --- a/SoObjects/Appointments/iCalEvent+SOGo.h +++ b/SoObjects/Appointments/iCalEvent+SOGo.h @@ -31,6 +31,7 @@ @interface iCalEvent (SOGoExtensions) - (BOOL) isStillRelevant; +- (unsigned int) occurenceInterval; - (NSMutableDictionary *) quickRecord; - (void) updateRecurrenceRulesUntilDate: (NSCalendarDate *) previousEndDate; diff --git a/SoObjects/Appointments/iCalEvent+SOGo.m b/SoObjects/Appointments/iCalEvent+SOGo.m index a645afc6a..089592dba 100644 --- a/SoObjects/Appointments/iCalEvent+SOGo.m +++ b/SoObjects/Appointments/iCalEvent+SOGo.m @@ -272,14 +272,22 @@ */ - (NGCalendarDateRange *) firstOccurenceRange { - iCalDateTime *firstStartDate, *firstEndDate; + iCalDateTime *firstStartDate; + NSCalendarDate *start, *end; NGCalendarDateRange *firstRange; - firstStartDate = (iCalDateTime *)[self uniqueChildWithTag: @"dtstart"]; - firstEndDate = (iCalDateTime *)[self uniqueChildWithTag: @"dtend"]; - firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: [[[firstStartDate values] lastObject] asCalendarDate] - endDate: [[[firstEndDate values] lastObject] asCalendarDate]]; + firstRange = nil; + firstStartDate = (iCalDateTime *)[self uniqueChildWithTag: @"dtstart"]; + if ([[firstStartDate values] count] > 0) + { + start = [[[firstStartDate values] lastObject] asCalendarDate]; + end = [start addTimeInterval: [self occurenceInterval]]; + + firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: start + endDate: end]; + } + return firstRange; } diff --git a/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m b/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m index 577cc8354..00276a1d6 100644 --- a/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m +++ b/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m @@ -131,8 +131,8 @@ firstRange = [self firstOccurenceRange]; // Set the range to check with respect to the event timezone (extracted from the start date) - firstStartDate = (iCalDateTime*) [self uniqueChildWithTag: @"dtstart"]; - eventTimeZone = [(iCalDateTime*) firstStartDate timeZone]; + firstStartDate = (iCalDateTime *)[self uniqueChildWithTag: @"dtstart"]; + eventTimeZone = [(iCalDateTime *)firstStartDate timeZone]; if (eventTimeZone) startDate = [eventTimeZone computedDateForDate: theOccurenceDate]; else @@ -144,12 +144,12 @@ // to the occurence's timezone. timeZone = [theOccurenceDate timeZone]; offset = [timeZone secondsFromGMTForDate: [firstRange startDate]]; - firstStartDate = (NSCalendarDate*) [[firstRange startDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 + firstStartDate = (NSCalendarDate *)[[firstRange startDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 seconds:-offset]; - firstEndDate = (NSCalendarDate*) [[firstRange endDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 + firstEndDate = (NSCalendarDate *)[[firstRange endDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 seconds:-offset]; - [(NSCalendarDate*) firstStartDate setTimeZone: timeZone]; - [(NSCalendarDate*) firstEndDate setTimeZone: timeZone]; + [(NSCalendarDate *)firstStartDate setTimeZone: timeZone]; + [(NSCalendarDate *)firstEndDate setTimeZone: timeZone]; firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: firstStartDate endDate: firstEndDate]; } diff --git a/SoObjects/Mailer/SOGoDraftObject.m b/SoObjects/Mailer/SOGoDraftObject.m index 6937fc9ef..b2804c824 100644 --- a/SoObjects/Mailer/SOGoDraftObject.m +++ b/SoObjects/Mailer/SOGoDraftObject.m @@ -1141,7 +1141,7 @@ static NSString *userAgent = nil; if ((s = [self contentTypeForAttachmentWithName:_name]) != nil) { [map setObject:s forKey: @"content-type"]; - if ([s hasPrefix: @"text/"]) + if ([s hasPrefix: @"text/plain"] || [s hasPrefix: @"text/html"]) attachAsString = YES; else if ([s hasPrefix: @"message/rfc822"]) is7bit = YES; diff --git a/SoObjects/Mailer/SOGoMailAccount.h b/SoObjects/Mailer/SOGoMailAccount.h index 56cb84653..cc3d331b1 100644 --- a/SoObjects/Mailer/SOGoMailAccount.h +++ b/SoObjects/Mailer/SOGoMailAccount.h @@ -57,6 +57,8 @@ typedef enum { SOGoTrashFolder *trashFolder; SOGoIMAPAclStyle imapAclStyle; NSMutableArray *identities; + NSString *otherUsersFolderName; + NSString *sharedFoldersName; } - (SOGoIMAPAclStyle) imapAclStyle; @@ -81,6 +83,8 @@ typedef enum { - (NSString *) draftsFolderNameInContext: (id)_ctx; - (NSString *) sentFolderNameInContext: (id)_ctx; - (NSString *) trashFolderNameInContext: (id)_ctx; +- (NSString *) otherUsersFolderNameInContext: (id)_ctx; +- (NSString *) sharedFoldersNameInContext: (id)_ctx; - (SOGoMailFolder *) inboxFolderInContext: (id)_ctx; - (SOGoDraftsFolder *) draftsFolderInContext: (id)_ctx; diff --git a/SoObjects/Mailer/SOGoMailAccount.m b/SoObjects/Mailer/SOGoMailAccount.m index 586605e2e..1e91b9c24 100644 --- a/SoObjects/Mailer/SOGoMailAccount.m +++ b/SoObjects/Mailer/SOGoMailAccount.m @@ -72,6 +72,8 @@ static NSString *sieveScriptName = @"sogo"; trashFolder = nil; imapAclStyle = undefined; identities = nil; + otherUsersFolderName = nil; + sharedFoldersName = nil; } return self; @@ -84,6 +86,8 @@ static NSString *sieveScriptName = @"sogo"; [sentFolder release]; [trashFolder release]; [identities release]; + [otherUsersFolderName release]; + [sharedFoldersName release]; [super dealloc]; } @@ -120,17 +124,33 @@ static NSString *sieveScriptName = @"sogo"; NSArray *namespace; NGImap4Client *client; + SOGoUser *user; + NSArray *accounts; + NSDictionary *account; + + user = [SOGoUser userWithLogin: [self ownerInContext: nil]]; + accounts = [user mailAccounts]; + account = [accounts objectAtIndex: [nameInContainer intValue]]; client = [[self imap4Connection] client]; namespaceDict = [client namespace]; + namespace = [namespaceDict objectForKey: @"personal"]; if (namespace) [self _appendNamespace: namespace toFolders: folders]; + namespace = [namespaceDict objectForKey: @"other users"]; if (namespace) - [self _appendNamespace: namespace toFolders: folders]; + { + [self _appendNamespace: namespace toFolders: folders]; + ASSIGN(otherUsersFolderName, [folders lastObject]); + } + namespace = [namespaceDict objectForKey: @"shared"]; if (namespace) - [self _appendNamespace: namespace toFolders: folders]; + { + [self _appendNamespace: namespace toFolders: folders]; + ASSIGN(sharedFoldersName, [folders lastObject]); + } } - (NSArray *) _namespacesWithKey: (NSString *) nsKey @@ -788,6 +808,16 @@ static NSString *sieveScriptName = @"sogo"; return [self _userFolderNameWithPurpose: @"Trash"]; } +- (NSString *) otherUsersFolderNameInContext: (id)_ctx +{ + return otherUsersFolderName; +} + +- (NSString *) sharedFoldersNameInContext: (id)_ctx +{ + return sharedFoldersName; +} + - (id) folderWithTraversal: (NSString *) traversal andClassName: (NSString *) className { diff --git a/SoObjects/SOGo/LDAPSource.h b/SoObjects/SOGo/LDAPSource.h index e77d5746a..3be52ee1d 100644 --- a/SoObjects/SOGo/LDAPSource.h +++ b/SoObjects/SOGo/LDAPSource.h @@ -4,6 +4,7 @@ * * Author: Wolfgang Sourdeau * Ludovic Marcotte + * Francis Lachapelle * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -53,7 +54,7 @@ NSString *CNField; NSString *UIDField; NSArray *mailFields, *searchFields; - NSString *IMAPHostField; + NSString *IMAPHostField, *IMAPLoginField; NSArray *bindFields; BOOL _bindAsCurrentUser; @@ -67,6 +68,10 @@ BOOL passwordPolicy; NSMutableDictionary *_dnCache; + + /* resources handling */ + NSString *kindField; + NSString *multipleBookingsField; } - (void) setBindDN: (NSString *) newBindDN @@ -83,7 +88,10 @@ mailFields: (NSArray *) newMailFields searchFields: (NSArray *) newSearchFields IMAPHostField: (NSString *) newIMAPHostField - andBindFields: (id) newBindFields; + IMAPLoginField: (NSString *) newIMAPLoginField + bindFields: (id) newBindFields + kindField: (NSString *) newKindField +andMultipleBookingsField: (NSString *) newMultipleBookingsField; - (NGLdapEntry *) lookupGroupEntryByUID: (NSString *) theUID; - (NGLdapEntry *) lookupGroupEntryByEmail: (NSString *) theEmail; diff --git a/SoObjects/SOGo/LDAPSource.m b/SoObjects/SOGo/LDAPSource.m index d844f946a..3ca5cce34 100644 --- a/SoObjects/SOGo/LDAPSource.m +++ b/SoObjects/SOGo/LDAPSource.m @@ -4,6 +4,7 @@ * * Author: Wolfgang Sourdeau * Ludovic Marcotte + * Francis Lachapelle * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -161,6 +162,7 @@ static NSArray *commonSearchFields; searchFields = [NSArray arrayWithObjects: @"sn", @"displayname", @"telephonenumber", nil]; [searchFields retain]; IMAPHostField = nil; + IMAPLoginField = nil; bindFields = nil; _scope = @"sub"; _filter = nil; @@ -168,6 +170,9 @@ static NSArray *commonSearchFields; searchAttributes = nil; passwordPolicy = NO; + kindField = nil; + multipleBookingsField = nil; + _dnCache = [[NSMutableDictionary alloc] init]; } @@ -176,7 +181,6 @@ static NSArray *commonSearchFields; - (void) dealloc { - NSLog(@"LDAPSource: -dealloc"); [bindDN release]; [hostname release]; [encryption release]; @@ -188,6 +192,7 @@ static NSArray *commonSearchFields; [mailFields release]; [searchFields release]; [IMAPHostField release]; + [IMAPLoginField release]; [bindFields release]; [_filter release]; [sourceID release]; @@ -196,6 +201,8 @@ static NSArray *commonSearchFields; [searchAttributes release]; [domain release]; [_dnCache release]; + [kindField release]; + [multipleBookingsField release]; [super dealloc]; } @@ -223,7 +230,10 @@ static NSArray *commonSearchFields; mailFields: [udSource objectForKey: @"MailFieldNames"] searchFields: [udSource objectForKey: @"SearchFieldNames"] IMAPHostField: [udSource objectForKey: @"IMAPHostFieldName"] - andBindFields: [udSource objectForKey: @"bindFields"]]; + IMAPLoginField: [udSource objectForKey: @"IMAPLoginFieldName"] + bindFields: [udSource objectForKey: @"bindFields"] + kindField: [udSource objectForKey: @"KindFieldName"] + andMultipleBookingsField: [udSource objectForKey: @"MultipleBookingsFieldName"]]; if ([sourceDomain length]) { @@ -305,7 +315,10 @@ static NSArray *commonSearchFields; mailFields: (NSArray *) newMailFields searchFields: (NSArray *) newSearchFields IMAPHostField: (NSString *) newIMAPHostField - andBindFields: (id) newBindFields + IMAPLoginField: (NSString *) newIMAPLoginField + bindFields: (id) newBindFields + kindField: (NSString *) newKindField +andMultipleBookingsField: (NSString *) newMultipleBookingsField { ASSIGN (baseDN, [newBaseDN lowercaseString]); if (newIDField) @@ -316,6 +329,8 @@ static NSArray *commonSearchFields; ASSIGN (UIDField, newUIDField); if (newIMAPHostField) ASSIGN (IMAPHostField, newIMAPHostField); + if (newIMAPLoginField) + ASSIGN (IMAPLoginField, newIMAPLoginField); if (newMailFields) ASSIGN (mailFields, newMailFields); if (newSearchFields) @@ -343,6 +358,10 @@ static NSArray *commonSearchFields; ASSIGN(bindFields, [newBindFields componentsSeparatedByString: @","]); } } + if (newKindField) + ASSIGN(kindField, newKindField); + if (newMultipleBookingsField) + ASSIGN(multipleBookingsField, newMultipleBookingsField); } - (BOOL) _setupEncryption: (NGLdapConnection *) encryptedConn @@ -694,6 +713,17 @@ static NSArray *commonSearchFields; // Add IMAP hostname from user defaults if ([IMAPHostField length]) [searchAttributes addObjectUniquely: IMAPHostField]; + + // Add IMAP login from user defaults + if ([IMAPLoginField length]) + [searchAttributes addObjectUniquely: IMAPLoginField]; + + // Add the resources handling attributes + if ([kindField length]) + [searchAttributes addObjectUniquely: kindField]; + + if ([multipleBookingsField length]) + [searchAttributes addObjectUniquely: multipleBookingsField]; } return searchAttributes; @@ -761,6 +791,13 @@ static NSArray *commonSearchFields; if ([ldapValue length] > 0) [contactEntry setObject: ldapValue forKey: @"c_imaphostname"]; } + + if (IMAPLoginField) + { + ldapValue = [[ldapEntry attributeWithName: IMAPLoginField] stringValueAtIndex: 0]; + if ([ldapValue length] > 0) + [contactEntry setObject: ldapValue forKey: @"c_imaplogin"]; + } } - (void) _fillConstraints: (NGLdapEntry *) ldapEntry @@ -838,6 +875,14 @@ static NSArray *commonSearchFields; [contactEntry setObject: [NSNumber numberWithInt: 1] forKey: @"isGroup"]; } + // We check if our entry is a resource. We also support + // determining resources based on the KindFieldName attribute + // value - see below. + else if ([classes containsObject: @"calendarresource"]) + { + [contactEntry setObject: [NSNumber numberWithInt: 1] + forKey: @"isResource"]; + } } while ((currentAttribute = [attributes nextObject])) @@ -847,7 +892,37 @@ static NSArray *commonSearchFields; // It's important here to set our attributes' key in lowercase. if (value) - [contactEntry setObject: value forKey: [currentAttribute lowercaseString]]; + { + currentAttribute = [currentAttribute lowercaseString]; + [contactEntry setObject: value forKey: currentAttribute]; + + // We check if that entry corresponds to a resource. For this, + // kindField must be defined and it must hold one of those values + // + // location + // thing + // group + // + if (kindField && + [kindField caseInsensitiveCompare: currentAttribute] == NSOrderedSame) + { + if ([value caseInsensitiveCompare: @"location"] == NSOrderedSame || + [value caseInsensitiveCompare: @"thing"] == NSOrderedSame || + [value caseInsensitiveCompare: @"group"] == NSOrderedSame) + { + [contactEntry setObject: [NSNumber numberWithInt: 1] + forKey: @"isResource"]; + } + } + // We check for the number of simultanous bookings that is allowed. + // A value of 0 means that there's no limit. + if (multipleBookingsField && + [multipleBookingsField caseInsensitiveCompare: currentAttribute] == NSOrderedSame) + { + [contactEntry setObject: [NSNumber numberWithInt: [value intValue]] + forKey: @"numberOfSimultaneousBookings"]; + } + } } value = [[ldapEntry attributeWithName: IDField] stringValueAtIndex: 0]; diff --git a/SoObjects/SOGo/SOGoFolder.m b/SoObjects/SOGo/SOGoFolder.m index ea89273ae..9079816b8 100644 --- a/SoObjects/SOGo/SOGoFolder.m +++ b/SoObjects/SOGo/SOGoFolder.m @@ -1,6 +1,6 @@ /* SOGoFolder.m - this file is part of SOGo * - * Copyright (C) 2007-2009 Inverse inc. + * Copyright (C) 2007-2011 Inverse inc. * * Author: Wolfgang Sourdeau * diff --git a/SoObjects/SOGo/SOGoGCSFolder.m b/SoObjects/SOGo/SOGoGCSFolder.m index 0e9c2093e..3eb0c742d 100644 --- a/SoObjects/SOGo/SOGoGCSFolder.m +++ b/SoObjects/SOGo/SOGoGCSFolder.m @@ -480,14 +480,17 @@ static NSArray *childRecordFields = nil; - (GCSFolder *) ocsFolder { GCSFolder *folder; + SOGoUser *user; NSString *userLogin; if (!ocsFolder) { ocsFolder = [self ocsFolderForPath: [self ocsPath]]; - userLogin = [[context activeUser] login]; + user = [context activeUser]; + userLogin = [user login]; if (!ocsFolder && [userLogin isEqualToString: [self ownerInContext: context]] + && [user canAuthenticate] && [self folderIsMandatory] && [self create]) ocsFolder = [self ocsFolderForPath: [self ocsPath]]; diff --git a/SoObjects/SOGo/SOGoGroup.m b/SoObjects/SOGo/SOGoGroup.m index 3f15cda4c..023961c7b 100644 --- a/SoObjects/SOGo/SOGoGroup.m +++ b/SoObjects/SOGo/SOGoGroup.m @@ -1,6 +1,6 @@ /* SOGoGroup.m - this file is part of SOGo * - * Copyright (C) 2009-2010 Inverse inc. + * Copyright (C) 2009-2011 Inverse inc. * * Author: Ludovic Marcotte * diff --git a/SoObjects/SOGo/SOGoParentFolder.m b/SoObjects/SOGo/SOGoParentFolder.m index 102816827..64cf44218 100644 --- a/SoObjects/SOGo/SOGoParentFolder.m +++ b/SoObjects/SOGo/SOGoParentFolder.m @@ -159,7 +159,12 @@ static SoSecurityManager *sm = nil; SOGoGCSFolder *folder; roles = [[context activeUser] rolesForObject: self inContext: context]; - if ([roles containsObject: SoRole_Owner]) + + // We autocreate the calendars if the user is the owner, a superuser or + // if it's a resource as we won't necessarily want to login as a resource + // in order to create its database tables. + if ([roles containsObject: SoRole_Owner] || + [[context activeUser] isResource]) { folder = [subFolderClass objectWithName: @"personal" inContainer: self]; [folder setDisplayName: [self defaultFolderName]]; diff --git a/SoObjects/SOGo/SOGoUser.h b/SoObjects/SOGo/SOGoUser.h index 00acf9962..2a003e3cc 100644 --- a/SoObjects/SOGo/SOGoUser.h +++ b/SoObjects/SOGo/SOGoUser.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2006-2010 Inverse inc. + Copyright (C) 2006-2011 Inverse inc. Copyright (C) 2005 SKYRIX Software AG This file is part of SOGo. @@ -112,17 +112,19 @@ - (NSMutableDictionary *) defaultIdentity; - (BOOL) isSuperUser; +- (BOOL) canAuthenticate; + +/* resource */ +- (BOOL) isResource; +- (int) numberOfSimultaneousBookings; /* module access */ - (BOOL) canAccessModule: (NSString *) module; /* folders */ - - (SOGoUserFolder *) homeFolderInContext: (id) context; - - (SOGoAppointmentFolders *) calendarsFolderInContext: (WOContext *) context; -- (SOGoAppointmentFolder *) - personalCalendarFolderInContext: (WOContext *) context; +- (SOGoAppointmentFolder *) personalCalendarFolderInContext: (WOContext *) context; @end diff --git a/SoObjects/SOGo/SOGoUser.m b/SoObjects/SOGo/SOGoUser.m index 26097fc62..1fcc859bb 100644 --- a/SoObjects/SOGo/SOGoUser.m +++ b/SoObjects/SOGo/SOGoUser.m @@ -757,6 +757,37 @@ return [[_domainDefaults superUsernames] containsObject: login]; } +- (BOOL) canAuthenticate +{ + id authValue; + + authValue = [self _fetchFieldForUser: @"canAuthenticate"]; + + return [authValue boolValue]; +} + +/* resource */ +- (BOOL) isResource +{ + NSNumber *v; + + v = [self _fetchFieldForUser: @"isResource"]; + + return (v && [v intValue]); +} + +- (int) numberOfSimultaneousBookings +{ + NSNumber *v; + + v = [self _fetchFieldForUser: @"numberOfSimultaneousBookings"]; + + if (v) + return [v intValue]; + + return 0; +} + /* module access */ - (BOOL) canAccessModule: (NSString *) module { diff --git a/SoObjects/SOGo/SOGoUserManager.m b/SoObjects/SOGo/SOGoUserManager.m index 5a19a6c41..36c55da2a 100644 --- a/SoObjects/SOGo/SOGoUserManager.m +++ b/SoObjects/SOGo/SOGoUserManager.m @@ -337,17 +337,23 @@ - (NSString *) getImapLoginForUID: (NSString *) uid { NSDictionary *contactInfos; - NSString *domain; + NSString *domain, *login; SOGoDomainDefaults *dd; contactInfos = [self contactInfosForUserWithUIDorEmail: uid]; + login = [contactInfos objectForKey: @"c_imaplogin"]; domain = [contactInfos objectForKey: @"c_domain"]; - if ([domain length]) - dd = [SOGoDomainDefaults defaultsForDomain: domain]; - else - dd = [SOGoSystemDefaults sharedSystemDefaults]; - - return ([dd forceIMAPLoginWithEmail] ? [self getEmailForUID: uid] : uid); + if (login == nil) + { + if ([domain length]) + dd = [SOGoDomainDefaults defaultsForDomain: domain]; + else + dd = [SOGoSystemDefaults sharedSystemDefaults]; + + login = [dd forceIMAPLoginWithEmail] ? [self getEmailForUID: uid] : uid; + } + + return login; } - (NSString *) getUIDForEmail: (NSString *) email @@ -542,6 +548,9 @@ [contact setObject: [emails objectAtIndex: 0] forKey: @"c_email"]; } +// +// +// - (void) _fillContactInfosForUser: (NSMutableDictionary *) currentUser withUIDorEmail: (NSString *) uid { @@ -549,7 +558,7 @@ NSDictionary *userEntry; NSEnumerator *sogoSources; NSObject *currentSource; - NSString *sourceID, *cn, *c_domain, *c_uid, *c_imaphostname; + NSString *sourceID, *cn, *c_domain, *c_uid, *c_imaphostname, *c_imaplogin; NSArray *c_emails; BOOL access; @@ -558,6 +567,7 @@ c_uid = nil; c_domain = nil; c_imaphostname = nil; + c_imaplogin = nil; [currentUser setObject: [NSNumber numberWithBool: YES] forKey: @"CalendarAccess"]; @@ -583,6 +593,8 @@ [emails addObjectsFromArray: c_emails]; if (!c_imaphostname) c_imaphostname = [userEntry objectForKey: @"c_imaphostname"]; + if (!c_imaplogin) + c_imaplogin = [userEntry objectForKey: @"c_imaplogin"]; access = [[userEntry objectForKey: @"CalendarAccess"] boolValue]; if (!access) [currentUser setObject: [NSNumber numberWithBool: NO] @@ -591,6 +603,15 @@ if (!access) [currentUser setObject: [NSNumber numberWithBool: NO] forKey: @"MailAccess"]; + + // We also fill the resource attributes, if any + if ([userEntry objectForKey: @"isResource"]) + [currentUser setObject: [userEntry objectForKey: @"isResource"] + forKey: @"isResource"]; + if ([userEntry objectForKey: @"numberOfSimultaneousBookings"]) + [currentUser setObject: [userEntry objectForKey: @"numberOfSimultaneousBookings"] + forKey: @"numberOfSimultaneousBookings"]; + } } @@ -603,6 +624,9 @@ if (c_imaphostname) [currentUser setObject: c_imaphostname forKey: @"c_imaphostname"]; + if (c_imaplogin) + [currentUser setObject: c_imaplogin forKey: @"c_imaplogin"]; + [currentUser setObject: emails forKey: @"emails"]; [currentUser setObject: cn forKey: @"cn"]; [currentUser setObject: c_uid forKey: @"c_uid"]; diff --git a/SoObjects/SOGo/SOGoUserSettings.m b/SoObjects/SOGo/SOGoUserSettings.m index 701009e17..74387cdb1 100644 --- a/SoObjects/SOGo/SOGoUserSettings.m +++ b/SoObjects/SOGo/SOGoUserSettings.m @@ -1,6 +1,6 @@ /* SOGoUserSettings.m - this file is part of SOGo * - * Copyright (C) 2009 Inverse inc. + * Copyright (C) 2009-2010 Inverse inc. * * Author: Wolfgang Sourdeau * diff --git a/SoObjects/SOGo/SQLSource.h b/SoObjects/SOGo/SQLSource.h index 18900cf5b..c7ce6a35e 100644 --- a/SoObjects/SOGo/SQLSource.h +++ b/SoObjects/SOGo/SQLSource.h @@ -2,7 +2,8 @@ * * Copyright (C) 2009-2011 Inverse inc. * - * Author: Ludovic Marcotte + * Authors: Ludovic Marcotte + * Francis Lachapelle * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,9 +37,15 @@ { NSString *_sourceID; NSString *_domain; + NSString *_authenticationFilter; NSArray *_mailFields; + NSString *_imapLoginField; NSString *_userPasswordAlgorithm; NSURL *_viewURL; + + /* resources handling */ + NSString *_kindField; + NSString *_multipleBookingsField; } @end diff --git a/SoObjects/SOGo/SQLSource.m b/SoObjects/SOGo/SQLSource.m index 9e8d653e4..62083fe0b 100644 --- a/SoObjects/SOGo/SQLSource.m +++ b/SoObjects/SOGo/SQLSource.m @@ -2,7 +2,8 @@ * * Copyright (C) 2009-2011 Inverse inc. * - * Author: Ludovic Marcotte + * Authors: Ludovic Marcotte + * Francis Lachapelle * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,9 +32,8 @@ #import #import +#import #import -#import -#import #import "SOGoConstants.h" #import "NSString+Utilities.h" @@ -79,9 +79,12 @@ if ((self = [super init])) { _sourceID = nil; + _authenticationFilter = nil; _mailFields = nil; _userPasswordAlgorithm = nil; _viewURL = nil; + _kindField = nil; + _multipleBookingsField = nil; } return self; @@ -90,9 +93,12 @@ - (void) dealloc { [_sourceID release]; + [_authenticationFilter release]; [_mailFields release]; [_userPasswordAlgorithm release]; [_viewURL release]; + [_kindField release]; + [_multipleBookingsField release]; [super dealloc]; } @@ -103,9 +109,13 @@ self = [self init]; ASSIGN(_sourceID, [udSource objectForKey: @"id"]); + ASSIGN(_authenticationFilter, [udSource objectForKey: @"authenticationFilter"]); ASSIGN(_mailFields, [udSource objectForKey: @"MailFieldNames"]); ASSIGN(_userPasswordAlgorithm, [udSource objectForKey: @"userPasswordAlgorithm"]); - + ASSIGN(_imapLoginField, [udSource objectForKey: @"IMAPLoginFieldName"]); + ASSIGN(_kindField, [udSource objectForKey: @"KindFieldName"]); + ASSIGN(_multipleBookingsField, [udSource objectForKey: @"MultipleBookingsFieldName"]); + if (!_userPasswordAlgorithm) _userPasswordAlgorithm = @"none"; @@ -203,9 +213,10 @@ grace: (int *) _grace { EOAdaptorChannel *channel; + EOQualifier *qualifier; GCSChannelManager *cm; NSException *ex; - NSString *sql; + NSMutableString *sql; BOOL rc; rc = NO; @@ -214,12 +225,25 @@ cm = [GCSChannelManager defaultChannelManager]; channel = [cm acquireOpenChannelForURL: _viewURL]; if (channel) - { - sql = [NSString stringWithFormat: (@"SELECT c_password" - @" FROM %@" - @" WHERE c_uid = '%@'"), - [_viewURL gcsTableName], _login]; - + { + qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"c_uid" + operatorSelector: EOQualifierOperatorEqual + value: _login]; + [qualifier autorelease]; + sql = [NSMutableString stringWithFormat: @"SELECT c_password" + @" FROM %@" + @" WHERE ", + [_viewURL gcsTableName]]; + if (_authenticationFilter) + { + qualifier = [[EOAndQualifier alloc] initWithQualifiers: + qualifier, + [EOQualifier qualifierWithQualifierFormat: _authenticationFilter], + nil]; + [qualifier autorelease]; + } + [qualifier _gcsAppendToString: sql]; + ex = [channel evaluateExpressionX: sql]; if (!ex) { @@ -235,7 +259,8 @@ [channel cancelFetch]; } else - [self errorWithFormat: @"could not run SQL '%@': %@", sql, ex]; + [self errorWithFormat: @"could not run SQL '%@': %@", qualifier, ex]; + [cm releaseChannel: channel]; } else @@ -328,8 +353,10 @@ { NSMutableDictionary *response; EOAdaptorChannel *channel; + EOQualifier *qualifier; GCSChannelManager *cm; - NSString *sql, *value; + NSMutableString *sql; + NSString *value; NSException *ex; response = nil; @@ -340,21 +367,21 @@ if (channel) { if (!b) - sql = [NSString stringWithFormat: (@"SELECT *" - @" FROM %@" - @" WHERE c_uid = '%@'"), - [_viewURL gcsTableName], theID]; + sql = [NSMutableString stringWithFormat: (@"SELECT *" + @" FROM %@" + @" WHERE c_uid = '%@'"), + [_viewURL gcsTableName], theID]; else { - sql = [NSString stringWithFormat: (@"SELECT *" - @" FROM %@" - @" WHERE c_uid = '%@' OR" - @" LOWER(mail) = '%@'"), - [_viewURL gcsTableName], theID, [theID lowercaseString]]; - + sql = [NSMutableString stringWithFormat: (@"SELECT *" + @" FROM %@" + @" WHERE c_uid = '%@' OR" + @" LOWER(mail) = '%@'"), + [_viewURL gcsTableName], theID, [theID lowercaseString]]; + if (_mailFields && [_mailFields count] > 0) { - sql = [sql stringByAppendingString: [self _whereClauseFromArray: _mailFields value: [theID lowercaseString] exact: YES]]; + [sql appendString: [self _whereClauseFromArray: _mailFields value: [theID lowercaseString] exact: YES]]; } } @@ -397,6 +424,73 @@ } [response setObject: emails forKey: @"c_emails"]; + + // We check if the user can authenticate + if (_authenticationFilter) + { + EOQualifier *q_uid, *q_auth; + + sql = [NSMutableString stringWithFormat: @"SELECT c_uid" + @" FROM %@" + @" WHERE ", + [_viewURL gcsTableName]]; + + q_auth = [EOQualifier qualifierWithQualifierFormat: _authenticationFilter]; + + q_uid = [[EOKeyValueQualifier alloc] initWithKey: @"c_uid" + operatorSelector: EOQualifierOperatorEqual + value: theID]; + [q_uid autorelease]; + + qualifier = [[EOAndQualifier alloc] initWithQualifiers: q_uid, q_auth, nil]; + [qualifier autorelease]; + [qualifier _gcsAppendToString: sql]; + + ex = [channel evaluateExpressionX: sql]; + if (!ex) + { + NSDictionary *authResponse; + + authResponse = [channel fetchAttributes: [channel describeResults: NO] withZone: NULL]; + [response setObject: [NSNumber numberWithBool: [authResponse count] > 0] forKey: @"canAuthenticate"]; + [channel cancelFetch]; + } + else + [self errorWithFormat: @"could not run SQL '%@': %@", sql, ex]; + } + else + [response setObject: [NSNumber numberWithBool: YES] forKey: @"canAuthenticate"]; + + // We check if we should use a different login for IMAP + if (_imapLoginField) + { + if ([response objectForKey: _imapLoginField]) + [response setObject: [response objectForKey: _imapLoginField] forKey: @"c_imaplogin"]; + } + + // We check if it's a resource of not + if (_kindField) + { + if ((value = [response objectForKey: _kindField])) + { + if ([value caseInsensitiveCompare: @"location"] == NSOrderedSame || + [value caseInsensitiveCompare: @"thing"] == NSOrderedSame || + [value caseInsensitiveCompare: @"group"] == NSOrderedSame) + { + [response setObject: [NSNumber numberWithInt: 1] + forKey: @"isResource"]; + } + } + } + + if (_multipleBookingsField) + { + if ((value = [response objectForKey: _multipleBookingsField])) + { + [response setObject: [NSNumber numberWithInt: [value intValue]] + forKey: @"numberOfSimultaneousBookings"]; + } + } } else [self errorWithFormat: @"could not run SQL '%@': %@", sql, ex]; diff --git a/Tests/Unit/GNUmakefile b/Tests/Unit/GNUmakefile index 0fa8ffd2a..f802eafef 100644 --- a/Tests/Unit/GNUmakefile +++ b/Tests/Unit/GNUmakefile @@ -19,7 +19,8 @@ $(TEST_TOOL)_OBJC_FILES += \ \ TestSBJsonParser.m \ \ - TestNGMimeAddressHeaderFieldGenerator.m + TestNGMimeAddressHeaderFieldGenerator.m \ + TestNSString+URLEscaping.m TOOL_NAME = $(TEST_TOOL) diff --git a/Tests/Unit/TestNSString+URLEscaping.m b/Tests/Unit/TestNSString+URLEscaping.m new file mode 100644 index 000000000..8267b2a20 --- /dev/null +++ b/Tests/Unit/TestNSString+URLEscaping.m @@ -0,0 +1,56 @@ +/* TestNSString+URLEscaping.m - this file is part of $PROJECT_NAME_HERE$ + * + * Copyright (C) 2011 Inverse inc + * + * Author: Wolfgang Sourdeau + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* This file is encoded in utf-8. */ + +#import + +#import "SOGoTest.h" + +@interface TestNSString_plus_URLEscaping : SOGoTest +@end + +@implementation TestNSString_plus_URLEscaping + +- (void) test_stringByEscapingURL +{ + const char *inStrings[] = { "éléphant", "2š", NULL }; + const char **inString; + NSString *outStrings[] = { @"%C3%A9l%C3%A9phant", @"2%C5%A1" }; + NSString **outString; + NSString *result, *error; + + inString = inStrings; + outString = outStrings; + while (*inString) + { + result = [[NSString stringWithUTF8String: *inString] stringByEscapingURL]; + error = [NSString stringWithFormat: + @"string '%s' badly escaped: '%@' (expected '%@')", + *inString, result, *outString]; + testWithMessage([result isEqualToString: *outString], error); + inString++; + outString++; + } +} + +@end diff --git a/Tests/Unit/sogo-tests.m b/Tests/Unit/sogo-tests.m index 35fb4f4ad..f7189d89e 100644 --- a/Tests/Unit/sogo-tests.m +++ b/Tests/Unit/sogo-tests.m @@ -28,8 +28,20 @@ int main() { NSAutoreleasePool *pool; int rc; + NSDictionary *defaults; + NSUserDefaults *ud; pool = [NSAutoreleasePool new]; + + defaults = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool: YES], + @"NGUseUTF8AsURLEncoding", + nil]; + ud = [NSUserDefaults standardUserDefaults]; + [ud setVolatileDomain: defaults + forName: @"sogo-tests-volatile"]; + [ud addSuiteNamed: @"sogo-tests-volatile"]; + rc = [[SOGoTestRunner testRunner] run]; [pool release]; diff --git a/UI/Contacts/GNUmakefile b/UI/Contacts/GNUmakefile index 7df81e254..acc321a97 100644 --- a/UI/Contacts/GNUmakefile +++ b/UI/Contacts/GNUmakefile @@ -9,7 +9,7 @@ ContactsUI_PRINCIPAL_CLASS = ContactsUIProduct ContactsUI_LANGUAGES = BrazilianPortuguese Catalan Czech Dutch English French German Hungarian Italian Norwegian Polish Russian Spanish Swedish Ukrainian Welsh ContactsUI_OBJC_FILES = \ - UIxContactsUserFolders.m \ + UIxContactsUserFolders.m \ UIxContactsMailerSelection.m \ UIxContactsUserRightsEditor.m \ \ @@ -18,10 +18,10 @@ ContactsUI_OBJC_FILES = \ UIxContactActions.m \ UIxContactView.m \ UIxContactEditor.m \ - UIxListView.m \ - UIxListEditor.m \ - UIxContactsListView.m \ - UIxContactFoldersView.m \ + UIxListView.m \ + UIxListEditor.m \ + UIxContactsListActions.m \ + UIxContactFoldersView.m \ UIxContactFolderActions.m ContactsUI_RESOURCE_FILES += \ diff --git a/UI/Contacts/UIxContactFoldersView.h b/UI/Contacts/UIxContactFoldersView.h index d385c1adf..f300cc6e5 100644 --- a/UI/Contacts/UIxContactFoldersView.h +++ b/UI/Contacts/UIxContactFoldersView.h @@ -29,6 +29,7 @@ @interface UIxContactFoldersView : UIxComponent { SOGoUserSettings *us; + NSDictionary *currentContact; NSString *selectorComponentClass; NSMutableDictionary *moduleSettings; id currentFolder; @@ -37,6 +38,8 @@ - (NSArray *) contactFolders; +- (NSArray *) personalContactInfos; + - (NSString *) currentContactFolderId; - (NSString *) currentContactFolderOwner; - (NSString *) currentContactFolderName; diff --git a/UI/Contacts/UIxContactFoldersView.m b/UI/Contacts/UIxContactFoldersView.m index 3fcdc1572..a9d56ac3e 100644 --- a/UI/Contacts/UIxContactFoldersView.m +++ b/UI/Contacts/UIxContactFoldersView.m @@ -87,6 +87,38 @@ } } +- (void) setCurrentContact: (NSDictionary *) _contact +{ + currentContact = _contact; +} + +- (NSDictionary *) currentContact +{ + return currentContact; +} + +- (NSString *) currentContactClasses +{ + return [[currentContact objectForKey: @"c_component"] lowercaseString]; +} + +- (NSArray *) personalContactInfos +{ + SOGoContactFolders *folders; + id folder; + NSArray *contactInfos; + + folders = [self clientObject]; + folder = [folders lookupPersonalFolder: @"personal" ignoringRights: YES]; + + contactInfos = [folder lookupContactsWithFilter: nil + onCriteria: nil + sortBy: @"c_cn" + ordering: NSOrderedAscending]; + + return contactInfos; +} + - (id ) mailerContactsAction { selectorComponentClass = @"UIxContactsMailerSelection"; @@ -316,8 +348,23 @@ - (id) defaultAction { + // NSString *check; + // WOResponse *response; + // static NSString *etag = @"\"contacts-ui\""; + [self checkDefaultModulePreference]; + // check = [[context request] headerForKey: @"if-none-match"]; + // if ([check length] > 0 && [check rangeOfString: etag].location != NSNotFound) /* not perfectly correct */ + // response = [self responseWithStatus: 304]; + // else + // { + // response = [context response]; + // [response setHeader: etag forKey: @"etag"]; + // response = (WOResponse *) [super defaultAction]; + // } + + // return response; return [super defaultAction]; } diff --git a/UI/Contacts/UIxContactsListView.h b/UI/Contacts/UIxContactsListActions.h similarity index 81% rename from UI/Contacts/UIxContactsListView.h rename to UI/Contacts/UIxContactsListActions.h index 2f6e0bf5e..875fed8f4 100644 --- a/UI/Contacts/UIxContactsListView.h +++ b/UI/Contacts/UIxContactsListActions.h @@ -19,17 +19,17 @@ 02111-1307, USA. */ -#ifndef __UIxContactsListView_H__ -#define __UIxContactsListView_H__ +#ifndef __UIxContactsListActions_H__ +#define __UIxContactsListActions_H__ -#import +#import @class NSDictionary; @class NSString; @protocol SOGoContactObject; -@interface UIxContactsListView : UIxComponent +@interface UIxContactsListActions : WODirectAction { NSDictionary *currentContact; NSArray *contactInfos; @@ -37,4 +37,4 @@ @end -#endif /* __UIxContactsListView_H__ */ +#endif /* __UIxContactsListActions_H__ */ diff --git a/UI/Contacts/UIxContactsListView.m b/UI/Contacts/UIxContactsListActions.m similarity index 81% rename from UI/Contacts/UIxContactsListView.m rename to UI/Contacts/UIxContactsListActions.m index bc2f07656..cd4ddf4ea 100644 --- a/UI/Contacts/UIxContactsListView.m +++ b/UI/Contacts/UIxContactsListActions.m @@ -1,5 +1,5 @@ /* - Copyright (C) 2006-2010 Inverse inc. + Copyright (C) 2006-2011 Inverse inc. Copyright (C) 2004-2005 SKYRIX Software AG This file is part of OpenGroupware.org. @@ -32,6 +32,8 @@ #import #import +#import + #import #import #import @@ -44,9 +46,9 @@ #import #import -#import "UIxContactsListView.h" +#import "UIxContactsListActions.h" -@implementation UIxContactsListView +@implementation UIxContactsListActions - (id) init { @@ -64,16 +66,6 @@ /* accessors */ -- (void) setCurrentContact: (NSDictionary *) _contact -{ - currentContact = _contact; -} - -- (NSDictionary *) currentContact -{ - return currentContact; -} - - (NSString *) defaultSortKey { return @"c_cn"; @@ -82,8 +74,10 @@ - (NSString *) sortKey { NSString *s; + WORequest *rq; - s = [self queryParameterForKey: @"sort"]; + rq = [context request]; + s = [rq formValueForKey: @"sort"]; if (![s length]) s = [self defaultSortKey]; @@ -95,18 +89,20 @@ id folder; NSString *ascending, *searchText, *valueText; NSComparisonResult ordering; + WORequest *rq; if (!contactInfos) { folder = [self clientObject]; + rq = [context request]; - ascending = [self queryParameterForKey: @"asc"]; + ascending = [rq formValueForKey: @"asc"]; ordering = ((![ascending length] || [ascending boolValue]) ? NSOrderedAscending : NSOrderedDescending); - searchText = [self queryParameterForKey: @"search"]; + searchText = [rq formValueForKey: @"search"]; if ([searchText length] > 0) - valueText = [self queryParameterForKey: @"value"]; + valueText = [rq formValueForKey: @"value"]; else valueText = nil; @@ -121,9 +117,21 @@ return contactInfos; } -- (NSString *) currentContactClasses +/** + * Retrieve the addressbook contacts with respect to the sort and + * search criteria. + * @return a JSON array of dictionaries representing the contacts. + */ +- (id ) contactsListAction { - return [[currentContact objectForKey: @"c_component"] lowercaseString]; + id result; + NSArray *contactsList; + + contactsList = [self contactInfos]; + result = [self responseWithStatus: 200 + andString: [contactsList jsonRepresentation]]; + + return result; } - (id ) contactSearchAction @@ -136,11 +144,12 @@ NSMutableDictionary *uniqueContacts; unsigned int i; NSSortDescriptor *commonNameDescriptor; + WORequest *rq; - searchText = [self queryParameterForKey: @"search"]; + rq = [context request]; + searchText = [rq formValueForKey: @"search"]; if ([searchText length] > 0) { - folder = nil; NS_DURING folder = [self clientObject]; NS_HANDLER @@ -176,9 +185,8 @@ data = [NSDictionary dictionaryWithObjectsAndKeys: searchText, @"searchText", sortedContacts, @"contacts", nil]; - result = [self responseWithStatus: 200]; - - [(WOResponse*)result appendContentString: [data jsonRepresentation]]; + result = [self responseWithStatus: 200 + andString: [data jsonRepresentation]]; } else result = [NSException exceptionWithHTTPStatus: 400 @@ -187,13 +195,4 @@ return result; } - -/* actions */ - -- (BOOL) shouldTakeValuesFromRequest: (WORequest *) _rq - inContext: (WOContext*) _c -{ - return YES; -} - -@end /* UIxContactsListView */ +@end /* UIxContactsListActions */ diff --git a/UI/Contacts/product.plist b/UI/Contacts/product.plist index 2136af2bf..e88d39ca5 100644 --- a/UI/Contacts/product.plist +++ b/UI/Contacts/product.plist @@ -71,11 +71,12 @@ methods = { view = { protectedBy = "View"; - pageName = "UIxContactsListView"; + actionClass = "UIxContactsListActions"; + actionName = "contactsList"; }; contactSearch = { protectedBy = ""; - pageName = "UIxContactsListView"; + actionClass = "UIxContactsListActions"; actionName = "contactSearch"; }; newcontact = { @@ -90,7 +91,7 @@ }; mailer-contacts = { protectedBy = "View"; - pageName = "UIxContactsListView"; + pageName = "UIxContactFoldersView"; actionName = "mailerContacts"; }; export = { @@ -130,7 +131,8 @@ methods = { view = { protectedBy = ""; - pageName = "UIxContactsListView"; + actionClass = "UIxContactsListActions"; + actionName = "contactsList"; }; newcontact = { protectedBy = ""; @@ -139,7 +141,7 @@ }; mailer-contacts = { protectedBy = ""; - pageName = "UIxContactsListView"; + pageName = "UIxContactFoldersView"; actionName = "mailerContacts"; }; canAccessContent = { diff --git a/UI/MailerUI/BrazilianPortuguese.lproj/Localizable.strings b/UI/MailerUI/BrazilianPortuguese.lproj/Localizable.strings index b225c75cd..60d582ffc 100644 --- a/UI/MailerUI/BrazilianPortuguese.lproj/Localizable.strings +++ b/UI/MailerUI/BrazilianPortuguese.lproj/Localizable.strings @@ -165,6 +165,8 @@ "InboxFolderName" = "Entrada"; "DraftsFolderName" = "Rascunhos"; "SieveFolderName" = "Filtros"; +"OtherUsersFolderName" = "Outros Usuários"; +"SharedFoldersName" = "Pastas Compartilhadas"; "Folders" = "Pastas"; /* title line */ /* MailMoveToPopUp */ @@ -286,4 +288,4 @@ /* Message sending */ "cannot send message: (smtp) all recipients discarded" = "Cannot send message: all recipients are invalid."; "cannot send message (smtp) - recipients discarded:" = "Cannot send message. The following addresses are invalid:"; -"cannot send message: (smtp) error when connecting" = "Cannot send message: error when connecting to the SMTP server."; \ No newline at end of file +"cannot send message: (smtp) error when connecting" = "Cannot send message: error when connecting to the SMTP server."; diff --git a/UI/MailerUI/Catalan.lproj/Localizable.strings b/UI/MailerUI/Catalan.lproj/Localizable.strings index a6fd89780..73ac708eb 100644 --- a/UI/MailerUI/Catalan.lproj/Localizable.strings +++ b/UI/MailerUI/Catalan.lproj/Localizable.strings @@ -165,6 +165,8 @@ "InboxFolderName" = "Safata d'entrada"; "DraftsFolderName" = "Esborranys"; "SieveFolderName" = "Filtres"; +"OtherUsersFolderName" = "Altres usuaris"; +"SharedFoldersName" = "Carpetes compartides"; "Folders" = "Carpetes"; /* title line */ /* MailMoveToPopUp */ @@ -286,4 +288,4 @@ /* Message sending */ "cannot send message: (smtp) all recipients discarded" = "Cannot send message: all recipients are invalid."; "cannot send message (smtp) - recipients discarded:" = "Cannot send message. The following addresses are invalid:"; -"cannot send message: (smtp) error when connecting" = "Cannot send message: error when connecting to the SMTP server."; \ No newline at end of file +"cannot send message: (smtp) error when connecting" = "Cannot send message: error when connecting to the SMTP server."; diff --git a/UI/MailerUI/Czech.lproj/Localizable.strings b/UI/MailerUI/Czech.lproj/Localizable.strings index e50b20eea..301c74541 100644 --- a/UI/MailerUI/Czech.lproj/Localizable.strings +++ b/UI/MailerUI/Czech.lproj/Localizable.strings @@ -165,6 +165,8 @@ "InboxFolderName" = "Doručená pošta"; "DraftsFolderName" = "Koncepty"; "SieveFolderName" = "Filtry"; +"OtherUsersFolderName" = "Ostatní uživatelé"; +"SharedFoldersName" = "Sdílené složky"; "Folders" = "Složky"; /* title line */ /* MailMoveToPopUp */ @@ -286,4 +288,4 @@ /* Message sending */ "cannot send message: (smtp) all recipients discarded" = "Cannot send message: all recipients are invalid."; "cannot send message (smtp) - recipients discarded:" = "Cannot send message. The following addresses are invalid:"; -"cannot send message: (smtp) error when connecting" = "Cannot send message: error when connecting to the SMTP server."; \ No newline at end of file +"cannot send message: (smtp) error when connecting" = "Cannot send message: error when connecting to the SMTP server."; diff --git a/UI/MailerUI/Dutch.lproj/Localizable.strings b/UI/MailerUI/Dutch.lproj/Localizable.strings index 18f6fedea..0187b0854 100644 --- a/UI/MailerUI/Dutch.lproj/Localizable.strings +++ b/UI/MailerUI/Dutch.lproj/Localizable.strings @@ -165,6 +165,8 @@ "InboxFolderName" = "Postvak IN"; "DraftsFolderName" = "Concepten"; "SieveFolderName" = "Berichtregel"; +"OtherUsersFolderName" = "Other Users"; +"SharedFoldersName" = "Shared Folders"; "Folders" = "Mappen"; /* title line */ /* MailMoveToPopUp */ @@ -286,4 +288,4 @@ /* Message sending */ "cannot send message: (smtp) all recipients discarded" = "Cannot send message: all recipients are invalid."; "cannot send message (smtp) - recipients discarded:" = "Cannot send message. The following addresses are invalid:"; -"cannot send message: (smtp) error when connecting" = "Cannot send message: error when connecting to the SMTP server."; \ No newline at end of file +"cannot send message: (smtp) error when connecting" = "Cannot send message: error when connecting to the SMTP server."; diff --git a/UI/MailerUI/English.lproj/Localizable.strings b/UI/MailerUI/English.lproj/Localizable.strings index aafc40dd7..3333f6765 100644 --- a/UI/MailerUI/English.lproj/Localizable.strings +++ b/UI/MailerUI/English.lproj/Localizable.strings @@ -165,6 +165,8 @@ "InboxFolderName" = "Inbox"; "DraftsFolderName" = "Drafts"; "SieveFolderName" = "Filters"; +"OtherUsersFolderName" = "Other Users"; +"SharedFoldersName" = "Shared Folders"; "Folders" = "Folders"; /* title line */ /* MailMoveToPopUp */ @@ -286,4 +288,4 @@ /* Message sending */ "cannot send message: (smtp) all recipients discarded" = "Cannot send message: all recipients are invalid."; "cannot send message (smtp) - recipients discarded:" = "Cannot send message. The following addresses are invalid:"; -"cannot send message: (smtp) error when connecting" = "Cannot send message: error when connecting to the SMTP server."; \ No newline at end of file +"cannot send message: (smtp) error when connecting" = "Cannot send message: error when connecting to the SMTP server."; diff --git a/UI/MailerUI/French.lproj/Localizable.strings b/UI/MailerUI/French.lproj/Localizable.strings index bec89ea95..aec2c38b5 100644 --- a/UI/MailerUI/French.lproj/Localizable.strings +++ b/UI/MailerUI/French.lproj/Localizable.strings @@ -165,6 +165,8 @@ "InboxFolderName" = "Courrier entrant"; "DraftsFolderName" = "Brouillons"; "SieveFolderName" = "Filtres"; +"OtherUsersFolderName" = "Autres utilisateurs"; +"SharedFoldersName" = "Dossiers partagés"; "Folders" = "Dossiers"; /* title line */ /* MailMoveToPopUp */ diff --git a/UI/MailerUI/German.lproj/Localizable.strings b/UI/MailerUI/German.lproj/Localizable.strings index 14e60b3e5..1f09a38f8 100644 --- a/UI/MailerUI/German.lproj/Localizable.strings +++ b/UI/MailerUI/German.lproj/Localizable.strings @@ -165,6 +165,8 @@ "InboxFolderName" = "Posteingang"; "DraftsFolderName" = "Entwürfe"; "SieveFolderName" = "Filter"; +"Other Users" = "Andere Benutzer"; +"Shared Folders" = "Gemeinsame Ordner"; "Folders" = "Ordner"; /* title line */ /* MailMoveToPopUp */ diff --git a/UI/MailerUI/Hungarian.lproj/Localizable.strings b/UI/MailerUI/Hungarian.lproj/Localizable.strings index adaf96dae..8d5b1176b 100644 --- a/UI/MailerUI/Hungarian.lproj/Localizable.strings +++ b/UI/MailerUI/Hungarian.lproj/Localizable.strings @@ -165,6 +165,8 @@ "InboxFolderName" = "Beérkezett üzenetek"; "DraftsFolderName" = "Piszkozatok"; "SieveFolderName" = "Szűrők"; +"OtherUsersFolderName" = "Egyéb felhasználók"; +"SharedFoldersName" = "Megosztott mappák"; "Folders" = "Mappák"; /* title line */ /* MailMoveToPopUp */ @@ -286,4 +288,4 @@ /* Message sending */ "cannot send message: (smtp) all recipients discarded" = "Cannot send message: all recipients are invalid."; "cannot send message (smtp) - recipients discarded:" = "Cannot send message. The following addresses are invalid:"; -"cannot send message: (smtp) error when connecting" = "Cannot send message: error when connecting to the SMTP server."; \ No newline at end of file +"cannot send message: (smtp) error when connecting" = "Cannot send message: error when connecting to the SMTP server."; diff --git a/UI/MailerUI/Italian.lproj/Localizable.strings b/UI/MailerUI/Italian.lproj/Localizable.strings index 435335ea5..12c198e58 100644 --- a/UI/MailerUI/Italian.lproj/Localizable.strings +++ b/UI/MailerUI/Italian.lproj/Localizable.strings @@ -165,6 +165,8 @@ "InboxFolderName" = "Posta in arrivo"; "DraftsFolderName" = "Bozze"; "SieveFolderName" = "Filtri"; +"OtherUsersFolderName" = "Altri Utenti"; +"SharedFoldersName" = "Cartelle Condivise"; "Folders" = "Cartelle"; /* title line */ /* MailMoveToPopUp */ diff --git a/UI/MailerUI/Norwegian.lproj/Localizable.strings b/UI/MailerUI/Norwegian.lproj/Localizable.strings index 76617e181..0e9eef368 100644 --- a/UI/MailerUI/Norwegian.lproj/Localizable.strings +++ b/UI/MailerUI/Norwegian.lproj/Localizable.strings @@ -165,6 +165,8 @@ "InboxFolderName" = "Innboks"; "DraftsFolderName" = "Kladder"; "SieveFolderName" = "Filter"; +"OtherUsersFolderName" = "Other Users"; +"SharedFoldersName" = "Shared Folders"; "Folders" = "Mapper"; /* title line */ /* MailMoveToPopUp */ diff --git a/UI/MailerUI/Polish.lproj/Localizable.strings b/UI/MailerUI/Polish.lproj/Localizable.strings index 30b1683e1..fadde0062 100644 --- a/UI/MailerUI/Polish.lproj/Localizable.strings +++ b/UI/MailerUI/Polish.lproj/Localizable.strings @@ -165,6 +165,8 @@ "InboxFolderName" = "Odebrane"; "DraftsFolderName" = "Szkice"; "SieveFolderName" = "Filtry"; +"OtherUsersFolderName" = "Other Users"; +"SharedFoldersName" = "Shared Folders"; "Folders" = "Foldery"; /* title line */ /* MailMoveToPopUp */ @@ -286,4 +288,4 @@ /* Message sending */ "cannot send message: (smtp) all recipients discarded" = "Cannot send message: all recipients are invalid."; "cannot send message (smtp) - recipients discarded:" = "Cannot send message. The following addresses are invalid:"; -"cannot send message: (smtp) error when connecting" = "Cannot send message: error when connecting to the SMTP server."; \ No newline at end of file +"cannot send message: (smtp) error when connecting" = "Cannot send message: error when connecting to the SMTP server."; diff --git a/UI/MailerUI/Russian.lproj/Localizable.strings b/UI/MailerUI/Russian.lproj/Localizable.strings index 42e573e51..e9c8705f5 100644 --- a/UI/MailerUI/Russian.lproj/Localizable.strings +++ b/UI/MailerUI/Russian.lproj/Localizable.strings @@ -165,6 +165,8 @@ "InboxFolderName" = "Входящие"; "DraftsFolderName" = "Черновики"; "SieveFolderName" = "Папки"; +"OtherUsersFolderName" = "Другие пользователи"; +"SharedFoldersName" = "Общие папки"; "Folders" = "Папки"; /* title line */ /* MailMoveToPopUp */ @@ -286,4 +288,4 @@ /* Message sending */ "cannot send message: (smtp) all recipients discarded" = "Cannot send message: all recipients are invalid."; "cannot send message (smtp) - recipients discarded:" = "Cannot send message. The following addresses are invalid:"; -"cannot send message: (smtp) error when connecting" = "Cannot send message: error when connecting to the SMTP server."; \ No newline at end of file +"cannot send message: (smtp) error when connecting" = "Cannot send message: error when connecting to the SMTP server."; diff --git a/UI/MailerUI/Spanish.lproj/Localizable.strings b/UI/MailerUI/Spanish.lproj/Localizable.strings index c3a81cfcf..56ca60c46 100644 --- a/UI/MailerUI/Spanish.lproj/Localizable.strings +++ b/UI/MailerUI/Spanish.lproj/Localizable.strings @@ -165,6 +165,8 @@ "InboxFolderName" = "Bandeja de entrada"; "DraftsFolderName" = "Borradores"; "SieveFolderName" = "Filtros"; +"OtherUsersFolderName" = "Otros usuarios"; +"SharedFoldersName" = "Carpetas compartidas"; "Folders" = "Carpetas"; /* title line */ /* MailMoveToPopUp */ @@ -286,4 +288,4 @@ /* Message sending */ "cannot send message: (smtp) all recipients discarded" = "No se puede enviar el mensaje: (smtp) todos los destinatarios han sido descartados"; "cannot send message (smtp) - recipients discarded:" = "No se puede enviar el mensaje: (smtp) destinatarios descartados:"; -"cannot send message: (smtp) error when connecting" = "No se puede enviar el mensaje: (smtp) error de conexión"; \ No newline at end of file +"cannot send message: (smtp) error when connecting" = "No se puede enviar el mensaje: (smtp) error de conexión"; diff --git a/UI/MailerUI/Swedish.lproj/Localizable.strings b/UI/MailerUI/Swedish.lproj/Localizable.strings index 4137cd8ba..7ac70600d 100644 --- a/UI/MailerUI/Swedish.lproj/Localizable.strings +++ b/UI/MailerUI/Swedish.lproj/Localizable.strings @@ -165,6 +165,8 @@ "InboxFolderName" = "Inkorgen"; "DraftsFolderName" = "Utkast"; "SieveFolderName" = "Filter"; +"OtherUsersFolderName" = "Other Users"; +"SharedFoldersName" = "Shared Folders"; "Folders" = "Mappar"; /* title line */ /* MailMoveToPopUp */ diff --git a/UI/MailerUI/UIxMailAccountActions.h b/UI/MailerUI/UIxMailAccountActions.h index 9e98ae5fb..08874fcf3 100644 --- a/UI/MailerUI/UIxMailAccountActions.h +++ b/UI/MailerUI/UIxMailAccountActions.h @@ -1,6 +1,6 @@ /* UIxMailAccountActions.h - this file is part of SOGo * - * Copyright (C) 2007 Inverse inc. + * Copyright (C) 2007-2011 Inverse inc. * * Author: Wolfgang Sourdeau * @@ -33,6 +33,8 @@ NSString *draftsFolderName; NSString *sentFolderName; NSString *trashFolderName; + NSString *otherUsersFolderName; + NSString *sharedFoldersName; } - (WOResponse *) listMailboxesAction; diff --git a/UI/MailerUI/UIxMailAccountActions.m b/UI/MailerUI/UIxMailAccountActions.m index f596c0c88..5633f1313 100644 --- a/UI/MailerUI/UIxMailAccountActions.m +++ b/UI/MailerUI/UIxMailAccountActions.m @@ -1,6 +1,6 @@ /* UIxMailAccountActions.m - this file is part of SOGo * - * Copyright (C) 2007, 2011 Inverse inc. + * Copyright (C) 2007-2011 Inverse inc. * * Author: Wolfgang Sourdeau * @@ -30,6 +30,7 @@ #import #import #import +#import #import #import @@ -39,6 +40,7 @@ #import #import #import +#import #import "../Common/WODirectAction+SOGo.h" @@ -54,6 +56,8 @@ draftsFolderName = nil; sentFolderName = nil; trashFolderName = nil; + otherUsersFolderName = nil; + sharedFoldersName = nil; } return self; @@ -65,6 +69,8 @@ [draftsFolderName release]; [sentFolderName release]; [trashFolderName release]; + [otherUsersFolderName release]; + [sharedFoldersName release]; [super dealloc]; } @@ -82,11 +88,17 @@ [co draftsFolderNameInContext: context], [co sentFolderNameInContext: context], [co trashFolderNameInContext: context], + [co otherUsersFolderNameInContext: context], + [co sharedFoldersNameInContext: context], nil] stringsWithFormat: @"/%@"]; - ASSIGN (inboxFolderName, [specialFolders objectAtIndex: 0]); - ASSIGN (draftsFolderName, [specialFolders objectAtIndex: 1]); - ASSIGN (sentFolderName, [specialFolders objectAtIndex: 2]); - ASSIGN (trashFolderName, [specialFolders objectAtIndex: 3]); + ASSIGN(inboxFolderName, [specialFolders objectAtIndex: 0]); + ASSIGN(draftsFolderName, [specialFolders objectAtIndex: 1]); + ASSIGN(sentFolderName, [specialFolders objectAtIndex: 2]); + ASSIGN(trashFolderName, [specialFolders objectAtIndex: 3]); + if ([specialFolders count] > 4) + ASSIGN(otherUsersFolderName, [specialFolders objectAtIndex: 4]); + if ([specialFolders count] > 5) + ASSIGN(sharedFoldersName, [specialFolders objectAtIndex: 5]); } if ([folderName isEqualToString: inboxFolderName]) @@ -105,17 +117,46 @@ - (NSArray *) _jsonFolders: (NSEnumerator *) rawFolders { - NSMutableArray *folders; - NSString *currentFolder; + NSString *currentFolder, *currentDisplayName, *currentFolderType, *login, *fullName; + NSMutableArray *pathComponents; + SOGoUserManager *userManager; NSDictionary *folderData; + NSMutableArray *folders; folders = [NSMutableArray array]; while ((currentFolder = [rawFolders nextObject])) { + currentFolderType = [self _folderType: currentFolder]; + + // We translate the "Other Users" and "Shared Folders" namespaces. + // While we're at it, we also translate the user's mailbox names + // to the full name of the person. + if (otherUsersFolderName && [currentFolder hasPrefix: otherUsersFolderName]) + { + // We have a string like /Other Users/lmarcotte/... + pathComponents = [NSMutableArray arrayWithArray: [currentFolder pathComponents]]; + login = [pathComponents objectAtIndex: 2]; + userManager = [SOGoUserManager sharedUserManager]; + fullName = [userManager getCNForUID: login]; + [pathComponents removeObjectsInRange: NSMakeRange(0,3)]; + + currentDisplayName = [NSString stringWithFormat: @"/%@/%@/%@", + [self labelForKey: @"OtherUsersFolderName"], + (fullName != nil ? fullName : login), + [pathComponents componentsJoinedByString: @"/"]]; + + } + else if (sharedFoldersName && [currentFolder hasPrefix: sharedFoldersName]) + currentDisplayName = [NSString stringWithFormat: @"/%@%@", [self labelForKey: @"SharedFoldersName"], + [currentFolder substringFromIndex: [sharedFoldersName length]]]; + else + currentDisplayName = currentFolder; + folderData = [NSDictionary dictionaryWithObjectsAndKeys: currentFolder, @"path", - [self _folderType: currentFolder], @"type", - nil]; + currentFolderType, @"type", + currentDisplayName, @"displayName", + nil]; [folders addObject: folderData]; } @@ -170,7 +211,7 @@ value = [[self request] formValueForKey: @"mailto"]; if ([value length] > 0) { - mailTo = [value componentsSeparatedByString: @","]; + mailTo = [[value stringByUnescapingURL] componentsSeparatedByString: @","]; [headers setObject: mailTo forKey: @"to"]; save = YES; } @@ -178,7 +219,7 @@ value = [[self request] formValueForKey: @"subject"]; if ([value length] > 0) { - [headers setObject: value forKey: @"subject"]; + [headers setObject: [value stringByUnescapingURL] forKey: @"subject"]; save = YES; } diff --git a/UI/MailerUI/UIxMailMainFrame.m b/UI/MailerUI/UIxMailMainFrame.m index 6fb38d5ef..302404db8 100644 --- a/UI/MailerUI/UIxMailMainFrame.m +++ b/UI/MailerUI/UIxMailMainFrame.m @@ -1,5 +1,5 @@ /* - Copyright (C) 2007-2010 Inverse inc. + Copyright (C) 2007-2011 Inverse inc. Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOGo. diff --git a/UI/MailerUI/Ukrainian.lproj/Localizable.strings b/UI/MailerUI/Ukrainian.lproj/Localizable.strings index f836f00a5..856b3d318 100644 --- a/UI/MailerUI/Ukrainian.lproj/Localizable.strings +++ b/UI/MailerUI/Ukrainian.lproj/Localizable.strings @@ -165,6 +165,8 @@ "InboxFolderName" = "Вхідні"; "DraftsFolderName" = "Чернетки"; "SieveFolderName" = "Теки"; +"OtherUsersFolderName" = "Інші користувачі"; +"SharedFoldersName" = "Спільні теки"; "Folders" = "Всі теки"; /* title line */ /* MailMoveToPopUp */ @@ -286,4 +288,4 @@ /* Message sending */ "cannot send message: (smtp) all recipients discarded" = "Помилка під час відправлення повідомлення: некоректні адреси всіх отримувачів."; "cannot send message (smtp) - recipients discarded:" = "Помила під час відправлення повідомлення: такі адреси некоректні:"; -"cannot send message: (smtp) error when connecting" = "Помилка під час відправлення повідомлення: SMTP-сервер не відповідає."; \ No newline at end of file +"cannot send message: (smtp) error when connecting" = "Помилка під час відправлення повідомлення: SMTP-сервер не відповідає."; diff --git a/UI/MailerUI/Welsh.lproj/Localizable.strings b/UI/MailerUI/Welsh.lproj/Localizable.strings index 1e895b250..c42752a34 100644 --- a/UI/MailerUI/Welsh.lproj/Localizable.strings +++ b/UI/MailerUI/Welsh.lproj/Localizable.strings @@ -165,6 +165,8 @@ "InboxFolderName" = "Newydd"; "DraftsFolderName" = "Draffts"; "SieveFolderName" = "Ffilteri"; +"OtherUsersFolderName" = "Other Users"; +"SharedFoldersName" = "Shared Folders"; "Folders" = "Ffolderi"; /* title line */ /* MailMoveToPopUp */ @@ -286,4 +288,4 @@ /* Message sending */ "cannot send message: (smtp) all recipients discarded" = "Cannot send message: all recipients are invalid."; "cannot send message (smtp) - recipients discarded:" = "Cannot send message. The following addresses are invalid:"; -"cannot send message: (smtp) error when connecting" = "Cannot send message: error when connecting to the SMTP server."; \ No newline at end of file +"cannot send message: (smtp) error when connecting" = "Cannot send message: error when connecting to the SMTP server."; diff --git a/UI/SOGoUI/UIxComponent.m b/UI/SOGoUI/UIxComponent.m index df69cb541..86a105f7d 100644 --- a/UI/SOGoUI/UIxComponent.m +++ b/UI/SOGoUI/UIxComponent.m @@ -1,14 +1,15 @@ /* + Copyright (C) 2007-2011 Inverse inc. Copyright (C) 2004 SKYRIX Software AG - This file is part of OpenGroupware.org. + This file is part of SOGo - OGo is free software; you can redistribute it and/or modify it under + SOGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - OGo is distributed in the hope that it will be useful, but WITHOUT ANY + SOGo is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. diff --git a/UI/SOGoUI/UIxJSClose.h b/UI/SOGoUI/UIxJSClose.h index 5a0820f78..41da7053a 100644 --- a/UI/SOGoUI/UIxJSClose.h +++ b/UI/SOGoUI/UIxJSClose.h @@ -1,6 +1,6 @@ /* UIxJSClose.h - this file is part of SOGo * - * Copyright (C) 2006 Inverse inc. + * Copyright (C) 2006-2011 Inverse inc. * * Author: Wolfgang Sourdeau * diff --git a/UI/SOGoUI/UIxJSClose.m b/UI/SOGoUI/UIxJSClose.m index 172e2b93a..936855232 100644 --- a/UI/SOGoUI/UIxJSClose.m +++ b/UI/SOGoUI/UIxJSClose.m @@ -1,6 +1,6 @@ /* UIxJSClose.m - this file is part of SOGo * - * Copyright (C) 2006 Inverse inc. + * Copyright (C) 2006-2011 Inverse inc. * * Author: Wolfgang Sourdeau * diff --git a/UI/Scheduler/BrazilianPortuguese.lproj/Localizable.strings b/UI/Scheduler/BrazilianPortuguese.lproj/Localizable.strings index 9e386ad19..ce67979d7 100644 --- a/UI/Scheduler/BrazilianPortuguese.lproj/Localizable.strings +++ b/UI/Scheduler/BrazilianPortuguese.lproj/Localizable.strings @@ -459,7 +459,7 @@ validate_endbeforestart = "A data que você informou ocorre antes da data ini "Workweek days only" = "Somente semanas úteis"; "Tasks in View" = "Tarefas na vista"; -"eventDeleteConfirmation" = "Apagar permanentemente este evento.\nVocê gostaria de continuar?"; +"eventDeleteConfirmation" = "O(s) seguinte(s) evento(s) será(ão) apagado(s): \n%{0}\nGostaria de continuar?"; "taskDeleteConfirmation" = "Apagar permanentemente esta tarefa.\nVocê gostaria de continuar?"; "You cannot remove nor unsubscribe from your personal calendar." diff --git a/UI/Scheduler/Catalan.lproj/Localizable.strings b/UI/Scheduler/Catalan.lproj/Localizable.strings index 76dd5a970..c45301acf 100644 --- a/UI/Scheduler/Catalan.lproj/Localizable.strings +++ b/UI/Scheduler/Catalan.lproj/Localizable.strings @@ -459,7 +459,7 @@ validate_endbeforestart = "La data/hora de començament és posterior a la d' "Workweek days only" = "Només dies laborables"; "Tasks in View" = "Mostrar tasques"; -"eventDeleteConfirmation" = "Aquest esdeveniment s'esborrarà definitivament. Voleu continuar?"; +"eventDeleteConfirmation" = "El següent esdeveniment (s) s'esborrarà: \n%{0}\nVoleu continuar?"; "taskDeleteConfirmation" = "Aquesta tasca s'esborrarà definitivament. Voleu continuar?"; "You cannot remove nor unsubscribe from your personal calendar." diff --git a/UI/Scheduler/Czech.lproj/Localizable.strings b/UI/Scheduler/Czech.lproj/Localizable.strings index 8936160a4..781c56174 100644 --- a/UI/Scheduler/Czech.lproj/Localizable.strings +++ b/UI/Scheduler/Czech.lproj/Localizable.strings @@ -459,7 +459,7 @@ validate_endbeforestart = "Zadané datum konce je před začátkem události. "Workweek days only" = "Pouze pracovní dny"; "Tasks in View" = "Zobrazené úkoly"; -"eventDeleteConfirmation" = "Smazání této události je permanentní.\nChcete pokračovat?"; +"eventDeleteConfirmation" = "Tato událost(i) bude smazána:\n%{0}\nChcete pokračovat?"; "taskDeleteConfirmation" = "Smazání tohoto úkolu je permanentní.\nChcete pokračovat?"; "You cannot remove nor unsubscribe from your personal calendar." diff --git a/UI/Scheduler/English.lproj/Localizable.strings b/UI/Scheduler/English.lproj/Localizable.strings index e85f21932..551c0bb4b 100644 --- a/UI/Scheduler/English.lproj/Localizable.strings +++ b/UI/Scheduler/English.lproj/Localizable.strings @@ -459,8 +459,8 @@ validate_endbeforestart = "The end date that you entered occurs before the st "Workweek days only" = "Workweek days only"; "Tasks in View" = "Tasks in View"; -"eventDeleteConfirmation" = "Erasing this event will be permanent.\nWould you like to continue?"; -"taskDeleteConfirmation" = "Erasing this task will be permanent.\nWould you like to continue?"; +"eventDeleteConfirmation" = "The following event(s) will be erased: \n%{0}\nWould you like to continue?"; +"taskDeleteConfirmation" = "The following task(s) will be erased: \n%{0}\nWould you like to continue?"; "You cannot remove nor unsubscribe from your personal calendar." = "You cannot remove nor unsubscribe from your personal calendar."; diff --git a/UI/Scheduler/French.lproj/Localizable.strings b/UI/Scheduler/French.lproj/Localizable.strings index 9d75161a1..6d0dd538e 100644 --- a/UI/Scheduler/French.lproj/Localizable.strings +++ b/UI/Scheduler/French.lproj/Localizable.strings @@ -459,8 +459,8 @@ validate_endbeforestart = "La date de fin est avant la date de début."; "Workweek days only" = "Semaine de travail seulement"; "Tasks in View" = "Afficher les tâches"; -"eventDeleteConfirmation" = "L'effacement de cet événement sera permanent.\nVoulez-vous continuer?"; -"taskDeleteConfirmation" = "L'effacement de cette tâche sera permanent.\nVoulez-vous continuer?"; +"eventDeleteConfirmation" = "Le ou les événements suivants seront supprimés :\n%{0}\nVoulez-vous continuer?"; +"taskDeleteConfirmation" = "Le ou les tâches suivantes seront supprimées :\n%{0}\nVoulez-vous continuer?"; "You cannot remove nor unsubscribe from your personal calendar." = "Vous ne pouvez pas supprimer ni vous désabonner de votre agenda personnel."; diff --git a/UI/Scheduler/German.lproj/Localizable.strings b/UI/Scheduler/German.lproj/Localizable.strings index 62070582c..034d2b0e4 100644 --- a/UI/Scheduler/German.lproj/Localizable.strings +++ b/UI/Scheduler/German.lproj/Localizable.strings @@ -459,7 +459,7 @@ validate_endbeforestart = "Ihr Beginn ist nach dem Ende"; "Workweek days only" = "nur Arbeitstage"; "Tasks in View" = "Aufgaben anzeigen"; -"eventDeleteConfirmation" = "Wollen Sie diesen Termin wirklich dauerhaft löschen?"; +"eventDeleteConfirmation" = "Diese Termine werden gelöscht: \n%{0}\nFortfahren?"; "taskDeleteConfirmation" = "Wollen Sie diese Aufgabe wirklich dauerhaft löschen?"; "You cannot remove nor unsubscribe from your personal calendar." diff --git a/UI/Scheduler/Hungarian.lproj/Localizable.strings b/UI/Scheduler/Hungarian.lproj/Localizable.strings index 91a3913a6..fa9547c7d 100644 --- a/UI/Scheduler/Hungarian.lproj/Localizable.strings +++ b/UI/Scheduler/Hungarian.lproj/Localizable.strings @@ -459,7 +459,7 @@ validate_endbeforestart = "A megadott befejező dátum korábbi, mint a kezd "Workweek days only" = "Csak hétköznapok"; "Tasks in View" = "Feladatok megjelenítése"; -"eventDeleteConfirmation" = "Az esemény törlése végleges.\nFolytatja?"; +"eventDeleteConfirmation" = "Az alábbi esemény(eke)t törli: \n%{0}\nFolytatja?"; "taskDeleteConfirmation" = "A feladat törlése végleges.\nFolytatja?"; "You cannot remove nor unsubscribe from your personal calendar." diff --git a/UI/Scheduler/Italian.lproj/Localizable.strings b/UI/Scheduler/Italian.lproj/Localizable.strings index caa581fef..7a75febde 100644 --- a/UI/Scheduler/Italian.lproj/Localizable.strings +++ b/UI/Scheduler/Italian.lproj/Localizable.strings @@ -453,7 +453,7 @@ validate_endbeforestart = "La data finale specificata è precedente alla data "Workweek days only" = "Solo giorni lavorativi"; "Tasks in View" = "Attività in elenco"; -"eventDeleteConfirmation" = "Stai per cancellare in maniera permanente l'evento.\nVuoi procedere?"; +"eventDeleteConfirmation" = "Il seguente evento(i) sarà cancellato: \n%{0}\nVuoi continuare?"; "taskDeleteConfirmation" = "Stai per cancellare in maniera permanente il l'attività.\nVuoi procedere?"; "You cannot remove nor unsubscribe from your personal calendar." diff --git a/UI/Scheduler/Russian.lproj/Localizable.strings b/UI/Scheduler/Russian.lproj/Localizable.strings index 56de269d0..d1bc797d1 100644 --- a/UI/Scheduler/Russian.lproj/Localizable.strings +++ b/UI/Scheduler/Russian.lproj/Localizable.strings @@ -459,7 +459,7 @@ validate_endbeforestart = "The end date that you entered occurs before the st "Workweek days only" = "Workweek days only"; "Tasks in View" = "Tasks in View"; -"eventDeleteConfirmation" = "Erasing this event will be permanent.\nWould you like to continue?"; +"eventDeleteConfirmation" = "Следующие события будут удалены: \n%{0}\nПродолжить удаление?"; "taskDeleteConfirmation" = "Erasing this task will be permanent.\nWould you like to continue?"; "You cannot remove nor unsubscribe from your personal calendar." diff --git a/UI/Scheduler/Spanish.lproj/Localizable.strings b/UI/Scheduler/Spanish.lproj/Localizable.strings index 6309eff09..46226c2cc 100644 --- a/UI/Scheduler/Spanish.lproj/Localizable.strings +++ b/UI/Scheduler/Spanish.lproj/Localizable.strings @@ -459,7 +459,7 @@ validate_endbeforestart = "La fecha/hora de inicio es posterior a la de fin." "Workweek days only" = "Sólo días laborables"; "Tasks in View" = "Mostrar tareas"; -"eventDeleteConfirmation" = "No se puede deshacer el borrado de este evento. ¿Desea continuar?"; +"eventDeleteConfirmation" = "Se eliminarán el/los siguiente(s) evento(s) : \n%{0}\n¿Desea proceder?"; "taskDeleteConfirmation" = "No se puede deshacer el borrado de esta tarea. ¿Desea continuar?"; "You cannot remove nor unsubscribe from your personal calendar." diff --git a/UI/Scheduler/UIxAppointmentEditor.m b/UI/Scheduler/UIxAppointmentEditor.m index b7a72bc60..5d07ecd6f 100644 --- a/UI/Scheduler/UIxAppointmentEditor.m +++ b/UI/Scheduler/UIxAppointmentEditor.m @@ -378,6 +378,7 @@ { SOGoAppointmentFolder *previousCalendar; SOGoAppointmentObject *co; + NSString *jsonResponse; SoSecurityManager *sm; NSException *ex; @@ -386,6 +387,7 @@ co = [co container]; previousCalendar = [co container]; sm = [SoSecurityManager sharedSecurityManager]; + ex = nil; if ([event hasRecurrenceRules]) [self _adjustRecurrentRules]; @@ -409,12 +411,12 @@ } // Save the event. - [co saveComponent: event]; + ex = [co saveComponent: event]; } else { // The event was modified -- save it. - [co saveComponent: event]; + ex = [co saveComponent: event]; if (componentCalendar && ![[componentCalendar ocsPath] @@ -432,8 +434,19 @@ } } } + + if (ex) + jsonResponse = [NSDictionary dictionaryWithObjectsAndKeys: + @"failure", @"status", + [ex reason], + @"message", + nil]; + else + jsonResponse = [NSDictionary dictionaryWithObjectsAndKeys: + @"success", @"status", nil]; - return [self jsCloseWithRefreshMethod: @"refreshEventsAndDisplay()"]; + return [self responseWithStatus: 200 + andString: [jsonResponse jsonRepresentation]]; } - (id ) viewAction diff --git a/UI/Scheduler/Ukrainian.lproj/Localizable.strings b/UI/Scheduler/Ukrainian.lproj/Localizable.strings index f690a7e19..070303f33 100644 --- a/UI/Scheduler/Ukrainian.lproj/Localizable.strings +++ b/UI/Scheduler/Ukrainian.lproj/Localizable.strings @@ -453,7 +453,7 @@ validate_endbeforestart = "Дата закінчення передує да "Workweek days only" = "Лише робочі дні"; "Tasks in View" = "Перегляд завдань"; -"eventDeleteConfirmation" = "Подію буде вилучено без можливості відновлення.\nПродовжити?"; +"eventDeleteConfirmation" = "Ці події буде вилучено: \n%{0}\nПродовжити?"; "taskDeleteConfirmation" = "Завдання буде вилучено назавжди.\nПродовжити?"; "You cannot remove nor unsubscribe from your personal calendar." diff --git a/UI/Templates/ContactsUI/UIxContactFoldersView.wox b/UI/Templates/ContactsUI/UIxContactFoldersView.wox index 2bd9210cc..e8f304862 100644 --- a/UI/Templates/ContactsUI/UIxContactFoldersView.wox +++ b/UI/Templates/ContactsUI/UIxContactFoldersView.wox @@ -138,11 +138,47 @@
-
+
+ + + + + + + + + + + + + + + + + + + +
+
-
+
diff --git a/UI/Templates/MailerUI/UIxMailToSelection.wox b/UI/Templates/MailerUI/UIxMailToSelection.wox index 6a51f9293..c3b3b3b4d 100644 --- a/UI/Templates/MailerUI/UIxMailToSelection.wox +++ b/UI/Templates/MailerUI/UIxMailToSelection.wox @@ -13,8 +13,7 @@ + > diff --git a/UI/Templates/SchedulerUI/UIxComponentEditor.wox b/UI/Templates/SchedulerUI/UIxComponentEditor.wox index 3d7cbcecb..4ccd91a18 100644 --- a/UI/Templates/SchedulerUI/UIxComponentEditor.wox +++ b/UI/Templates/SchedulerUI/UIxComponentEditor.wox @@ -37,7 +37,7 @@ - +
',a.document);o.appendTo(a.document.getHead());try{b.hc=o.getComputedStyle('background-image')=='none';}catch(p){b.hc=false; -}if(b.hc)b.cssClass+=' cke_hc';o.remove();})();j.load(i.corePlugins.split(','),function(){a.status='loaded';a.fire('loaded');var l=a._.pending;if(l){delete a._.pending;for(var m=0;m0){z=A.shift();while(!z.getParent().equals(D))z=z.getParent();if(!z.equals(H))E.push(z);H=z;}while(E.length>0){z=E.shift();if(z.getName()=='blockquote'){var I=new d.documentFragment(q.document);while(z.getFirst()){I.append(z.getFirst().remove());A.push(I.getLast());}I.replace(z);}else A.push(z);}var J=q.document.createElement('blockquote');J.insertBefore(A[0]);while(A.length>0){z=A.shift();J.append(z);}}else if(r==1){var K=[],L={};while(z=y.getNextParagraph()){var M=null,N=null;while(z.getParent()){if(z.getParent().getName()=='blockquote'){M=z.getParent();N=z;break;}z=z.getParent();}if(M&&N&&!N.getCustomData('blockquote_moveout')){K.push(N);h.setMarker(L,N,'blockquote_moveout',true);}}h.clearAllMarkers(L); -var O=[],P=[];L={};while(K.length>0){var Q=K.shift();J=Q.getParent();if(!Q.getPrevious())Q.remove().insertBefore(J);else if(!Q.getNext())Q.remove().insertAfter(J);else{Q.breakParent(Q.getParent());P.push(Q.getNext());}if(!J.getCustomData('blockquote_processed')){P.push(J);h.setMarker(L,J,'blockquote_processed',true);}O.push(Q);}h.clearAllMarkers(L);for(F=P.length-1;F>=0;F--){J=P[F];if(o(J))J.remove();}if(q.config.enterMode==2){var R=true;while(O.length){Q=O.shift();if(Q.getName()=='div'){I=new d.documentFragment(q.document);var S=R&&Q.getPrevious()&&!(Q.getPrevious().type==1&&Q.getPrevious().isBlockBoundary());if(S)I.append(q.document.createElement('br'));var T=Q.getNext()&&!(Q.getNext().type==1&&Q.getNext().isBlockBoundary());while(Q.getFirst())Q.getFirst().remove().appendTo(I);if(T)I.append(q.document.createElement('br'));I.replace(Q);R=false;}}}}s.selectBookmarks(u);q.focus();}};j.add('blockquote',{init:function(q){q.addCommand('blockquote',p);q.ui.addButton('Blockquote',{label:q.lang.blockquote,command:'blockquote'});q.on('selectionChange',n);},requires:['domiterator']});})();j.add('button',{beforeInit:function(m){m.ui.addHandler(1,k.button.handler);}});a.UI_BUTTON=1;k.button=function(m){e.extend(this,m,{title:m.label,className:m.className||m.command&&'cke_button_'+m.command||'',click:m.click||(function(n){n.execCommand(m.command);})});this._={};};k.button.handler={create:function(m){return new k.button(m);}};k.button._={instances:[],keydown:function(m,n){var o=k.button._.instances[m];if(o.onkey){n=new d.event(n);return o.onkey(o,n.getKeystroke())!==false;}},focus:function(m,n){var o=k.button._.instances[m],p;if(o.onfocus)p=o.onfocus(o,new d.event(n))!==false;if(b.gecko&&b.version<10900)n.preventBubble();return p;}};(function(){var m=e.addFunction(k.button._.keydown,k.button._),n=e.addFunction(k.button._.focus,k.button._);k.button.prototype={canGroup:true,render:function(o,p){var q=b,r=this._.id=e.getNextId(),s='',t=this.command,u,v;this._.editor=o;var w={id:r,button:this,editor:o,focus:function(){var z=a.document.getById(r);z.focus();},execute:function(){this.button.click(o);}};w.clickFn=u=e.addFunction(w.execute,w);w.index=v=k.button._.instances.push(w)-1;if(this.modes){var x={};o.on('beforeModeUnload',function(){x[o.mode]=this._.state;},this);o.on('mode',function(){var z=o.mode;this.setState(this.modes[z]?x[z]!=undefined?x[z]:2:0);},this);}else if(t){t=o.getCommand(t);if(t){t.on('state',function(){this.setState(t.state);},this);s+='cke_'+(t.state==1?'on':t.state==0?'disabled':'off'); -}}if(!t)s+='cke_off';if(this.className)s+=' '+this.className;p.push('','=10900&&!q.hc?'':'" href="javascript:void(\''+(this.title||'').replace("'",'')+"')\"",' title="',this.title,'" tabindex="-1" hidefocus="true" role="button" aria-labelledby="'+r+'_label"'+(this.hasArrow?' aria-haspopup="true"':''));if(q.opera||q.gecko&&q.mac)p.push(' onkeypress="return false;"');if(q.gecko)p.push(' onblur="this.style.cssText = this.style.cssText;"');p.push(' onkeydown="return CKEDITOR.tools.callFunction(',m,', ',v,', event);" onfocus="return CKEDITOR.tools.callFunction(',n,', ',v,', event);" onclick="CKEDITOR.tools.callFunction(',u,', this); return false;"> ',this.label,'');if(this.hasArrow)p.push(''+(b.hc?'▼':' ')+'');p.push('','');if(this.onRender)this.onRender();return w;},setState:function(o){if(this._.state==o)return false;this._.state=o;var p=a.document.getById(this._.id);if(p){p.setState(o);o==0?p.setAttribute('aria-disabled',true):p.removeAttribute('aria-disabled');o==1?p.setAttribute('aria-pressed',true):p.removeAttribute('aria-pressed');return true;}else return false;}};})();k.prototype.addButton=function(m,n){this.add(m,1,n);};a.on('reset',function(){k.button._.instances=[];});(function(){var m=function(x,y){var z=x.document,A=z.getBody(),B=0,C=function(){B=1;};A.on(y,C);(b.version>7?z.$:z.$.selection.createRange()).execCommand(y);A.removeListener(y,C);return B;},n=c?function(x,y){return m(x,y);}:function(x,y){try{return x.document.$.execCommand(y,false,null);}catch(z){return false;}},o=function(x){var y=this;y.type=x;y.canUndo=y.type=='cut';y.startDisabled=true;};o.prototype={exec:function(x,y){this.type=='cut'&&s(x);var z=n(x,this.type);if(!z)alert(x.lang.clipboard[this.type+'Error']);return z;}};var p={canUndo:false,exec:c?function(x){x.focus();if(!x.document.getBody().fire('beforepaste')&&!m(x,'paste')){x.fire('pasteDialog');return false;}}:function(x){try{if(!x.document.getBody().fire('beforepaste')&&!x.document.$.execCommand('Paste',false,null))throw 0;}catch(y){setTimeout(function(){x.fire('pasteDialog');},0);return false;}}},q=function(x){if(this.mode!='wysiwyg')return; -switch(x.data.keyCode){case 1000+86:case 2000+45:var y=this.document.getBody();if(!c&&y.fire('beforepaste'))x.cancel();else if(b.opera||b.gecko&&b.version<10900)y.fire('paste');return;case 1000+88:case 2000+46:var z=this;this.fire('saveSnapshot');setTimeout(function(){z.fire('saveSnapshot');},0);}};function r(x,y,z){var A=this.document;if(A.getById('cke_pastebin'))return;if(y=='text'&&x.data&&x.data.$.clipboardData){var B=x.data.$.clipboardData.getData('text/plain');if(B){x.data.preventDefault();z(B);return;}}var C=this.getSelection(),D=new d.range(A),E=new h(y=='text'?'textarea':b.webkit?'body':'div',A);E.setAttribute('id','cke_pastebin');b.webkit&&E.append(A.createText('\xa0'));A.getBody().append(E);E.setStyles({position:'absolute',top:C.getStartElement().getDocumentPosition().y+'px',width:'1px',height:'1px',overflow:'hidden'});E.setStyle(this.config.contentsLangDirection=='ltr'?'left':'right','-1000px');var F=C.createBookmarks();if(y=='text'){if(c){var G=A.getBody().$.createTextRange();G.moveToElementText(E.$);G.execCommand('Paste');x.data.preventDefault();}else E.$.focus();}else{D.setStartAt(E,1);D.setEndAt(E,2);D.select(true);}var H=this;window.setTimeout(function(){y=='text'&&b.gecko&&H.focusGrabber.focus();E.remove();var I;E=b.webkit&&(I=E.getFirst())&&I.is&&I.hasClass('Apple-style-span')?I:E;C.selectBookmarks(F);z(E['get'+(y=='text'?'Value':'Html')]());},0);};function s(x){if(!c||b.quirks)return;var y=x.getSelection(),z;if(y.getType()==3&&(z=y.getSelectedElement())){var A=y.getRanges()[0],B=x.document.createText('');B.insertBefore(z);A.setStartBefore(B);A.setEndAfter(z);y.selectRanges([A]);setTimeout(function(){if(z.getParent()){B.remove();y.selectElement(z);}},0);}};var t;function u(x,y){c&&(t=1);var z=y.document.$.queryCommandEnabled(x)?2:0;t=0;return z;};var v;function w(){var y=this;if(y.mode!='wysiwyg')return;y.getCommand('cut').setState(v?0:u('Cut',y));y.getCommand('copy').setState(u('Copy',y));var x=v?0:b.webkit?2:u('Paste',y);y.fire('pasteState',x);};j.add('clipboard',{requires:['dialog','htmldataprocessor'],init:function(x){x.on('paste',function(A){var B=A.data;if(B.html)x.insertHtml(B.html);else if(B.text)x.insertText(B.text);},null,null,1000);x.on('pasteDialog',function(A){setTimeout(function(){x.openDialog('paste');},0);});x.on('pasteState',function(A){x.getCommand('paste').setState(A.data);});function y(A,B,C,D){var E=x.lang[B];x.addCommand(B,C);x.ui.addButton(A,{label:E,command:B});if(x.addMenuItems)x.addMenuItem(B,{label:E,command:B,group:'clipboard',order:D}); -};y('Cut','cut',new o('cut'),1);y('Copy','copy',new o('copy'),4);y('Paste','paste',p,8);a.dialog.add('paste',a.getUrl(this.path+'dialogs/paste.js'));x.on('key',q,x);var z=x.config.forcePasteAsPlainText?'text':'html';x.on('contentDom',function(){var A=x.document.getBody();A.on(z=='text'&&c||b.webkit?'paste':'beforepaste',function(B){if(t)return;r.call(x,B,z,function(C){if(!C)return;var D={};D[z]=C;x.fire('paste',D);});});A.on('beforecut',function(){!t&&s(x);});A.on('mouseup',function(){setTimeout(function(){w.call(x);},0);},x);A.on('keyup',w,x);});x.on('selectionChange',function(A){v=A.data.selection.getRanges()[0].checkReadOnly();w.call(x);});if(x.contextMenu)x.contextMenu.addListener(function(A,B){var C=B.getRanges()[0].checkReadOnly();return{cut:!C&&u('Cut',x),copy:u('Copy',x),paste:!C&&(b.webkit?2:u('Paste',x))};});}});})();j.add('colorbutton',{requires:['panelbutton','floatpanel','styles'],init:function(m){var n=m.config,o=m.lang.colorButton,p;if(!b.hc){q('TextColor','fore',o.textColorTitle);q('BGColor','back',o.bgColorTitle);}function q(t,u,v){var w=e.getNextId()+'_colorBox';m.ui.add(t,4,{label:v,title:v,className:'cke_button_'+t.toLowerCase(),modes:{wysiwyg:1},panel:{css:m.skin.editor.css,attributes:{role:'listbox','aria-label':o.panelTitle}},onBlock:function(x,y){y.autoSize=true;y.element.addClass('cke_colorblock');y.element.setHtml(r(x,u,w));y.element.getDocument().getBody().setStyle('overflow','hidden');k.fire('ready',this);var z=y.keys,A=m.lang.dir=='rtl';z[A?37:39]='next';z[40]='next';z[9]='next';z[A?39:37]='prev';z[38]='prev';z[2000+9]='prev';z[32]='click';},onOpen:function(){var x=m.getSelection(),y=x&&x.getStartElement(),z=new d.elementPath(y),A;y=z.block||z.blockLimit;do A=y&&y.getComputedStyle(u=='back'?'background-color':'color')||'transparent';while(u=='back'&&A=='transparent'&&y&&(y=y.getParent()));if(!A||A=='transparent')A='#ffffff';this._.panel._.iframe.getFrameDocument().getById(w).setStyle('background-color',A);}});};function r(t,u,v){var w=[],x=n.colorButton_colors.split(','),y=x.length+(n.colorButton_enableMore?2:1),z=e.addFunction(function(F,G){if(F=='?'){var H=arguments.callee;function I(K){this.removeListener('ok',I);this.removeListener('cancel',I);K.name=='ok'&&H(this.getContentElement('picker','selectedColor').getValue(),G);};m.openDialog('colordialog',function(){this.on('ok',I);this.on('cancel',I);});return;}m.focus();t.hide();m.fire('saveSnapshot');new a.style(n['colorButton_'+G+'Style'],{color:'inherit'}).remove(m.document); -if(F){var J=n['colorButton_'+G+'Style'];J.childRule=G=='back'?function(K){return s(K);}:function(K){return K.getName()!='a'||s(K);};new a.style(J,{color:F}).apply(m.document);}m.fire('saveSnapshot');});w.push('
',o.auto,'
');for(var A=0;A');var B=x[A].split('/'),C=B[0],D=B[1]||C;if(!B[1])C='#'+C.replace(/^(.)(.)(.)$/,'$1$1$2$2$3$3');var E=m.lang.colors[D]||D;w.push('');}if(n.colorButton_enableMore===undefined||n.colorButton_enableMore)w.push('');w.push('
',o.more,'
');return w.join('');};function s(t){return t.getAttribute('contentEditable')=='false'||t.getAttribute('data-nostyle');};}});i.colorButton_colors='000,800000,8B4513,2F4F4F,008080,000080,4B0082,696969,B22222,A52A2A,DAA520,006400,40E0D0,0000CD,800080,808080,F00,FF8C00,FFD700,008000,0FF,00F,EE82EE,A9A9A9,FFA07A,FFA500,FFFF00,00FF00,AFEEEE,ADD8E6,DDA0DD,D3D3D3,FFF0F5,FAEBD7,FFFFE0,F0FFF0,F0FFFF,F0F8FF,E6E6FA,FFF';i.colorButton_foreStyle={element:'span',styles:{color:'#(color)'},overrides:[{element:'font',attributes:{color:null}}]};i.colorButton_backStyle={element:'span',styles:{'background-color':'#(color)'}};(function(){j.colordialog={init:function(m){m.addCommand('colordialog',new a.dialogCommand('colordialog'));a.dialog.add('colordialog',this.path+'dialogs/colordialog.js');}};j.add('colordialog',j.colordialog);})();j.add('contextmenu',{requires:['menu'],onLoad:function(){j.contextMenu=e.createClass({base:a.menu,$:function(m){this.base.call(this,m,{panel:{className:m.skinClass+' cke_contextmenu',attributes:{'aria-label':m.lang.contextmenu.options}}}); -},proto:{addTarget:function(m,n){if(b.opera&&!('oncontextmenu' in document.body)){var o;m.on('mousedown',function(s){s=s.data;if(s.$.button!=2){if(s.getKeystroke()==1000+1)m.fire('contextmenu',s);return;}if(n&&(b.mac?s.$.metaKey:s.$.ctrlKey))return;var t=s.getTarget();if(!o){var u=t.getDocument();o=u.createElement('input');o.$.type='button';u.getBody().append(o);}o.setAttribute('style','position:absolute;top:'+(s.$.clientY-2)+'px;left:'+(s.$.clientX-2)+'px;width:5px;height:5px;opacity:0.01');});m.on('mouseup',function(s){if(o){o.remove();o=undefined;m.fire('contextmenu',s.data);}});}m.on('contextmenu',function(s){var t=s.data;if(n&&(b.webkit?p:b.mac?t.$.metaKey:t.$.ctrlKey))return;t.preventDefault();var u=t.getTarget().getDocument().getDocumentElement(),v=t.$.clientX,w=t.$.clientY;e.setTimeout(function(){this.open(u,null,v,w);},0,this);},this);if(b.opera)m.on('keypress',function(s){var t=s.data;if(t.$.keyCode===0)t.preventDefault();});if(b.webkit){var p,q=function(s){p=b.mac?s.data.$.metaKey:s.data.$.ctrlKey;},r=function(){p=0;};m.on('keydown',q);m.on('keyup',r);m.on('contextmenu',r);}},open:function(m,n,o,p){this.editor.focus();m=m||a.document.getDocumentElement();this.show(m,n,o,p);}}});},beforeInit:function(m){m.contextMenu=new j.contextMenu(m);m.addCommand('contextMenu',{exec:function(){m.contextMenu.open(m.document.getBody());}});}});(function(){function m(o){var p=this.att,q=o&&o.hasAttribute(p)&&o.getAttribute(p)||'';if(q!==undefined)this.setValue(q);};function n(){var o;for(var p=0;p ';j.add('elementspath',{requires:['selection'],init:function(o){var p='cke_path_'+o.name,q,r=function(){if(!q)q=a.document.getById(p);return q;},s='cke_elementspath_'+e.getNextNumber()+'_';o._.elementsPath={idBase:s,filters:[]};o.on('themeSpace',function(w){if(w.data.space=='bottom')w.data.html+=''+o.lang.elementsPath.eleLabel+''+'
'+n+'
';});function t(w){o.focus();var x=o._.elementsPath.list[w];if(x.is('body')){var y=new d.range(o.document); -y.selectNodeContents(x);y.select();}else o.getSelection().selectElement(x);};var u=e.addFunction(t),v=e.addFunction(function(w,x){var y=o._.elementsPath.idBase,z;x=new d.event(x);var A=o.lang.dir=='rtl';switch(x.getKeystroke()){case A?39:37:case 9:z=a.document.getById(y+(w+1));if(!z)z=a.document.getById(y+'0');z.focus();return false;case A?37:39:case 2000+9:z=a.document.getById(y+(w-1));if(!z)z=a.document.getById(y+(o._.elementsPath.list.length-1));z.focus();return false;case 27:o.focus();return false;case 13:case 32:t(w);return false;}return true;});o.on('selectionChange',function(w){var x=b,y=w.data.selection,z=y.getStartElement(),A=[],B=w.editor,C=B._.elementsPath.list=[],D=B._.elementsPath.filters;while(z){var E=0;for(var F=0;F',H,''+J+'','');}if(H=='body')break;z=z.getParent();}var K=r();K.setHtml(A.join('')+n);B.fire('elementsPathUpdate',{space:K});});o.on('contentDomUnload',function(){q&&q.setHtml(n);});o.addCommand('elementsPathFocus',m.toolbarFocus);}});})();(function(){j.add('enterkey',{requires:['keystrokes','indent'],init:function(t){var u=t.specialKeys;u[13]=r;u[2000+13]=q;}});j.enterkey={enterBlock:function(t,u,v,w){v=v||s(t);if(!v)return;var x=v.document;if(v.checkStartOfBlock()&&v.checkEndOfBlock()){var y=new d.elementPath(v.startContainer),z=y.block;if(z&&(z.is('li')||z.getParent().is('li'))){t.execCommand('outdent');return;}}var A=u==3?'div':'p',B=v.splitBlock(A);if(!B)return;var C=B.previousBlock,D=B.nextBlock,E=B.wasStartOfBlock,F=B.wasEndOfBlock,G;if(D){G=D.getParent();if(G.is('li')){D.breakParent(G);D.move(D.getNext(),1);}}else if(C&&(G=C.getParent())&&G.is('li')){C.breakParent(G);v.moveToElementEditStart(C.getNext());C.move(C.getPrevious());}if(!E&&!F){if(D.is('li')&&(G=D.getFirst(d.walker.invisible(true)))&&G.is&&G.is('ul','ol'))(c?x.createText('\xa0'):x.createElement('br')).insertBefore(G); -if(D)v.moveToElementEditStart(D);}else{var H,I;if(C){if(C.is('li')||!p.test(C.getName()))H=C.clone();}else if(D)H=D.clone();if(!H){H=x.createElement(A);if(C&&(I=C.getDirection()))H.setAttribute('dir',I);}else if(w&&!H.is('li'))H.renameNode(A);var J=B.elementPath;if(J)for(var K=0,L=J.elements.length;K0;v--)u[v].deleteContents();return u[0];};})();(function(){var m='nbsp,gt,lt',n='quot,iexcl,cent,pound,curren,yen,brvbar,sect,uml,copy,ordf,laquo,not,shy,reg,macr,deg,plusmn,sup2,sup3,acute,micro,para,middot,cedil,sup1,ordm,raquo,frac14,frac12,frac34,iquest,times,divide,fnof,bull,hellip,prime,Prime,oline,frasl,weierp,image,real,trade,alefsym,larr,uarr,rarr,darr,harr,crarr,lArr,uArr,rArr,dArr,hArr,forall,part,exist,empty,nabla,isin,notin,ni,prod,sum,minus,lowast,radic,prop,infin,ang,and,or,cap,cup,int,there4,sim,cong,asymp,ne,equiv,le,ge,sub,sup,nsub,sube,supe,oplus,otimes,perp,sdot,lceil,rceil,lfloor,rfloor,lang,rang,loz,spades,clubs,hearts,diams,circ,tilde,ensp,emsp,thinsp,zwnj,zwj,lrm,rlm,ndash,mdash,lsquo,rsquo,sbquo,ldquo,rdquo,bdquo,dagger,Dagger,permil,lsaquo,rsaquo,euro',o='Agrave,Aacute,Acirc,Atilde,Auml,Aring,AElig,Ccedil,Egrave,Eacute,Ecirc,Euml,Igrave,Iacute,Icirc,Iuml,ETH,Ntilde,Ograve,Oacute,Ocirc,Otilde,Ouml,Oslash,Ugrave,Uacute,Ucirc,Uuml,Yacute,THORN,szlig,agrave,aacute,acirc,atilde,auml,aring,aelig,ccedil,egrave,eacute,ecirc,euml,igrave,iacute,icirc,iuml,eth,ntilde,ograve,oacute,ocirc,otilde,ouml,oslash,ugrave,uacute,ucirc,uuml,yacute,thorn,yuml,OElig,oelig,Scaron,scaron,Yuml',p='Alpha,Beta,Gamma,Delta,Epsilon,Zeta,Eta,Theta,Iota,Kappa,Lambda,Mu,Nu,Xi,Omicron,Pi,Rho,Sigma,Tau,Upsilon,Phi,Chi,Psi,Omega,alpha,beta,gamma,delta,epsilon,zeta,eta,theta,iota,kappa,lambda,mu,nu,xi,omicron,pi,rho,sigmaf,sigma,tau,upsilon,phi,chi,psi,omega,thetasym,upsih,piv'; +l.basePath=j;l.fileName=k;l.registered={};l.loaded={};l.externals={};l._={waitingList:{}};};a.resourceManager.prototype={add:function(j,k){if(this.registered[j])throw '[CKEDITOR.resourceManager.add] The resource name "'+j+'" is already registered.';a.fire(j+e.capitalize(this.fileName)+'Ready',this.registered[j]=k||{});},get:function(j){return this.registered[j]||null;},getPath:function(j){var k=this.externals[j];return a.getUrl(k&&k.dir||this.basePath+j+'/');},getFilePath:function(j){var k=this.externals[j];return a.getUrl(this.getPath(j)+(k&&typeof k.file=='string'?k.file:this.fileName+'.js'));},addExternal:function(j,k,l){j=j.split(',');for(var m=0;m1)return;var w=!p.css||!p.css.length,x=!p.js||!p.js.length,y=function(){if(w&&x){p._isLoaded=1;for(var B=0;B=0?x.langCode:J[0];if(!I.langEntries||!I.langEntries[L])G.push(a.getUrl(K+'lang/'+L+'.js'));else{e.extend(x.lang,I.langEntries[L]);L=null;}}F.push(L);E.push(I);}a.scriptLoader.load(G,function(){var M=['beforeInit','init','afterInit'];for(var N=0;N]+)>)|(?:!--([\\S|\\s]*?)-->)|(?:([^\\s>]+)\\s*((?:(?:[^\"'>]+)|(?:\"[^\"]*\")|(?:'[^']*'))*)\\/?>))",'g')};};(function(){var l=/([\w\-:.]+)(?:(?:\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))|(?=\s|$))/g,m={checked:1,compact:1,declare:1,defer:1,disabled:1,ismap:1,multiple:1,nohref:1,noresize:1,noshade:1,nowrap:1,readonly:1,selected:1};a.htmlParser.prototype={onTagOpen:function(){},onTagClose:function(){},onText:function(){},onCDATA:function(){},onComment:function(){},parse:function(n){var A=this;var o,p,q=0,r;while(o=A._.htmlPartsRegex.exec(n)){var s=o.index;if(s>q){var t=n.substring(q,s);if(r)r.push(t);else A.onText(t);}q=A._.htmlPartsRegex.lastIndex;if(p=o[1]){p=p.toLowerCase();if(r&&f.$cdata[p]){A.onCDATA(r.join(''));r=null;}if(!r){A.onTagClose(p);continue;}}if(r){r.push(o[0]);continue;}if(p=o[3]){p=p.toLowerCase();if(/="/.test(p))continue;var u={},v,w=o[4],x=!!(w&&w.charAt(w.length-1)=='/');if(w)while(v=l.exec(w)){var y=v[1].toLowerCase(),z=v[2]||v[3]||v[4]||'';if(!z&&m[y])u[y]=y;else u[y]=z;}A.onTagOpen(p,u,x);if(!r&&f.$cdata[p])r=[];continue;}if(p=o[2])A.onComment(p);}if(n.length>q)A.onText(n.substring(q,n.length));}};})();a.htmlParser.comment=function(l){this.value=l;this._={isBlockLike:false}; +};a.htmlParser.comment.prototype={type:8,writeHtml:function(l,m){var n=this.value;if(m){if(!(n=m.onComment(n,this)))return;if(typeof n!='string'){n.parent=this.parent;n.writeHtml(l,m);return;}}l.comment(n);}};(function(){var l=/[\t\r\n ]{2,}|[\t\r\n]/g;a.htmlParser.text=function(m){this.value=m;this._={isBlockLike:false};};a.htmlParser.text.prototype={type:3,writeHtml:function(m,n){var o=this.value;if(n&&!(o=n.onText(o,this)))return;m.text(o);}};})();(function(){a.htmlParser.cdata=function(l){this.value=l;};a.htmlParser.cdata.prototype={type:3,writeHtml:function(l){l.write(this.value);}};})();a.htmlParser.fragment=function(){this.children=[];this.parent=null;this._={isBlockLike:true,hasInlineStarted:false};};(function(){var l=e.extend({table:1,ul:1,ol:1,dl:1},f.table,f.ul,f.ol,f.dl),m={ol:1,ul:1},n=e.extend({},{html:1},f.html,f.body,f.head,{style:1,script:1});a.htmlParser.fragment.fromHtml=function(o,p,q){var r=new a.htmlParser(),s=q||new a.htmlParser.fragment(),t=[],u=[],v=s,w=false;function x(A){var B;if(t.length>0)for(var C=0;C=0;B--){if(A==t[B].name){t.splice(B,1);return;}}var C=[],D=[],E=v;while(E!=s&&E.name!=A){if(!E._.isBlockLike)D.unshift(E);C.push(E);E=E.returnPoint||E.parent;}if(E!=s){for(B=0;B0&&r.children[p-1]||null;if(q){if(o._.isBlockLike&&q.type==3){q.value=e.rtrim(q.value);if(q.value.length===0){r.children.pop();r.add(o);return;}}q.next=o;}o.previous=q;o.parent=r;r.children.push(o);r._.hasInlineStarted=o.type==3||o.type==1&&!o._.isBlockLike;},writeHtml:function(o,p){var q;this.filterChildren=function(){var r=new a.htmlParser.basicWriter();this.writeChildrenHtml.call(this,r,p,true);var s=r.getHtml();this.children=new a.htmlParser.fragment.fromHtml(s).children;q=1;};!this.name&&p&&p.onFragment(this);this.writeChildrenHtml(o,q?null:p);},writeChildrenHtml:function(o,p){for(var q=0;qn?1:0;};a.htmlParser.element.prototype={type:1,add:a.htmlParser.fragment.prototype.add,clone:function(){return new a.htmlParser.element(this.name,this.attributes);},writeHtml:function(m,n){var o=this.attributes,p=this,q=p.name,r,s,t,u;p.filterChildren=function(){if(!u){var z=new a.htmlParser.basicWriter();a.htmlParser.fragment.prototype.writeChildrenHtml.call(p,z,n);p.children=new a.htmlParser.fragment.fromHtml(z.getHtml(),0,p.clone()).children; +u=1;}};if(n){for(;;){if(!(q=n.onElementName(q)))return;p.name=q;if(!(p=n.onElement(p)))return;p.parent=this.parent;if(p.name==q)break;if(p.type!=1){p.writeHtml(m,n);return;}q=p.name;if(!q){this.writeChildrenHtml.call(p,m,u?null:n);return;}}o=p.attributes;}m.openTag(q,o);var v=[];for(var w=0;w<2;w++)for(r in o){s=r;t=o[r];if(w==1)v.push([r,t]);else if(n){for(;;){if(!(s=n.onAttributeName(r))){delete o[r];break;}else if(s!=r){delete o[r];r=s;continue;}else break;}if(s)if((t=n.onAttribute(p,s,t))===false)delete o[s];else o[s]=t;}}if(m.sortAttributes)v.sort(l);var x=v.length;for(w=0;w=0;u--){var x=r[u]; +if(x){x.pri=s;q.splice(t,0,x);}}}};function n(q,r,s){if(r)for(var t in r){var u=q[t];q[t]=o(u,r[t],s);if(!u)q.$length++;}};function o(q,r,s){if(r){r.pri=s;if(q){if(!q.splice){if(q.pri>s)q=[r,q];else q=[q,r];q.filter=p;}else m(q,r,s);return q;}else{r.filter=r;return r;}}};function p(q){var r=q.type||q instanceof a.htmlParser.fragment;for(var s=0;s');else this._.output.push('>');},attribute:function(l,m){if(typeof m=='string')m=e.htmlEncodeAttr(m);this._.output.push(' ',l,'="',m,'"');},closeTag:function(l){this._.output.push('');},text:function(l){this._.output.push(l);},comment:function(l){this._.output.push('');},write:function(l){this._.output.push(l);},reset:function(){this._.output=[];this._.indent=false;},getHtml:function(l){var m=this._.output.join('');if(l)this.reset();return m;}}});delete a.loadFullCore;a.instances={};a.document=new g(document);a.add=function(l){a.instances[l.name]=l;l.on('focus',function(){if(a.currentInstance!=l){a.currentInstance=l;a.fire('currentInstance');}});l.on('blur',function(){if(a.currentInstance==l){a.currentInstance=null;a.fire('currentInstance');}});};a.remove=function(l){delete a.instances[l.name];};a.on('instanceDestroyed',function(){if(e.isEmpty(this.instances))a.fire('reset');});a.TRISTATE_ON=1;a.TRISTATE_OFF=2;a.TRISTATE_DISABLED=0;d.comment=e.createClass({base:d.node,$:function(l,m){if(typeof l=='string')l=(m?m.$:document).createComment(l);this.base(l);},proto:{type:8,getOuterHtml:function(){return '';}}});(function(){var l={address:1,blockquote:1,dl:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,p:1,pre:1,li:1,dt:1,dd:1,legend:1},m={body:1,div:1,table:1,tbody:1,tr:1,td:1,th:1,caption:1,form:1,fieldset:1},n=function(o){var p=o.getChildren();for(var q=0,r=p.count();q0&&C.getChild(v.startOffset-1);this._.guardRTL=function(F,G){return(!G||!C.equals(F))&&(!D||!F.equals(D))&&(F.type!=1||!G||F.getName()!='body');};}var E=s?this._.guardRTL:this._.guardLTR;if(x)w=function(F,G){if(E(F,G)===false)return false;return x(F,G);};else w=E;if(this.current)u=this.current[z](false,y,w);else if(s){u=v.endContainer;if(v.endOffset>0){u=u.getChild(v.endOffset-1);if(w(u)===false)u=null;}else u=w(u,true)===false?null:u.getPreviousSourceNode(true,y,w);}else{u=v.startContainer; +u=u.getChild(v.startOffset);if(u){if(w(u)===false)u=null;}else u=w(v.startContainer,true)===false?null:v.startContainer.getNextSourceNode(true,y,w);}while(u&&!this._.end){this.current=u;if(!this.evaluator||this.evaluator(u)!==false){if(!t)return u;}else if(t&&this.evaluator)return false;u=u[z](false,y,w);}this.end();return this.current=null;};function m(s){var t,u=null;while(t=l.call(this,s))u=t;return u;};d.walker=e.createClass({$:function(s){this.range=s;this._={};},proto:{end:function(){this._.end=1;},next:function(){return l.call(this);},previous:function(){return l.call(this,1);},checkForward:function(){return l.call(this,0,1)!==false;},checkBackward:function(){return l.call(this,1,1)!==false;},lastForward:function(){return m.call(this);},lastBackward:function(){return m.call(this,1);},reset:function(){delete this.current;this._={};}}});var n={block:1,'list-item':1,table:1,'table-row-group':1,'table-header-group':1,'table-footer-group':1,'table-row':1,'table-column-group':1,'table-column':1,'table-cell':1,'table-caption':1};h.prototype.isBlockBoundary=function(s){var t=e.extend({},f.$block,s||{});return this.getComputedStyle('float')=='none'&&n[this.getComputedStyle('display')]||t[this.getName()];};d.walker.blockBoundary=function(s){return function(t,u){return!(t.type==1&&t.isBlockBoundary(s));};};d.walker.listItemBoundary=function(){return this.blockBoundary({br:1});};d.walker.bookmark=function(s,t){function u(v){return v&&v.getName&&v.getName()=='span'&&v.data('cke-bookmark');};return function(v){var w,x;w=v&&!v.getName&&(x=v.getParent())&&u(x);w=s?w:w||u(v);return!!(t^w);};};d.walker.whitespaces=function(s){return function(t){var u=t&&t.type==3&&!e.trim(t.getText());return!!(s^u);};};d.walker.invisible=function(s){var t=d.walker.whitespaces();return function(u){var v=t(u)||u.is&&!u.$.offsetHeight;return!!(s^v);};};d.walker.nodeType=function(s,t){return function(u){return!!(t^u.type==s);};};var o=/^[\t\r\n ]*(?: |\xa0)$/,p=d.walker.whitespaces(),q=d.walker.bookmark(),r=function(s){return q(s)||p(s)||s.type==1&&s.getName() in f.$inline&&!(s.getName() in f.$empty);};h.prototype.getBogus=function(){var s=this;do s=s.getPreviousSourceNode();while(r(s));if(s&&(!c?s.is&&s.is('br'):s.getText&&o.test(s.getText())))return s;return false;};})();d.range=function(l){var m=this;m.startContainer=null;m.startOffset=null;m.endContainer=null;m.endOffset=null;m.collapsed=true;m.document=l;};(function(){var l=function(t){t.collapsed=t.startContainer&&t.endContainer&&t.startContainer.equals(t.endContainer)&&t.startOffset==t.endOffset; +},m=function(t,u,v,w){t.optimizeBookmark();var x=t.startContainer,y=t.endContainer,z=t.startOffset,A=t.endOffset,B,C;if(y.type==3)y=y.split(A);else if(y.getChildCount()>0)if(A>=y.getChildCount()){y=y.append(t.document.createText(''));C=true;}else y=y.getChild(A);if(x.type==3){x.split(z);if(x.equals(y))y=x.getNext();}else if(!z){x=x.getFirst().insertBeforeMe(t.document.createText(''));B=true;}else if(z>=x.getChildCount()){x=x.append(t.document.createText(''));B=true;}else x=x.getChild(z).getPrevious();var D=x.getParents(),E=y.getParents(),F,G,H;for(F=0;F0&&!J.equals(y))K=I.append(J.clone());if(!D[O]||J.$.parentNode!=D[O].$.parentNode){L=J.getPrevious();while(L){if(L.equals(D[O])||L.equals(x))break;M=L.getPrevious();if(u==2)I.$.insertBefore(L.$.cloneNode(true),I.$.firstChild);else{L.remove();if(u==1)I.$.insertBefore(L.$,I.$.firstChild);}L=M;}}if(I)I=K;}if(u==2){var P=t.startContainer;if(P.type==3){P.$.data+=P.$.nextSibling.data;P.$.parentNode.removeChild(P.$.nextSibling);}var Q=t.endContainer;if(Q.type==3&&Q.$.nextSibling){Q.$.data+=Q.$.nextSibling.data;Q.$.parentNode.removeChild(Q.$.nextSibling);}}else{if(G&&H&&(x.$.parentNode!=G.$.parentNode||y.$.parentNode!=H.$.parentNode)){var R=H.getIndex();if(B&&H.$.parentNode==x.$.parentNode)R--;if(w&&G.type==1){var S=h.createFromHtml(' ',t.document);S.insertAfter(G);G.mergeSiblings(false);t.moveToBookmark({startNode:S});}else t.setStart(H.getParent(),R);}t.collapse(true);}if(B)x.remove();if(C&&y.$.parentNode)y.remove();},n={abbr:1,acronym:1,b:1,bdo:1,big:1,cite:1,code:1,del:1,dfn:1,em:1,font:1,i:1,ins:1,label:1,kbd:1,q:1,samp:1,small:1,span:1,strike:1,strong:1,sub:1,sup:1,tt:1,u:1,'var':1};function o(t){var u=false,v=d.walker.bookmark(true);return function(w){if(v(w))return true;if(w.type==3){if(e.trim(w.getText()).length)return false;}else if(w.type==1)if(!n[w.getName()])if(!t&&!c&&w.getName()=='br'&&!u)u=true;else return false;return true;};};function p(t){return t.type!=3&&t.getName() in f.$removeEmpty||!e.trim(t.getText())||!!t.getParent().data('cke-bookmark');};var q=new d.walker.whitespaces(),r=new d.walker.bookmark(); +function s(t){return!q(t)&&!r(t);};d.range.prototype={clone:function(){var u=this;var t=new d.range(u.document);t.startContainer=u.startContainer;t.startOffset=u.startOffset;t.endContainer=u.endContainer;t.endOffset=u.endOffset;t.collapsed=u.collapsed;return t;},collapse:function(t){var u=this;if(t){u.endContainer=u.startContainer;u.endOffset=u.startOffset;}else{u.startContainer=u.endContainer;u.startOffset=u.endOffset;}u.collapsed=true;},cloneContents:function(){var t=new d.documentFragment(this.document);if(!this.collapsed)m(this,2,t);return t;},deleteContents:function(t){if(this.collapsed)return;m(this,0,null,t);},extractContents:function(t){var u=new d.documentFragment(this.document);if(!this.collapsed)m(this,1,u,t);return u;},createBookmark:function(t){var z=this;var u,v,w,x,y=z.collapsed;u=z.document.createElement('span');u.data('cke-bookmark',1);u.setStyle('display','none');u.setHtml(' ');if(t){w='cke_bm_'+e.getNextNumber();u.setAttribute('id',w+'S');}if(!y){v=u.clone();v.setHtml(' ');if(t)v.setAttribute('id',w+'E');x=z.clone();x.collapse();x.insertNode(v);}x=z.clone();x.collapse(true);x.insertNode(u);if(v){z.setStartAfter(u);z.setEndBefore(v);}else z.moveToPosition(u,4);return{startNode:t?w+'S':u,endNode:t?w+'E':v,serializable:t,collapsed:y};},createBookmark2:function(t){var B=this;var u=B.startContainer,v=B.endContainer,w=B.startOffset,x=B.endOffset,y=B.collapsed,z,A;if(!u||!v)return{start:0,end:0};if(t){if(u.type==1){z=u.getChild(w);if(z&&z.type==3&&w>0&&z.getPrevious().type==3){u=z;w=0;}if(z&&z.type==1)w=z.getIndex(1);}while(u.type==3&&(A=u.getPrevious())&&A.type==3){u=A;w+=A.getLength();}if(!y){if(v.type==1){z=v.getChild(x);if(z&&z.type==3&&x>0&&z.getPrevious().type==3){v=z;x=0;}if(z&&z.type==1)x=z.getIndex(1);}while(v.type==3&&(A=v.getPrevious())&&A.type==3){v=A;x+=A.getLength();}}}return{start:u.getAddress(t),end:y?null:v.getAddress(t),startOffset:w,endOffset:x,normalized:t,collapsed:y,is2:true};},moveToBookmark:function(t){var B=this;if(t.is2){var u=B.document.getByAddress(t.start,t.normalized),v=t.startOffset,w=t.end&&B.document.getByAddress(t.end,t.normalized),x=t.endOffset;B.setStart(u,v);if(w)B.setEnd(w,x);else B.collapse(true);}else{var y=t.serializable,z=y?B.document.getById(t.startNode):t.startNode,A=y?B.document.getById(t.endNode):t.endNode;B.setStartBefore(z);z.remove();if(A){B.setEndBefore(A);A.remove();}else B.collapse(true);}},getBoundaryNodes:function(){var y=this;var t=y.startContainer,u=y.endContainer,v=y.startOffset,w=y.endOffset,x; +if(t.type==1){x=t.getChildCount();if(x>v)t=t.getChild(v);else if(x<1)t=t.getPreviousSourceNode();else{t=t.$;while(t.lastChild)t=t.lastChild;t=new d.node(t);t=t.getNextSourceNode()||t;}}if(u.type==1){x=u.getChildCount();if(x>w)u=u.getChild(w).getPreviousSourceNode(true);else if(x<1)u=u.getPreviousSourceNode();else{u=u.$;while(u.lastChild)u=u.lastChild;u=new d.node(u);}}if(t.getPosition(u)&2)t=u;return{startNode:t,endNode:u};},getCommonAncestor:function(t,u){var y=this;var v=y.startContainer,w=y.endContainer,x;if(v.equals(w)){if(t&&v.type==1&&y.startOffset==y.endOffset-1)x=v.getChild(y.startOffset);else x=v;}else x=v.getCommonAncestor(w);return u&&!x.is?x.getParent():x;},optimize:function(){var v=this;var t=v.startContainer,u=v.startOffset;if(t.type!=1)if(!u)v.setStartBefore(t);else if(u>=t.getLength())v.setStartAfter(t);t=v.endContainer;u=v.endOffset;if(t.type!=1)if(!u)v.setEndBefore(t);else if(u>=t.getLength())v.setEndAfter(t);},optimizeBookmark:function(){var v=this;var t=v.startContainer,u=v.endContainer;if(t.is&&t.is('span')&&t.data('cke-bookmark'))v.setStartAt(t,3);if(u&&u.is&&u.is('span')&&u.data('cke-bookmark'))v.setEndAt(u,4);},trim:function(t,u){var B=this;var v=B.startContainer,w=B.startOffset,x=B.collapsed;if((!t||x)&&v&&v.type==3){if(!w){w=v.getIndex();v=v.getParent();}else if(w>=v.getLength()){w=v.getIndex()+1;v=v.getParent();}else{var y=v.split(w);w=v.getIndex()+1;v=v.getParent();if(B.startContainer.equals(B.endContainer))B.setEnd(y,B.endOffset-B.startOffset);else if(v.equals(B.endContainer))B.endOffset+=1;}B.setStart(v,w);if(x){B.collapse(true);return;}}var z=B.endContainer,A=B.endOffset;if(!(u||x)&&z&&z.type==3){if(!A){A=z.getIndex();z=z.getParent();}else if(A>=z.getLength()){A=z.getIndex()+1;z=z.getParent();}else{z.split(A);A=z.getIndex()+1;z=z.getParent();}B.setEnd(z,A);}},enlarge:function(t,u){switch(t){case 1:if(this.collapsed)return;var v=this.getCommonAncestor(),w=this.document.getBody(),x,y,z,A,B,C=false,D,E,F=this.startContainer,G=this.startOffset;if(F.type==3){if(G){F=!e.trim(F.substring(0,G)).length&&F;C=!!F;}if(F)if(!(A=F.getPrevious()))z=F.getParent();}else{if(G)A=F.getChild(G-1)||F.getLast();if(!A)z=F;}while(z||A){if(z&&!A){if(!B&&z.equals(v))B=true;if(!w.contains(z))break;if(!C||z.getComputedStyle('display')!='inline'){C=false;if(B)x=z;else this.setStartBefore(z);}A=z.getPrevious();}while(A){D=false;if(A.type==3){E=A.getText();if(/[^\s\ufeff]/.test(E))A=null;D=/[\s\ufeff]$/.test(E);}else if((A.$.offsetWidth>0||u&&A.is('br'))&&!A.data('cke-bookmark'))if(C&&f.$removeEmpty[A.getName()]){E=A.getText(); +if(/[^\s\ufeff]/.test(E))A=null;else{var H=A.$.all||A.$.getElementsByTagName('*');for(var I=0,J;J=H[I++];){if(!f.$removeEmpty[J.nodeName.toLowerCase()]){A=null;break;}}}if(A)D=!!E.length;}else A=null;if(D)if(C){if(B)x=z;else if(z)this.setStartBefore(z);}else C=true;if(A){var K=A.getPrevious();if(!z&&!K){z=A;A=null;break;}A=K;}else z=null;}if(z)z=z.getParent();}F=this.endContainer;G=this.endOffset;z=A=null;B=C=false;if(F.type==3){F=!e.trim(F.substring(G)).length&&F;C=!(F&&F.getLength());if(F)if(!(A=F.getNext()))z=F.getParent();}else{A=F.getChild(G);if(!A)z=F;}while(z||A){if(z&&!A){if(!B&&z.equals(v))B=true;if(!w.contains(z))break;if(!C||z.getComputedStyle('display')!='inline'){C=false;if(B)y=z;else if(z)this.setEndAfter(z);}A=z.getNext();}while(A){D=false;if(A.type==3){E=A.getText();if(/[^\s\ufeff]/.test(E))A=null;D=/^[\s\ufeff]/.test(E);}else if((A.$.offsetWidth>0||u&&A.is('br'))&&!A.data('cke-bookmark'))if(C&&f.$removeEmpty[A.getName()]){E=A.getText();if(/[^\s\ufeff]/.test(E))A=null;else{H=A.$.all||A.$.getElementsByTagName('*');for(I=0;J=H[I++];){if(!f.$removeEmpty[J.nodeName.toLowerCase()]){A=null;break;}}}if(A)D=!!E.length;}else A=null;if(D)if(C)if(B)y=z;else this.setEndAfter(z);if(A){K=A.getNext();if(!z&&!K){z=A;A=null;break;}A=K;}else z=null;}if(z)z=z.getParent();}if(x&&y){v=x.contains(y)?y:x;this.setStartBefore(v);this.setEndAfter(v);}break;case 2:case 3:var L=new d.range(this.document);w=this.document.getBody();L.setStartAt(w,1);L.setEnd(this.startContainer,this.startOffset);var M=new d.walker(L),N,O,P=d.walker.blockBoundary(t==3?{br:1}:null),Q=function(S){var T=P(S);if(!T)N=S;return T;},R=function(S){var T=Q(S);if(!T&&S.is&&S.is('br'))O=S;return T;};M.guard=Q;z=M.lastBackward();N=N||w;this.setStartAt(N,!N.is('br')&&(!z&&this.checkStartOfBlock()||z&&N.contains(z))?1:4);L=this.clone();L.collapse();L.setEndAt(w,2);M=new d.walker(L);M.guard=t==3?R:Q;N=null;z=M.lastForward();N=N||w;this.setEndAt(N,!z&&this.checkEndOfBlock()||z&&N.contains(z)?2:3);if(O)this.setEndAfter(O);}},shrink:function(t,u){if(!this.collapsed){t=t||2;var v=this.clone(),w=this.startContainer,x=this.endContainer,y=this.startOffset,z=this.endOffset,A=this.collapsed,B=1,C=1;if(w&&w.type==3)if(!y)v.setStartBefore(w);else if(y>=w.getLength())v.setStartAfter(w);else{v.setStartBefore(w);B=0;}if(x&&x.type==3)if(!z)v.setEndBefore(x);else if(z>=x.getLength())v.setEndAfter(x);else{v.setEndAfter(x);C=0;}var D=new d.walker(v),E=d.walker.bookmark();D.evaluator=function(I){return I.type==(t==1?1:3); +};var F;D.guard=function(I,J){if(E(I))return true;if(t==1&&I.type==3)return false;if(J&&I.equals(F))return false;if(!J&&I.type==1)F=I;return true;};if(B){var G=D[t==1?'lastForward':'next']();G&&this.setStartAt(G,u?1:3);}if(C){D.reset();var H=D[t==1?'lastBackward':'previous']();H&&this.setEndAt(H,u?2:4);}return!!(B||C);}},insertNode:function(t){var x=this;x.optimizeBookmark();x.trim(false,true);var u=x.startContainer,v=x.startOffset,w=u.getChild(v);if(w)t.insertBefore(w);else u.append(t);if(t.getParent().equals(x.endContainer))x.endOffset++;x.setStartBefore(t);},moveToPosition:function(t,u){this.setStartAt(t,u);this.collapse(true);},selectNodeContents:function(t){this.setStart(t,0);this.setEnd(t,t.type==3?t.getLength():t.getChildCount());},setStart:function(t,u){var v=this;if(t.type==1&&f.$empty[t.getName()])u=t.getIndex(),t=t.getParent();v.startContainer=t;v.startOffset=u;if(!v.endContainer){v.endContainer=t;v.endOffset=u;}l(v);},setEnd:function(t,u){var v=this;if(t.type==1&&f.$empty[t.getName()])u=t.getIndex()+1,t=t.getParent();v.endContainer=t;v.endOffset=u;if(!v.startContainer){v.startContainer=t;v.startOffset=u;}l(v);},setStartAfter:function(t){this.setStart(t.getParent(),t.getIndex()+1);},setStartBefore:function(t){this.setStart(t.getParent(),t.getIndex());},setEndAfter:function(t){this.setEnd(t.getParent(),t.getIndex()+1);},setEndBefore:function(t){this.setEnd(t.getParent(),t.getIndex());},setStartAt:function(t,u){var v=this;switch(u){case 1:v.setStart(t,0);break;case 2:if(t.type==3)v.setStart(t,t.getLength());else v.setStart(t,t.getChildCount());break;case 3:v.setStartBefore(t);break;case 4:v.setStartAfter(t);}l(v);},setEndAt:function(t,u){var v=this;switch(u){case 1:v.setEnd(t,0);break;case 2:if(t.type==3)v.setEnd(t,t.getLength());else v.setEnd(t,t.getChildCount());break;case 3:v.setEndBefore(t);break;case 4:v.setEndAfter(t);}l(v);},fixBlock:function(t,u){var x=this;var v=x.createBookmark(),w=x.document.createElement(u);x.collapse(t);x.enlarge(2);x.extractContents().appendTo(w);w.trim();if(!c)w.appendBogus();x.insertNode(w);x.moveToBookmark(v);return w;},splitBlock:function(t){var D=this;var u=new d.elementPath(D.startContainer),v=new d.elementPath(D.endContainer),w=u.blockLimit,x=v.blockLimit,y=u.block,z=v.block,A=null;if(!w.equals(x))return null;if(t!='br'){if(!y){y=D.fixBlock(true,t);z=new d.elementPath(D.endContainer).block;}if(!z)z=D.fixBlock(false,t);}var B=y&&D.checkStartOfBlock(),C=z&&D.checkEndOfBlock();D.deleteContents();if(y&&y.equals(z))if(C){A=new d.elementPath(D.startContainer); +D.moveToPosition(z,4);z=null;}else if(B){A=new d.elementPath(D.startContainer);D.moveToPosition(y,3);y=null;}else{z=D.splitElement(y);if(!c&&!y.is('ul','ol'))y.appendBogus();}return{previousBlock:y,nextBlock:z,wasStartOfBlock:B,wasEndOfBlock:C,elementPath:A};},splitElement:function(t){var w=this;if(!w.collapsed)return null;w.setEndAt(t,2);var u=w.extractContents(),v=t.clone(false);u.appendTo(v);v.insertAfter(t);w.moveToPosition(t,4);return v;},checkBoundaryOfElement:function(t,u){var v=u==1,w=this.clone();w.collapse(v);w[v?'setStartAt':'setEndAt'](t,v?1:2);var x=new d.walker(w);x.evaluator=p;return x[v?'checkBackward':'checkForward']();},checkStartOfBlock:function(){var z=this;var t=z.startContainer,u=z.startOffset;if(u&&t.type==3){var v=e.ltrim(t.substring(0,u));if(v.length)return false;}z.trim();var w=new d.elementPath(z.startContainer),x=z.clone();x.collapse(true);x.setStartAt(w.block||w.blockLimit,1);var y=new d.walker(x);y.evaluator=o(true);return y.checkBackward();},checkEndOfBlock:function(){var z=this;var t=z.endContainer,u=z.endOffset;if(t.type==3){var v=e.rtrim(t.substring(u));if(v.length)return false;}z.trim();var w=new d.elementPath(z.endContainer),x=z.clone();x.collapse(false);x.setEndAt(w.block||w.blockLimit,2);var y=new d.walker(x);y.evaluator=o(false);return y.checkForward();},checkReadOnly:(function(){function t(u,v){while(u){if(u.type==1)if(u.getAttribute('contentEditable')=='false'&&!u.data('cke-editable'))return 0;else if(u.is('body')||u.getAttribute('contentEditable')=='true'&&(u.contains(v)||u.equals(v)))break;u=u.getParent();}return 1;};return function(){var u=this.startContainer,v=this.endContainer;return!(t(u,v)&&t(v,u));};})(),moveToElementEditablePosition:function(t,u){var v;if(f.$empty[t.getName()])return false;while(t&&t.type==1){v=t.isEditable();if(v)this.moveToPosition(t,u?2:1);else if(f.$inline[t.getName()]){this.moveToPosition(t,u?4:3);return true;}if(f.$empty[t.getName()])t=t[u?'getPrevious':'getNext'](s);else t=t[u?'getLast':'getFirst'](s);if(t&&t.type==3){this.moveToPosition(t,u?4:3);return true;}}return v;},moveToElementEditStart:function(t){return this.moveToElementEditablePosition(t);},moveToElementEditEnd:function(t){return this.moveToElementEditablePosition(t,true);},getEnclosedNode:function(){var t=this.clone();t.optimize();if(t.startContainer.type!=1||t.endContainer.type!=1)return null;var u=new d.walker(t),v=d.walker.bookmark(true),w=d.walker.whitespaces(true),x=function(z){return w(z)&&v(z);};t.evaluator=x;var y=u.next(); +u.reset();return y&&y.equals(u.previous())?y:null;},getTouchedStartNode:function(){var t=this.startContainer;if(this.collapsed||t.type!=1)return t;return t.getChild(this.startOffset)||t;},getTouchedEndNode:function(){var t=this.endContainer;if(this.collapsed||t.type!=1)return t;return t.getChild(this.endOffset-1)||t;}};})();a.POSITION_AFTER_START=1;a.POSITION_BEFORE_END=2;a.POSITION_BEFORE_START=3;a.POSITION_AFTER_END=4;a.ENLARGE_ELEMENT=1;a.ENLARGE_BLOCK_CONTENTS=2;a.ENLARGE_LIST_ITEM_CONTENTS=3;a.START=1;a.END=2;a.STARTEND=3;a.SHRINK_ELEMENT=1;a.SHRINK_TEXT=2;(function(){d.rangeList=function(n){if(n instanceof d.rangeList)return n;if(!n)n=[];else if(n instanceof d.range)n=[n];return e.extend(n,l);};var l={createIterator:function(){var n=this,o=d.walker.bookmark(),p=function(s){return!(s.is&&s.is('tr'));},q=[],r;return{getNextRange:function(s){r=r==undefined?0:r+1;var t=n[r];if(t&&n.length>1){if(!r)for(var u=n.length-1;u>=0;u--)q.unshift(n[u].createBookmark(true));if(s){var v=0;while(n[r+v+1]){var w=t.document,x=0,y=w.getById(q[v].endNode),z=w.getById(q[v+1].startNode),A;while(1){A=y.getNextSourceNode(false);if(!z.equals(A)){if(o(A)||A.type==1&&A.isBlockBoundary()){y=A;continue;}}else x=1;break;}if(!x)break;v++;}}t.moveToBookmark(q.shift());while(v--){A=n[++r];A.moveToBookmark(q.shift());t.setEnd(A.endContainer,A.endOffset);}}return t;}};},createBookmarks:function(n){var s=this;var o=[],p;for(var q=0;q',a.document);l.appendTo(a.document.getHead()); +try{b.hc=l.getComputedStyle('border-top-color')==l.getComputedStyle('border-right-color');}catch(m){b.hc=false;}if(b.hc)b.cssClass+=' cke_hc';l.remove();})();j.load(i.corePlugins.split(','),function(){a.status='loaded';a.fire('loaded');var l=a._.pending;if(l){delete a._.pending;for(var m=0;m0){z=A.shift();while(!z.getParent().equals(D))z=z.getParent();if(!z.equals(H))E.push(z);H=z;}while(E.length>0){z=E.shift();if(z.getName()=='blockquote'){var I=new d.documentFragment(q.document);while(z.getFirst()){I.append(z.getFirst().remove());A.push(I.getLast());}I.replace(z);}else A.push(z);}var J=q.document.createElement('blockquote');J.insertBefore(A[0]);while(A.length>0){z=A.shift();J.append(z);}}else if(r==1){var K=[],L={};while(z=y.getNextParagraph()){var M=null,N=null;while(z.getParent()){if(z.getParent().getName()=='blockquote'){M=z.getParent();N=z;break;}z=z.getParent();}if(M&&N&&!N.getCustomData('blockquote_moveout')){K.push(N);h.setMarker(L,N,'blockquote_moveout',true);}}h.clearAllMarkers(L);var O=[],P=[];L={};while(K.length>0){var Q=K.shift();J=Q.getParent();if(!Q.getPrevious())Q.remove().insertBefore(J);else if(!Q.getNext())Q.remove().insertAfter(J);else{Q.breakParent(Q.getParent());P.push(Q.getNext());}if(!J.getCustomData('blockquote_processed')){P.push(J);h.setMarker(L,J,'blockquote_processed',true);}O.push(Q);}h.clearAllMarkers(L);for(F=P.length-1;F>=0;F--){J=P[F];if(o(J))J.remove();}if(q.config.enterMode==2){var R=true;while(O.length){Q=O.shift();if(Q.getName()=='div'){I=new d.documentFragment(q.document);var S=R&&Q.getPrevious()&&!(Q.getPrevious().type==1&&Q.getPrevious().isBlockBoundary());if(S)I.append(q.document.createElement('br'));var T=Q.getNext()&&!(Q.getNext().type==1&&Q.getNext().isBlockBoundary());while(Q.getFirst())Q.getFirst().remove().appendTo(I);if(T)I.append(q.document.createElement('br'));I.replace(Q);R=false;}}}}s.selectBookmarks(u);q.focus();}};j.add('blockquote',{init:function(q){q.addCommand('blockquote',p);q.ui.addButton('Blockquote',{label:q.lang.blockquote,command:'blockquote'});q.on('selectionChange',n);},requires:['domiterator']});})();j.add('button',{beforeInit:function(m){m.ui.addHandler(1,k.button.handler);}});a.UI_BUTTON=1;k.button=function(m){e.extend(this,m,{title:m.label,className:m.className||m.command&&'cke_button_'+m.command||'',click:m.click||(function(n){n.execCommand(m.command);})});this._={};};k.button.handler={create:function(m){return new k.button(m);}};k.button._={instances:[],keydown:function(m,n){var o=k.button._.instances[m];if(o.onkey){n=new d.event(n);return o.onkey(o,n.getKeystroke())!==false;}},focus:function(m,n){var o=k.button._.instances[m],p;if(o.onfocus)p=o.onfocus(o,new d.event(n))!==false;if(b.gecko&&b.version<10900)n.preventBubble();return p;}};(function(){var m=e.addFunction(k.button._.keydown,k.button._),n=e.addFunction(k.button._.focus,k.button._); +k.button.prototype={canGroup:true,render:function(o,p){var q=b,r=this._.id=e.getNextId(),s='',t=this.command,u,v;this._.editor=o;var w={id:r,button:this,editor:o,focus:function(){var z=a.document.getById(r);z.focus();},execute:function(){this.button.click(o);}};w.clickFn=u=e.addFunction(w.execute,w);w.index=v=k.button._.instances.push(w)-1;if(this.modes){var x={};o.on('beforeModeUnload',function(){x[o.mode]=this._.state;},this);o.on('mode',function(){var z=o.mode;this.setState(this.modes[z]?x[z]!=undefined?x[z]:2:0);},this);}else if(t){t=o.getCommand(t);if(t){t.on('state',function(){this.setState(t.state);},this);s+='cke_'+(t.state==1?'on':t.state==0?'disabled':'off');}}if(!t)s+='cke_off';if(this.className)s+=' '+this.className;p.push('','=10900&&!q.hc?'':'" href="javascript:void(\''+(this.title||'').replace("'",'')+"')\"",' title="',this.title,'" tabindex="-1" hidefocus="true" role="button" aria-labelledby="'+r+'_label"'+(this.hasArrow?' aria-haspopup="true"':''));if(q.opera||q.gecko&&q.mac)p.push(' onkeypress="return false;"');if(q.gecko)p.push(' onblur="this.style.cssText = this.style.cssText;"');p.push(' onkeydown="return CKEDITOR.tools.callFunction(',m,', ',v,', event);" onfocus="return CKEDITOR.tools.callFunction(',n,', ',v,', event);" onclick="CKEDITOR.tools.callFunction(',u,', this); return false;"> ',this.label,'');if(this.hasArrow)p.push(''+(b.hc?'▼':' ')+'');p.push('','');if(this.onRender)this.onRender();return w;},setState:function(o){if(this._.state==o)return false;this._.state=o;var p=a.document.getById(this._.id);if(p){p.setState(o);o==0?p.setAttribute('aria-disabled',true):p.removeAttribute('aria-disabled');o==1?p.setAttribute('aria-pressed',true):p.removeAttribute('aria-pressed');return true;}else return false;}};})();k.prototype.addButton=function(m,n){this.add(m,1,n);};a.on('reset',function(){k.button._.instances=[];});(function(){var m=function(y,z){var A=y.document,B=A.getBody(),C=0,D=function(){C=1;};B.on(z,D);(b.version>7?A.$:A.$.selection.createRange()).execCommand(z);B.removeListener(z,D);return C;},n=c?function(y,z){return m(y,z); +}:function(y,z){try{return y.document.$.execCommand(z,false,null);}catch(A){return false;}},o=function(y){var z=this;z.type=y;z.canUndo=z.type=='cut';z.startDisabled=true;};o.prototype={exec:function(y,z){this.type=='cut'&&t(y);var A=n(y,this.type);if(!A)alert(y.lang.clipboard[this.type+'Error']);return A;}};var p={canUndo:false,exec:c?function(y){y.focus();if(!y.document.getBody().fire('beforepaste')&&!m(y,'paste')){y.fire('pasteDialog');return false;}}:function(y){try{if(!y.document.getBody().fire('beforepaste')&&!y.document.$.execCommand('Paste',false,null))throw 0;}catch(z){setTimeout(function(){y.fire('pasteDialog');},0);return false;}}},q=function(y){if(this.mode!='wysiwyg')return;switch(y.data.keyCode){case 1000+86:case 2000+45:var z=this.document.getBody();if(!c&&z.fire('beforepaste'))y.cancel();else if(b.opera||b.gecko&&b.version<10900)z.fire('paste');return;case 1000+88:case 2000+46:var A=this;this.fire('saveSnapshot');setTimeout(function(){A.fire('saveSnapshot');},0);}};function r(y){y.cancel();};function s(y,z,A){var B=this.document;if(B.getById('cke_pastebin'))return;if(z=='text'&&y.data&&y.data.$.clipboardData){var C=y.data.$.clipboardData.getData('text/plain');if(C){y.data.preventDefault();A(C);return;}}var D=this.getSelection(),E=new d.range(B),F=new h(z=='text'?'textarea':b.webkit?'body':'div',B);F.setAttribute('id','cke_pastebin');b.webkit&&F.append(B.createText('\xa0'));B.getBody().append(F);F.setStyles({position:'absolute',top:D.getStartElement().getDocumentPosition().y+'px',width:'1px',height:'1px',overflow:'hidden'});F.setStyle(this.config.contentsLangDirection=='ltr'?'left':'right','-1000px');var G=D.createBookmarks();this.on('selectionChange',r,null,null,0);if(z=='text'){if(c){var H=B.getBody().$.createTextRange();H.moveToElementText(F.$);H.execCommand('Paste');y.data.preventDefault();}else F.$.focus();}else{E.setStartAt(F,1);E.setEndAt(F,2);E.select(true);}var I=this;window.setTimeout(function(){z=='text'&&b.gecko&&I.focusGrabber.focus();F.remove();I.removeListener('selectionChange',r);var J;F=b.webkit&&(J=F.getFirst())&&J.is&&J.hasClass('Apple-style-span')?J:F;D.selectBookmarks(G);A(F['get'+(z=='text'?'Value':'Html')]());},0);};function t(y){if(!c||b.quirks)return;var z=y.getSelection(),A;if(z.getType()==3&&(A=z.getSelectedElement())){var B=z.getRanges()[0],C=y.document.createText('');C.insertBefore(A);B.setStartBefore(C);B.setEndAfter(A);z.selectRanges([B]);setTimeout(function(){if(A.getParent()){C.remove();z.selectElement(A);}},0); +}};var u;function v(y,z){c&&(u=1);var A=z.document.$.queryCommandEnabled(y)?2:0;u=0;return A;};var w;function x(){var z=this;if(z.mode!='wysiwyg')return;z.getCommand('cut').setState(w?0:v('Cut',z));z.getCommand('copy').setState(v('Copy',z));var y=w?0:b.webkit?2:v('Paste',z);z.fire('pasteState',y);};j.add('clipboard',{requires:['dialog','htmldataprocessor'],init:function(y){y.on('paste',function(B){var C=B.data;if(C.html)y.insertHtml(C.html);else if(C.text)y.insertText(C.text);setTimeout(function(){y.fire('afterPaste');},0);},null,null,1000);y.on('pasteDialog',function(B){setTimeout(function(){y.openDialog('paste');},0);});y.on('pasteState',function(B){y.getCommand('paste').setState(B.data);});function z(B,C,D,E){var F=y.lang[C];y.addCommand(C,D);y.ui.addButton(B,{label:F,command:C});if(y.addMenuItems)y.addMenuItem(C,{label:F,command:C,group:'clipboard',order:E});};z('Cut','cut',new o('cut'),1);z('Copy','copy',new o('copy'),4);z('Paste','paste',p,8);a.dialog.add('paste',a.getUrl(this.path+'dialogs/paste.js'));y.on('key',q,y);var A=y.config.forcePasteAsPlainText?'text':'html';y.on('contentDom',function(){var B=y.document.getBody();B.on(A=='text'&&c||b.webkit?'paste':'beforepaste',function(C){if(u)return;s.call(y,C,A,function(D){if(!e.trim(D.toLowerCase().replace(/]+data-cke-bookmark[^<]*?<\/span>/g,'')))return;var E={};E[A]=D;y.fire('paste',E);});});B.on('beforecut',function(){!u&&t(y);});B.on('mouseup',function(){setTimeout(function(){x.call(y);},0);},y);B.on('keyup',x,y);});y.on('selectionChange',function(B){w=B.data.selection.getRanges()[0].checkReadOnly();x.call(y);});if(y.contextMenu)y.contextMenu.addListener(function(B,C){var D=C.getRanges()[0].checkReadOnly();return{cut:!D&&v('Cut',y),copy:v('Copy',y),paste:!D&&(b.webkit?2:v('Paste',y))};});}});})();j.add('colorbutton',{requires:['panelbutton','floatpanel','styles'],init:function(m){var n=m.config,o=m.lang.colorButton,p;if(!b.hc){q('TextColor','fore',o.textColorTitle);q('BGColor','back',o.bgColorTitle);}function q(t,u,v){var w=e.getNextId()+'_colorBox';m.ui.add(t,4,{label:v,title:v,className:'cke_button_'+t.toLowerCase(),modes:{wysiwyg:1},panel:{css:m.skin.editor.css,attributes:{role:'listbox','aria-label':o.panelTitle}},onBlock:function(x,y){y.autoSize=true;y.element.addClass('cke_colorblock');y.element.setHtml(r(x,u,w));y.element.getDocument().getBody().setStyle('overflow','hidden');k.fire('ready',this);var z=y.keys,A=m.lang.dir=='rtl';z[A?37:39]='next';z[40]='next';z[9]='next';z[A?39:37]='prev'; +z[38]='prev';z[2000+9]='prev';z[32]='click';},onOpen:function(){var x=m.getSelection(),y=x&&x.getStartElement(),z=new d.elementPath(y),A;y=z.block||z.blockLimit||m.document.getBody();do A=y&&y.getComputedStyle(u=='back'?'background-color':'color')||'transparent';while(u=='back'&&A=='transparent'&&y&&(y=y.getParent()));if(!A||A=='transparent')A='#ffffff';this._.panel._.iframe.getFrameDocument().getById(w).setStyle('background-color',A);}});};function r(t,u,v){var w=[],x=n.colorButton_colors.split(','),y=x.length+(n.colorButton_enableMore?2:1),z=e.addFunction(function(F,G){if(F=='?'){var H=arguments.callee;function I(K){this.removeListener('ok',I);this.removeListener('cancel',I);K.name=='ok'&&H(this.getContentElement('picker','selectedColor').getValue(),G);};m.openDialog('colordialog',function(){this.on('ok',I);this.on('cancel',I);});return;}m.focus();t.hide();m.fire('saveSnapshot');new a.style(n['colorButton_'+G+'Style'],{color:'inherit'}).remove(m.document);if(F){var J=n['colorButton_'+G+'Style'];J.childRule=G=='back'?function(K){return s(K);}:function(K){return K.getName()!='a'||s(K);};new a.style(J,{color:F}).apply(m.document);}m.fire('saveSnapshot');});w.push('
',o.auto,'
');for(var A=0;A');var B=x[A].split('/'),C=B[0],D=B[1]||C;if(!B[1])C='#'+C.replace(/^(.)(.)(.)$/,'$1$1$2$2$3$3');var E=m.lang.colors[D]||D;w.push('');}if(n.colorButton_enableMore===undefined||n.colorButton_enableMore)w.push(''); +w.push('
',o.more,'
');return w.join('');};function s(t){return t.getAttribute('contentEditable')=='false'||t.getAttribute('data-nostyle');};}});i.colorButton_colors='000,800000,8B4513,2F4F4F,008080,000080,4B0082,696969,B22222,A52A2A,DAA520,006400,40E0D0,0000CD,800080,808080,F00,FF8C00,FFD700,008000,0FF,00F,EE82EE,A9A9A9,FFA07A,FFA500,FFFF00,00FF00,AFEEEE,ADD8E6,DDA0DD,D3D3D3,FFF0F5,FAEBD7,FFFFE0,F0FFF0,F0FFFF,F0F8FF,E6E6FA,FFF';i.colorButton_foreStyle={element:'span',styles:{color:'#(color)'},overrides:[{element:'font',attributes:{color:null}}]};i.colorButton_backStyle={element:'span',styles:{'background-color':'#(color)'}};(function(){j.colordialog={init:function(m){m.addCommand('colordialog',new a.dialogCommand('colordialog'));a.dialog.add('colordialog',this.path+'dialogs/colordialog.js');}};j.add('colordialog',j.colordialog);})();j.add('contextmenu',{requires:['menu'],onLoad:function(){j.contextMenu=e.createClass({base:a.menu,$:function(m){this.base.call(this,m,{panel:{className:m.skinClass+' cke_contextmenu',attributes:{'aria-label':m.lang.contextmenu.options}}});},proto:{addTarget:function(m,n){if(b.opera&&!('oncontextmenu' in document.body)){var o;m.on('mousedown',function(s){s=s.data;if(s.$.button!=2){if(s.getKeystroke()==1000+1)m.fire('contextmenu',s);return;}if(n&&(b.mac?s.$.metaKey:s.$.ctrlKey))return;var t=s.getTarget();if(!o){var u=t.getDocument();o=u.createElement('input');o.$.type='button';u.getBody().append(o);}o.setAttribute('style','position:absolute;top:'+(s.$.clientY-2)+'px;left:'+(s.$.clientX-2)+'px;width:5px;height:5px;opacity:0.01');});m.on('mouseup',function(s){if(o){o.remove();o=undefined;m.fire('contextmenu',s.data);}});}m.on('contextmenu',function(s){var t=s.data;if(n&&(b.webkit?p:b.mac?t.$.metaKey:t.$.ctrlKey))return;t.preventDefault();var u=t.getTarget().getDocument().getDocumentElement(),v=t.$.clientX,w=t.$.clientY;e.setTimeout(function(){this.open(u,null,v,w);},0,this);},this);if(b.opera)m.on('keypress',function(s){var t=s.data;if(t.$.keyCode===0)t.preventDefault();});if(b.webkit){var p,q=function(s){p=b.mac?s.data.$.metaKey:s.data.$.ctrlKey;},r=function(){p=0;};m.on('keydown',q);m.on('keyup',r);m.on('contextmenu',r);}},open:function(m,n,o,p){this.editor.focus();m=m||a.document.getDocumentElement();this.show(m,n,o,p);}}});},beforeInit:function(m){m.contextMenu=new j.contextMenu(m);m.addCommand('contextMenu',{exec:function(){m.contextMenu.open(m.document.getBody());}});}});(function(){function m(o){var p=this.att,q=o&&o.hasAttribute(p)&&o.getAttribute(p)||''; +if(q!==undefined)this.setValue(q);};function n(){var o;for(var p=0;p ';j.add('elementspath',{requires:['selection'],init:function(o){var p='cke_path_'+o.name,q,r=function(){if(!q)q=a.document.getById(p);return q;},s='cke_elementspath_'+e.getNextNumber()+'_';o._.elementsPath={idBase:s,filters:[]};o.on('themeSpace',function(w){if(w.data.space=='bottom')w.data.html+=''+o.lang.elementsPath.eleLabel+''+'
'+n+'
';});function t(w){o.focus();var x=o._.elementsPath.list[w];if(x.is('body')){var y=new d.range(o.document);y.selectNodeContents(x);y.select();}else o.getSelection().selectElement(x);};var u=e.addFunction(t),v=e.addFunction(function(w,x){var y=o._.elementsPath.idBase,z;x=new d.event(x);var A=o.lang.dir=='rtl';switch(x.getKeystroke()){case A?39:37:case 9:z=a.document.getById(y+(w+1));if(!z)z=a.document.getById(y+'0');z.focus();return false;case A?37:39:case 2000+9:z=a.document.getById(y+(w-1));if(!z)z=a.document.getById(y+(o._.elementsPath.list.length-1));z.focus();return false;case 27:o.focus();return false;case 13:case 32:t(w);return false;}return true;});o.on('selectionChange',function(w){var x=b,y=w.data.selection,z=y.getStartElement(),A=[],B=w.editor,C=B._.elementsPath.list=[],D=B._.elementsPath.filters;while(z){var E=0;for(var F=0;F',H,''+J+'',''); +}if(H=='body')break;z=z.getParent();}var K=r();K.setHtml(A.join('')+n);B.fire('elementsPathUpdate',{space:K});});o.on('contentDomUnload',function(){q&&q.setHtml(n);});o.addCommand('elementsPathFocus',m.toolbarFocus);}});})();(function(){j.add('enterkey',{requires:['keystrokes','indent'],init:function(t){var u=t.specialKeys;u[13]=r;u[2000+13]=q;}});j.enterkey={enterBlock:function(t,u,v,w){v=v||s(t);if(!v)return;var x=v.document;if(v.checkStartOfBlock()&&v.checkEndOfBlock()){var y=new d.elementPath(v.startContainer),z=y.block;if(z&&(z.is('li')||z.getParent().is('li'))){t.execCommand('outdent');return;}}var A=u==3?'div':'p',B=v.splitBlock(A);if(!B)return;var C=B.previousBlock,D=B.nextBlock,E=B.wasStartOfBlock,F=B.wasEndOfBlock,G;if(D){G=D.getParent();if(G.is('li')){D.breakParent(G);D.move(D.getNext(),1);}}else if(C&&(G=C.getParent())&&G.is('li')){C.breakParent(G);G=C.getNext();v.moveToElementEditStart(G);C.move(C.getPrevious());}if(!E&&!F){if(D.is('li')&&(G=D.getFirst(d.walker.invisible(true)))&&G.is&&G.is('ul','ol'))(c?x.createText('\xa0'):x.createElement('br')).insertBefore(G);if(D)v.moveToElementEditStart(D);}else{var H,I;if(C){if(C.is('li')||!p.test(C.getName())){H=C.clone();H.is('li')&&H.removeAttribute('value');}}else if(D)H=D.clone();if(!H){if(G&&G.is('li'))H=G;else{H=x.createElement(A);if(C&&(I=C.getDirection()))H.setAttribute('dir',I);}}else if(w&&!H.is('li'))H.renameNode(A);var J=B.elementPath;if(J)for(var K=0,L=J.elements.length;K0;v--)u[v].deleteContents();return u[0];};})();(function(){var m='nbsp,gt,lt',n='quot,iexcl,cent,pound,curren,yen,brvbar,sect,uml,copy,ordf,laquo,not,shy,reg,macr,deg,plusmn,sup2,sup3,acute,micro,para,middot,cedil,sup1,ordm,raquo,frac14,frac12,frac34,iquest,times,divide,fnof,bull,hellip,prime,Prime,oline,frasl,weierp,image,real,trade,alefsym,larr,uarr,rarr,darr,harr,crarr,lArr,uArr,rArr,dArr,hArr,forall,part,exist,empty,nabla,isin,notin,ni,prod,sum,minus,lowast,radic,prop,infin,ang,and,or,cap,cup,int,there4,sim,cong,asymp,ne,equiv,le,ge,sub,sup,nsub,sube,supe,oplus,otimes,perp,sdot,lceil,rceil,lfloor,rfloor,lang,rang,loz,spades,clubs,hearts,diams,circ,tilde,ensp,emsp,thinsp,zwnj,zwj,lrm,rlm,ndash,mdash,lsquo,rsquo,sbquo,ldquo,rdquo,bdquo,dagger,Dagger,permil,lsaquo,rsaquo,euro',o='Agrave,Aacute,Acirc,Atilde,Auml,Aring,AElig,Ccedil,Egrave,Eacute,Ecirc,Euml,Igrave,Iacute,Icirc,Iuml,ETH,Ntilde,Ograve,Oacute,Ocirc,Otilde,Ouml,Oslash,Ugrave,Uacute,Ucirc,Uuml,Yacute,THORN,szlig,agrave,aacute,acirc,atilde,auml,aring,aelig,ccedil,egrave,eacute,ecirc,euml,igrave,iacute,icirc,iuml,eth,ntilde,ograve,oacute,ocirc,otilde,ouml,oslash,ugrave,uacute,ucirc,uuml,yacute,thorn,yuml,OElig,oelig,Scaron,scaron,Yuml',p='Alpha,Beta,Gamma,Delta,Epsilon,Zeta,Eta,Theta,Iota,Kappa,Lambda,Mu,Nu,Xi,Omicron,Pi,Rho,Sigma,Tau,Upsilon,Phi,Chi,Psi,Omega,alpha,beta,gamma,delta,epsilon,zeta,eta,theta,iota,kappa,lambda,mu,nu,xi,omicron,pi,rho,sigmaf,sigma,tau,upsilon,phi,chi,psi,omega,thetasym,upsih,piv'; function q(r,s){var t={},u=[],v={nbsp:'\xa0',shy:'­',gt:'>',lt:'<'};r=r.replace(/\b(nbsp|shy|gt|lt|amp)(?:,|$)/g,function(A,B){var C=s?'&'+B+';':v[B],D=s?v[B]:'&'+B+';';t[C]=D;u.push(C);return '';});if(!s&&r){r=r.split(',');var w=document.createElement('div'),x;w.innerHTML='&'+r.join(';&')+';';x=w.innerHTML;w=null;for(var y=0;y'+u+'',u);}},onClick:function(t){m.focus();m.fire('saveSnapshot');var u=q[t],v=new d.elementPath(m.getSelection().getStartElement());u[u.checkActive(v)?'remove':'apply'](m.document);setTimeout(function(){m.fire('saveSnapshot');},0);},onRender:function(){m.on('selectionChange',function(t){var u=this.getValue(),v=t.data.path;for(var w in q){if(q[w].checkActive(v)){if(w!=u)this.setValue(w,m.lang.format['tag_'+w]);return;}}this.setValue('');},this);}});}});i.format_tags='p;h1;h2;h3;h4;h5;h6;pre;address;div';i.format_p={element:'p'};i.format_div={element:'div'};i.format_pre={element:'pre'};i.format_address={element:'address'};i.format_h1={element:'h1'};i.format_h2={element:'h2'};i.format_h3={element:'h3'};i.format_h4={element:'h4'};i.format_h5={element:'h5'};i.format_h6={element:'h6'};j.add('forms',{init:function(m){var n=m.lang;m.addCss('form{border: 1px dotted #FF0000;padding: 2px;}\n');m.addCss('img.cke_hidden{background-image: url('+a.getUrl(this.path+'images/hiddenfield.gif')+');'+'background-position: center center;'+'background-repeat: no-repeat;'+'border: 1px solid #a9a9a9;'+'width: 16px !important;'+'height: 16px !important;'+'}'); -var o=function(q,r,s){m.addCommand(r,new a.dialogCommand(r));m.ui.addButton(q,{label:n.common[q.charAt(0).toLowerCase()+q.slice(1)],command:r});a.dialog.add(r,s);},p=this.path+'dialogs/';o('Form','form',p+'form.js');o('Checkbox','checkbox',p+'checkbox.js');o('Radio','radio',p+'radio.js');o('TextField','textfield',p+'textfield.js');o('Textarea','textarea',p+'textarea.js');o('Select','select',p+'select.js');o('Button','button',p+'button.js');o('ImageButton','imagebutton',j.getPath('image')+'dialogs/image.js');o('HiddenField','hiddenfield',p+'hiddenfield.js');if(m.addMenuItems)m.addMenuItems({form:{label:n.form.menu,command:'form',group:'form'},checkbox:{label:n.checkboxAndRadio.checkboxTitle,command:'checkbox',group:'checkbox'},radio:{label:n.checkboxAndRadio.radioTitle,command:'radio',group:'radio'},textfield:{label:n.textfield.title,command:'textfield',group:'textfield'},hiddenfield:{label:n.hidden.title,command:'hiddenfield',group:'hiddenfield'},imagebutton:{label:n.image.titleButton,command:'imagebutton',group:'imagebutton'},button:{label:n.button.title,command:'button',group:'button'},select:{label:n.select.title,command:'select',group:'select'},textarea:{label:n.textarea.title,command:'textarea',group:'textarea'}});if(m.contextMenu){m.contextMenu.addListener(function(q){if(q&&q.hasAscendant('form',true)&&!q.isReadOnly())return{form:2};});m.contextMenu.addListener(function(q){if(q&&!q.isReadOnly()){var r=q.getName();if(r=='select')return{select:2};if(r=='textarea')return{textarea:2};if(r=='input')switch(q.getAttribute('type')){case 'button':case 'submit':case 'reset':return{button:2};case 'checkbox':return{checkbox:2};case 'radio':return{radio:2};case 'image':return{imagebutton:2};default:return{textfield:2};}if(r=='img'&&q.data('cke-real-element-type')=='hiddenfield')return{hiddenfield:2};}});}m.on('doubleclick',function(q){var r=q.data.element;if(r.is('form'))q.data.dialog='form';else if(r.is('select'))q.data.dialog='select';else if(r.is('textarea'))q.data.dialog='textarea';else if(r.is('img')&&r.data('cke-real-element-type')=='hiddenfield')q.data.dialog='hiddenfield';else if(r.is('input'))switch(r.getAttribute('type')){case 'button':case 'submit':case 'reset':q.data.dialog='button';break;case 'checkbox':q.data.dialog='checkbox';break;case 'radio':q.data.dialog='radio';break;case 'image':q.data.dialog='imagebutton';break;default:q.data.dialog='textfield';break;}});},afterInit:function(m){var n=m.dataProcessor,o=n&&n.htmlFilter,p=n&&n.dataFilter;if(c)o&&o.addRules({elements:{input:function(q){var r=q.attributes,s=r.type; -if(!s)r.type='text';if(s=='checkbox'||s=='radio')r.value=='on'&&delete r.value;}}});if(p)p.addRules({elements:{input:function(q){if(q.attributes.type=='hidden')return m.createFakeParserElement(q,'cke_hidden','hiddenfield');}}});},requires:['image','fakeobjects']});if(c)h.prototype.hasAttribute=function(m){var p=this;var n=p.$.attributes.getNamedItem(m);if(p.getName()=='input')switch(m){case 'class':return p.$.className.length>0;case 'checked':return!!p.$.checked;case 'value':var o=p.getAttribute('type');return o=='checkbox'||o=='radio'?p.$.value!='on':p.$.value;}return!!(n&&n.specified);};(function(){var m={canUndo:false,exec:function(o){o.insertElement(o.document.createElement('hr'));}},n='horizontalrule';j.add(n,{init:function(o){o.addCommand(n,m);o.ui.addButton('HorizontalRule',{label:o.lang.horizontalrule,command:n});}});})();(function(){var m=/^[\t\r\n ]*(?: |\xa0)$/,n='{cke_protected}';function o(R){var S=R.children.length,T=R.children[S-1];while(T&&T.type==3&&!e.trim(T.value))T=R.children[--S];return T;};function p(R,S){var T=R.children,U=o(R);if(U){if((S||!c)&&U.type==1&&U.name=='br')T.pop();if(U.type==3&&m.test(U.value))T.pop();}};function q(R,S,T){if(!S&&(!T||typeof T=='function'&&T(R)===false))return false;if(S&&c&&(document.documentMode>7||R.name in f.tr||R.name in f.$listItem))return false;var U=o(R);return!U||U&&(U.type==1&&U.name=='br'||R.name=='form'&&U.name=='input');};function r(R,S){return function(T){p(T,!R);if(q(T,!R,S))if(R||c)T.add(new a.htmlParser.text('\xa0'));else T.add(new a.htmlParser.element('br',{}));};};var s=f,t=e.extend({},s.$block,s.$listItem,s.$tableContent);for(var u in t){if(!('br' in s[u]))delete t[u];}delete t.pre;var v={elements:{a:function(R){var S=R.attributes;if(S&&S['data-cke-saved-name'])S['class']=(S['class']?S['class']+' ':'')+'cke_anchor';}},attributeNames:[[/^on/,'data-cke-pa-on']]},w={elements:{}};for(u in t)w.elements[u]=r();var x={elementNames:[[/^cke:/,''],[/^\?xml:namespace$/,'']],attributeNames:[[/^data-cke-(saved|pa)-/,''],[/^data-cke-.*/,''],['hidefocus','']],elements:{$:function(R){var S=R.attributes;if(S){if(S['data-cke-temp'])return false;var T=['name','href','src'],U;for(var V=0;V]*)>/gi,B=/\b(href|src|name)\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|(?:[^ "'>]+))/gi,C=/(?:])[^>]*>[\s\S]*<\/style>)|(?:<(:?link|meta|base)[^>]*>)/gi,D=/([^<]*)<\/cke:encoded>/gi,E=/(<\/?)((?:object|embed|param|html|body|head|title)[^>]*>)/gi,F=/(<\/?)cke:((?:html|body|head|title)[^>]*>)/gi,G=/]*?)\/?>(?!\s*<\/cke:\1)/gi;function H(R){return R.replace(A,function(S,T,U){return '<'+T+U.replace(B,function(V,W){if(U.indexOf('data-cke-saved-'+W)==-1)return ' data-cke-saved-'+V+' '+V;return V;})+'>';});};function I(R){return R.replace(C,function(S){return ''+encodeURIComponent(S)+'';});};function J(R){return R.replace(D,function(S,T){return decodeURIComponent(T);});};function K(R){return R.replace(E,'$1cke:$2');};function L(R){return R.replace(F,'$1$2');};function M(R){return R.replace(G,'');};function N(R){return R.replace(/(]*>)(\r\n|\n)/g,'$1$2$2');};function O(R){return R.replace(//g,function(S){return '';});};function P(R){return R.replace(//g,function(S,T){return decodeURIComponent(T); -});};function Q(R,S){var T=[],U=/<\!--\{cke_temp(comment)?\}(\d*?)-->/g,V=[//gi,//gi].concat(S);R=R.replace(//g,function(X){return '';});for(var W=0;W';});R=R.replace(U,function(X,Y,Z){return '';});return R;};j.add('htmldataprocessor',{requires:['htmlwriter'],init:function(R){var S=R.dataProcessor=new a.htmlDataProcessor(R);S.writer.forceSimpleAmpersand=R.config.forceSimpleAmpersand;S.dataFilter.addRules(v);S.dataFilter.addRules(w);S.htmlFilter.addRules(x);var T={elements:{}};for(u in t)T.elements[u]=r(true,R.config.fillEmptyBlocks);S.htmlFilter.addRules(T);},onLoad:function(){!('fillEmptyBlocks' in i)&&(i.fillEmptyBlocks=1);}});a.htmlDataProcessor=function(R){var S=this;S.editor=R;S.writer=new a.htmlWriter();S.dataFilter=new a.htmlParser.filter();S.htmlFilter=new a.htmlParser.filter();};a.htmlDataProcessor.prototype={toHtml:function(R,S){R=Q(R,this.editor.config.protectedSource);R=H(R);R=I(R);R=K(R);R=M(R);R=N(R);var T=new h('div');T.setHtml('a'+R);R=T.getHtml().substr(1);R=L(R);R=J(R);R=P(R);var U=a.htmlParser.fragment.fromHtml(R,S),V=new a.htmlParser.basicWriter();U.writeHtml(V,this.dataFilter);R=V.getHtml(true);R=O(R);return R;},toDataFormat:function(R,S){var T=this.writer,U=a.htmlParser.fragment.fromHtml(R,S);T.reset();U.writeHtml(T,this.htmlFilter);return T.getHtml(true);}};})();(function(){function m(n,o){var p=n.createFakeParserElement(o,'cke_iframe','iframe',true),q=p.attributes.style||'',r=o.attributes.width,s=o.attributes.height;if(typeof r!='undefined')q+='width:'+e.cssLength(r)+';';if(typeof s!='undefined')q+='height:'+e.cssLength(s)+';';p.attributes.style=q;return p;};j.add('iframe',{requires:['dialog','fakeobjects'],init:function(n){var o='iframe',p=n.lang.iframe;a.dialog.add(o,this.path+'dialogs/iframe.js');n.addCommand(o,new a.dialogCommand(o));n.addCss('img.cke_iframe{background-image: url('+a.getUrl(this.path+'images/placeholder.png')+');'+'background-position: center center;'+'background-repeat: no-repeat;'+'border: 1px solid #a9a9a9;'+'width: 80px;'+'height: 80px;'+'}');n.ui.addButton('Iframe',{label:p.toolbar,command:o});n.on('doubleclick',function(q){var r=q.data.element;if(r.is('img')&&r.data('cke-real-element-type')=='iframe')q.data.dialog='iframe'; -});if(n.addMenuItems)n.addMenuItems({iframe:{label:p.title,command:'iframe',group:'image'}});if(n.contextMenu)n.contextMenu.addListener(function(q,r){if(q&&q.is('img')&&q.data('cke-real-element-type')=='iframe')return{iframe:2};});},afterInit:function(n){var o=n.dataProcessor,p=o&&o.dataFilter;if(p)p.addRules({elements:{iframe:function(q){return m(n,q);}}});}});})();j.add('image',{init:function(m){var n='image';a.dialog.add(n,this.path+'dialogs/image.js');m.addCommand(n,new a.dialogCommand(n));m.ui.addButton('Image',{label:m.lang.common.image,command:n});m.on('doubleclick',function(o){var p=o.data.element;if(p.is('img')&&!p.data('cke-realelement'))o.data.dialog='image';});if(m.addMenuItems)m.addMenuItems({image:{label:m.lang.image.menu,command:'image',group:'image'}});if(m.contextMenu)m.contextMenu.addListener(function(o,p){if(!o||!o.is('img')||o.data('cke-realelement')||o.isReadOnly())return null;return{image:2};});}});i.image_removeLinkByEmptyURL=true;(function(){var m={ol:1,ul:1},n=d.walker.whitespaces(true),o=d.walker.bookmark(false,true);function p(t){var C=this;var u=t.editor,v=t.data.path,w=v&&v.contains(m);if(w)return C.setState(2);if(!C.useIndentClasses&&C.name=='indent')return C.setState(2);var x=t.data.path,y=x.block||x.blockLimit;if(!y)return C.setState(0);if(C.useIndentClasses){var z=y.$.className.match(C.classNameRegex),A=0;if(z){z=z[1];A=C.indentClassMap[z];}if(C.name=='outdent'&&!A||C.name=='indent'&&A==u.config.indentClasses.length)return C.setState(0);return C.setState(2);}else{var B=parseInt(y.getStyle(r(y)),10);if(isNaN(B))B=0;if(B<=0)return C.setState(0);return C.setState(2);}};function q(t,u){var w=this;w.name=u;w.useIndentClasses=t.config.indentClasses&&t.config.indentClasses.length>0;if(w.useIndentClasses){w.classNameRegex=new RegExp('(?:^|\\s+)('+t.config.indentClasses.join('|')+')(?=$|\\s)');w.indentClassMap={};for(var v=0;vY;T++)X[T].indent+=U;var aa=j.list.arrayToList(X,v,null,t.config.enterMode,M.getDirection());if(u.name=='outdent'){var ab;if((ab=M.getParent())&&ab.is('li')){var ac=aa.listNode.getChildren(),ad=[],ae=ac.count(),af;for(T=ae-1;T>=0;T--){if((af=ac.getItem(T))&&af.is&&af.is('li'))ad.push(af);}}}if(aa)aa.listNode.replace(M);if(ad&&ad.length)for(T=0;T0)M.addClass(t.config.indentClasses[P-1]);}else{var Q=r(M,N),R=parseInt(M.getStyle(Q),10);if(isNaN(R))R=0;var S=t.config.indentOffset||40;R+=(u.name=='indent'?1:-1)*S;if(R<0)return false;R=Math.max(R,0);R=Math.ceil(R/S)*S;M.setStyle(Q,R?R+(t.config.indentUnit||'px'):'');if(M.getAttribute('style')==='')M.removeAttribute('style');}h.setMarker(v,M,'indent_processed',1);return true;};var z=t.getSelection(),A=z.createBookmarks(1),B=z&&z.getRanges(1),C,D=B.createIterator();while(C=D.getNextRange()){var E=C.getCommonAncestor(),F=E;while(F&&!(F.type==1&&m[F.getName()]))F=F.getParent();if(!F){var G=C.getEnclosedNode();if(G&&G.type==1&&G.getName() in m){C.setStartAt(G,1);C.setEndAt(G,2);F=G;}}if(F&&C.startContainer.type==1&&C.startContainer.getName() in m){var H=new d.walker(C);H.evaluator=s;C.startContainer=H.next();}if(F&&C.endContainer.type==1&&C.endContainer.getName() in m){H=new d.walker(C);H.evaluator=s;C.endContainer=H.previous();}if(F){var I=F.getFirst(s),J=!!I.getNext(s),K=C.startContainer,L=I.equals(K)||I.contains(K); -if(!(L&&(u.name=='indent'||u.useIndentClasses||parseInt(F.getStyle(r(F)),10))&&y(F,!J&&I.getDirection())))w(F);}else x();}h.clearAllMarkers(v);t.forceNextSelectionCheck();z.selectBookmarks(A);}};j.add('indent',{init:function(t){var u=t.addCommand('indent',new q(t,'indent')),v=t.addCommand('outdent',new q(t,'outdent'));t.ui.addButton('Indent',{label:t.lang.indent,command:'indent'});t.ui.addButton('Outdent',{label:t.lang.outdent,command:'outdent'});t.on('selectionChange',e.bind(p,u));t.on('selectionChange',e.bind(p,v));if(b.ie6Compat||b.ie7Compat)t.addCss('ul,ol{\tmargin-left: 0px;\tpadding-left: 40px;}');t.on('dirChanged',function(w){var x=new d.range(t.document);x.setStartBefore(w.data.node);x.setEndAfter(w.data.node);var y=new d.walker(x),z;while(z=y.next()){if(z.type==1){if(!z.equals(w.data.node)&&z.getDirection()){x.setStartAfter(z);y=new d.walker(x);continue;}var A=t.config.indentClasses;if(A){var B=w.data.dir=='ltr'?['_rtl','']:['','_rtl'];for(var C=0;C=0;A--){x=v[A].createIterator();x.enlargeBr=t!=2;while(y=x.getNextParagraph(t==1?'p':'div')){y.removeAttribute('align');y.removeStyle('text-align');var B=w&&(y.$.className=e.ltrim(y.$.className.replace(D.cssClassRegex,''))),C=D.state==2&&(!z||n(y,true)!=D.value);if(w){if(C)y.addClass(w);else if(!B)y.removeAttribute('class');}else if(C)y.setStyle('text-align',D.value);}}r.focus();r.forceNextSelectionCheck();s.selectBookmarks(u);}};j.add('justify',{init:function(r){var s=new p(r,'justifyleft','left'),t=new p(r,'justifycenter','center'),u=new p(r,'justifyright','right'),v=new p(r,'justifyblock','justify');r.addCommand('justifyleft',s);r.addCommand('justifycenter',t);r.addCommand('justifyright',u);r.addCommand('justifyblock',v);r.ui.addButton('JustifyLeft',{label:r.lang.justify.left,command:'justifyleft'});r.ui.addButton('JustifyCenter',{label:r.lang.justify.center,command:'justifycenter'});r.ui.addButton('JustifyRight',{label:r.lang.justify.right,command:'justifyright'});r.ui.addButton('JustifyBlock',{label:r.lang.justify.block,command:'justifyblock'});r.on('selectionChange',e.bind(o,s));r.on('selectionChange',e.bind(o,u));r.on('selectionChange',e.bind(o,t));r.on('selectionChange',e.bind(o,v));r.on('dirChanged',q);},requires:['domiterator']});})();j.add('keystrokes',{beforeInit:function(m){m.keystrokeHandler=new a.keystrokeHandler(m);m.specialKeys={};},init:function(m){var n=m.config.keystrokes,o=m.config.blockedKeystrokes,p=m.keystrokeHandler.keystrokes,q=m.keystrokeHandler.blockedKeystrokes;for(var r=0;r7))O.append(J.createText('\xa0'));O.append(S.listNode);M=S.nextIndex;}else if(Q.indent==-1&&!G&&Q.grandparent){O; -if(m[Q.grandparent.getName()])O=Q.element.clone(false,true);else if(I||Q.element.hasAttributes()||H!=2){O=J.createElement(P);Q.element.copyAttributes(O,{type:1,value:1});var T=Q.element.getDirection()||I;T&&O.setAttribute('dir',T);if(!I&&H==2&&!O.hasAttributes())O=new d.documentFragment(J);}else O=new d.documentFragment(J);for(R=0;RH[J-1].indent+1){var N=H[J-1].indent+1-H[J].indent,O=H[J].indent;while(H[J]&&H[J].indent>=O){H[J].indent+=N;J++;}J--;}}var P=j.list.arrayToList(H,G,null,E.config.enterMode,F.root.getAttribute('dir')),Q=P.listNode,R,S;function T(U){if((R=Q[U?'getFirst':'getLast']())&&!(R.is&&R.isBlockBoundary())&&(S=F.root[U?'getPrevious':'getNext'](d.walker.whitespaces(true)))&&!(S.is&&S.isBlockBoundary({br:1})))E.document.createElement('br')[U?'insertBefore':'insertAfter'](R);};T(true);T();Q.replace(F.root);};function w(E,F){this.name=E;this.type=F;};w.prototype={exec:function(E){E.focus();var F=E.document,G=E.getSelection(),H=G&&G.getRanges(true);if(!H||H.length<1)return;if(this.state==2){var I=F.getBody();I.trim();if(!I.getFirst()){var J=F.createElement(E.config.enterMode==1?'p':E.config.enterMode==3?'div':'br');J.appendTo(I);H=new d.rangeList([new d.range(F)]);if(J.is('br')){H[0].setStartBefore(J);H[0].setEndAfter(J);}else H[0].selectNodeContents(J);G.selectRanges(H);}else{var K=H.length==1&&H[0],L=K&&K.getEnclosedNode();if(L&&L.is&&this.type==L.getName())this.setState(1);}}var M=G.createBookmarks(true),N=[],O={},P=H.createIterator(),Q=0;while((K=P.getNextRange())&&++Q){var R=K.getBoundaryNodes(),S=R.startNode,T=R.endNode;if(S.type==1&&S.getName()=='td')K.setStartAt(R.startNode,1);if(T.type==1&&T.getName()=='td')K.setEndAt(R.endNode,2);var U=K.createIterator(),V;U.forceBrBreak=this.state==2;while(V=U.getNextParagraph()){if(V.getCustomData('list_block'))continue;else h.setMarker(O,V,'list_block',1);var W=new d.elementPath(V),X=W.elements,Y=X.length,Z=null,aa=0,ab=W.blockLimit,ac;for(var ad=Y-1;ad>=0&&(ac=X[ad]);ad--){if(m[ac.getName()]&&ab.contains(ac)){ab.removeCustomData('list_group_object_'+Q);var ae=ac.getCustomData('list_group_object');if(ae)ae.contents.push(V); -else{ae={root:ac,contents:[V]};N.push(ae);h.setMarker(O,ac,'list_group_object',ae);}aa=1;break;}}if(aa)continue;var af=ab;if(af.getCustomData('list_group_object_'+Q))af.getCustomData('list_group_object_'+Q).contents.push(V);else{ae={root:af,contents:[V]};h.setMarker(O,af,'list_group_object_'+Q,ae);N.push(ae);}}}var ag=[];while(N.length>0){ae=N.shift();if(this.state==2){if(m[ae.root.getName()])s.call(this,E,ae,O,ag);else u.call(this,E,ae,ag);}else if(this.state==1&&m[ae.root.getName()])v.call(this,E,ae,O);}for(ad=0;ad0)for(var u=t.length-1;u>=0;u--){var v=t[u][0],w=t[u][1];if(w)v.insertBefore(w);else v.appendTo(s);}};function o(s,t){var u=m(s),v={},w=s.$;if(!t){v['class']=w.className||'';w.className='';}v.inline=w.style.cssText||'';if(!t)w.style.cssText='position: static; overflow: visible';n(u);return v;};function p(s,t){var u=m(s),v=s.$;if('class' in t)v.className=t['class'];if('inline' in t)v.style.cssText=t.inline;n(u);};function q(s){var t=a.instances;for(var u in t){var v=t[u];if(v.mode=='wysiwyg'){var w=v.document.getBody();w.setAttribute('contentEditable',false);w.setAttribute('contentEditable',true);}}if(s.focusManager.hasFocus){s.toolbox.focus();s.focus();}};function r(s){if(!c||b.version>6)return null;var t=h.createFromHtml('');return s.append(t,true);};j.add('maximize',{init:function(s){var t=s.lang,u=a.document,v=u.getWindow(),w,x,y,z;function A(){var C=v.getViewPaneSize();z&&z.setStyles({width:C.width+'px',height:C.height+'px'});s.resize(C.width,C.height,null,true);};var B=2;s.addCommand('maximize',{modes:{wysiwyg:1,source:1},editorFocus:false,exec:function(){var C=s.container.getChild(1),D=s.getThemeSpace('contents');if(s.mode=='wysiwyg'){var E=s.getSelection();w=E&&E.getRanges();x=v.getScrollPosition();}else{var F=s.textarea.$;w=!c&&[F.selectionStart,F.selectionEnd];x=[F.scrollLeft,F.scrollTop];}if(this.state==2){v.on('resize',A);y=v.getScrollPosition();var G=s.container;while(G=G.getParent()){G.setCustomData('maximize_saved_styles',o(G));G.setStyle('z-index',s.config.baseFloatZIndex-1);}D.setCustomData('maximize_saved_styles',o(D,true));C.setCustomData('maximize_saved_styles',o(C,true)); -var H={overflow:b.webkit?'':'hidden',width:0,height:0};u.getDocumentElement().setStyles(H);!b.gecko&&u.getDocumentElement().setStyle('position','fixed');u.getBody().setStyles(H);c?setTimeout(function(){v.$.scrollTo(0,0);},0):v.$.scrollTo(0,0);C.setStyle('position','absolute');C.$.offsetLeft;C.setStyles({'z-index':s.config.baseFloatZIndex-1,left:'0px',top:'0px'});z=r(C);C.addClass('cke_maximized');A();var I=C.getDocumentPosition();C.setStyles({left:-1*I.x+'px',top:-1*I.y+'px'});b.gecko&&q(s);}else if(this.state==1){v.removeListener('resize',A);var J=[D,C];for(var K=0;K ');o=m.createFakeElement(o,'cke_pagebreak','div');o.setAttributes({alt:n,'aria-label':n,title:n});var p=m.getSelection().getRanges(true);m.fire('saveSnapshot');for(var q,r=p.length-1;r>=0;r--){q=p[r];if(r1&&n.substr(n.length-1,1)=='%')n=parseInt(window.screen.width*parseInt(n,10)/100,10);if(typeof o=='string'&&o.length>1&&o.substr(o.length-1,1)=='%')o=parseInt(window.screen.height*parseInt(o,10)/100,10);if(n<640)n=640;if(o<420)o=420;var q=parseInt((window.screen.height-o)/2,10),r=parseInt((window.screen.width-n)/2,10);p=(p||'location=no,menubar=no,toolbar=no,dependent=yes,minimizable=no,modal=yes,alwaysRaised=yes,resizable=yes,scrollbars=yes')+',width='+n+',height='+o+',top='+q+',left='+r;var s=window.open('',null,p,true);if(!s)return false;try{s.moveTo(r,q);s.resizeTo(n,o);s.focus();s.location.href=m;}catch(t){s=window.open(m,null,p,true);}return true;}});(function(){var m={modes:{wysiwyg:1,source:1},canUndo:false,exec:function(o){var p,q=o.config,r=q.baseHref?'':'',s=b.isCustomDomain();if(q.fullPage)p=o.getData().replace(//,'$&'+r).replace(/[^>]*(?=<\/title>)/,'$& — '+o.lang.preview);else{var t=''+''+r+''+o.lang.preview+''+e.buildStyleHtml(o.config.contentsCss)+''+t+o.getData()+'';}var v=640,w=420,x=80;try{var y=window.screen;v=Math.round(y.width*0.8);w=Math.round(y.height*0.7);x=Math.round(y.width*0.1);}catch(B){}var z='';if(s){window._cke_htmlToLoad=p;z='javascript:void( (function(){document.open();document.domain="'+document.domain+'";'+'document.write( window.opener._cke_htmlToLoad );'+'document.close();'+'window.opener._cke_htmlToLoad = null;'+'})() )';}var A=window.open(z,null,'toolbar=yes,location=no,status=yes,menubar=yes,scrollbars=yes,resizable=yes,width='+v+',height='+w+',left='+x);if(!s){A.document.open();A.document.write(p);A.document.close();}}},n='preview';j.add(n,{init:function(o){o.addCommand(n,m);o.ui.addButton('Preview',{label:o.lang.preview,command:n});}});})();j.add('print',{init:function(m){var n='print',o=m.addCommand(n,j.print);m.ui.addButton('Print',{label:m.lang.print,command:n});}});j.print={exec:function(m){if(b.opera)return;else if(b.gecko)m.window.$.print(); -else m.document.$.execCommand('Print');},canUndo:false,modes:{wysiwyg:!b.opera}};j.add('removeformat',{requires:['selection'],init:function(m){m.addCommand('removeFormat',j.removeformat.commands.removeformat);m.ui.addButton('RemoveFormat',{label:m.lang.removeFormat,command:'removeFormat'});m._.removeFormat={filters:[]};}});j.removeformat={commands:{removeformat:{exec:function(m){var n=m._.removeFormatRegex||(m._.removeFormatRegex=new RegExp('^(?:'+m.config.removeFormatTags.replace(/,/g,'|')+')$','i')),o=m._.removeAttributes||(m._.removeAttributes=m.config.removeFormatAttributes.split(',')),p=j.removeformat.filter,q=m.getSelection().getRanges(1),r=q.createIterator(),s;while(s=r.getNextRange()){if(!s.collapsed)s.enlarge(1);var t=s.createBookmark(),u=t.startNode,v=t.endNode,w,x=function(z){var A=new d.elementPath(z),B=A.elements;for(var C=1,D;D=B[C];C++){if(D.equals(A.block)||D.equals(A.blockLimit))break;if(n.test(D.getName())&&p(m,D))z.breakParent(D);}};x(u);if(v){x(v);w=u.getNextSourceNode(true,1);while(w){if(w.equals(v))break;var y=w.getNextSourceNode(false,1);if(!(w.getName()=='img'&&w.data('cke-realelement'))&&p(m,w))if(n.test(w.getName()))w.remove(1);else{w.removeAttributes(o);m.fire('removeFormatCleanup',w);}w=y;}}s.moveToBookmark(t);}m.getSelection().selectRanges(q);}}},filter:function(m,n){var o=m._.removeFormat.filters;for(var p=0;pq.width&&(n.resize_minWidth=q.width);n.resize_minHeight>q.height&&(n.resize_minHeight=q.height);a.document.on('mousemove',t);a.document.on('mouseup',u);if(m.document){m.document.on('mousemove',t);m.document.on('mouseup',u);}});m.on('destroy',function(){e.removeFunction(v);});m.on('themeSpace',function(w){if(w.data.space=='bottom'){var x='';if(r&&!s)x=' cke_resizer_horizontal';if(!r&&s)x=' cke_resizer_vertical';w.data.html+='
';}},m,null,100);}}});(function(){var m={modes:{wysiwyg:1,source:1},exec:function(o){var p=o.element.$.form;if(p)try{p.submit();}catch(q){if(p.submit.click)p.submit.click();}}},n='save';j.add(n,{init:function(o){var p=o.addCommand(n,m);p.modes={wysiwyg:!!o.element.$.form};o.ui.addButton('Save',{label:o.lang.save,command:n});}});})();(function(){var m='scaytcheck',n='';function o(t,u){var v=0,w;for(w in u){if(u[w]==t){v=1;break;}}return v;};var p=function(){var t=this,u=function(){var y=t.config,z={};z.srcNodeRef=t.document.getWindow().$.frameElement;z.assocApp='CKEDITOR.'+a.version+'@'+a.revision;z.customerid=y.scayt_customerid||'1:WvF0D4-UtPqN1-43nkD4-NKvUm2-daQqk3-LmNiI-z7Ysb4-mwry24-T8YrS3-Q2tpq2';z.customDictionaryIds=y.scayt_customDictionaryIds||'';z.userDictionaryName=y.scayt_userDictionaryName||'';z.sLang=y.scayt_sLang||'en_US';z.onLoad=function(){if(!(c&&b.version<8))this.addStyle(this.selectorCss(),'padding-bottom: 2px !important;');if(t.focusManager.hasFocus&&!q.isControlRestored(t))this.focus();};z.onBeforeChange=function(){if(q.getScayt(t)&&!t.checkDirty())setTimeout(function(){t.resetDirty();},0);};var A=window.scayt_custom_params;if(typeof A=='object')for(var B in A)z[B]=A[B];if(q.getControlId(t))z.id=q.getControlId(t);var C=new window.scayt(z);C.afterMarkupRemove.push(function(J){new h(J,C.document).mergeSiblings();});var D=q.instances[t.name];if(D){C.sLang=D.sLang;C.option(D.option());C.paused=D.paused;}q.instances[t.name]=C;var E='scaytButton',F=window.scayt.uiTags,G=[];for(var H=0,I=4;H=0){this.setState(0);q.loadEngine(t);}}};j.add('scayt',{requires:['menubutton'],beforeInit:function(t){var u=t.config.scayt_contextMenuItemsOrder||'suggest|moresuggest|control',v='';u=u.split('|');if(u&&u.length)for(var w=0;w tr > td, .%1 table.%2 > tr > th,','.%1 table.%2 > tbody > tr > td, .%1 table.%2 > tbody > tr > th,','.%1 table.%2 > thead > tr > td, .%1 table.%2 > thead > tr > th,','.%1 table.%2 > tfoot > tr > td, .%1 table.%2 > tfoot > tr > th','{','border : #d3d3d3 1px dotted','}']).join('');n=o.replace(/%2/g,m).replace(/%1/g,'cke_show_borders ');var p={preserveState:true,editorFocus:false,exec:function(q){this.toggleState();this.refresh(q);},refresh:function(q){var r=this.state==1?'addClass':'removeClass';q.document.getBody()[r]('cke_show_borders');}};j.add('showborders',{requires:['wysiwygarea'],modes:{wysiwyg:1},init:function(q){var r=q.addCommand('showborders',p);r.canUndo=false;if(q.config.startupShowBorders!==false)r.setState(1);q.addCss(n);q.on('mode',function(){if(r.state!=0)r.refresh(q);},null,null,100);q.on('contentDom',function(){if(r.state!=0)r.refresh(q);});q.on('removeFormatCleanup',function(s){var t=s.data;if(q.getCommand('showborders').state==1&&t.is('table')&&(!t.hasAttribute('border')||parseInt(t.getAttribute('border'),10)<=0))t.addClass(m);});},afterInit:function(q){var r=q.dataProcessor,s=r&&r.dataFilter,t=r&&r.htmlFilter;if(s)s.addRules({elements:{table:function(u){var v=u.attributes,w=v['class'],x=parseInt(v.border,10);if(!x||x<=0)v['class']=(w||'')+' '+m;}}});if(t)t.addRules({elements:{table:function(u){var v=u.attributes,w=v['class'];w&&(v['class']=w.replace(m,'').replace(/\s{2}/,' ').replace(/^\s+|\s+$/,''));}}});}});a.on('dialogDefinition',function(q){var r=q.data.name;if(r=='table'||r=='tableProperties'){var s=q.data.definition,t=s.getContents('info'),u=t.get('txtBorder'),v=u.commit;u.commit=e.override(v,function(y){return function(z,A){y.apply(this,arguments);var B=parseInt(this.getValue(),10);A[!B||B<=0?'addClass':'removeClass'](m);};});var w=s.getContents('advanced'),x=w&&w.get('advCSSClasses');if(x){x.setup=e.override(x.setup,function(y){return function(){y.apply(this,arguments);this.setValue(this.getValue().replace(/cke_show_border/,''));};});x.commit=e.override(x.commit,function(y){return function(z,A){y.apply(this,arguments);if(!parseInt(A.getAttribute('border'),10))A.addClass('cke_show_border');};});}}});})();j.add('sourcearea',{requires:['editingblock'],init:function(m){var n=j.sourcearea,o=a.document.getWindow(); -m.on('editingBlockReady',function(){var p,q;m.addMode('source',{load:function(r,s){if(c&&b.version<8)r.setStyle('position','relative');m.textarea=p=new h('textarea');p.setAttributes({dir:'ltr',tabIndex:b.webkit?-1:m.tabIndex,role:'textbox','aria-label':m.lang.editorTitle.replace('%1',m.name)});p.addClass('cke_source');p.addClass('cke_enable_context_menu');var t={width:b.ie7Compat?'99%':'100%',height:'100%',resize:'none',outline:'none','text-align':'left'};if(c){q=function(){p.hide();p.setStyle('height',r.$.clientHeight+'px');p.setStyle('width',r.$.clientWidth+'px');p.show();};m.on('resize',q);o.on('resize',q);setTimeout(q,0);}r.setHtml('');r.append(p);p.setStyles(t);m.fire('ariaWidget',p);p.on('blur',function(){m.focusManager.blur();});p.on('focus',function(){m.focusManager.focus();});m.mayBeDirty=true;this.loadData(s);var u=m.keystrokeHandler;if(u)u.attach(p);setTimeout(function(){m.mode='source';m.fire('mode');},b.gecko||b.webkit?100:0);},loadData:function(r){p.setValue(r);m.fire('dataReady');},getData:function(){return p.getValue();},getSnapshotData:function(){return p.getValue();},unload:function(r){p.clearCustomData();m.textarea=p=null;if(q){m.removeListener('resize',q);o.removeListener('resize',q);}if(c&&b.version<8)r.removeStyle('position');},focus:function(){p.focus();}});});m.addCommand('source',n.commands.source);if(m.ui.addButton)m.ui.addButton('Source',{label:m.lang.source,command:'source'});m.on('mode',function(){m.getCommand('source').setState(m.mode=='source'?1:2);});}});j.sourcearea={commands:{source:{modes:{wysiwyg:1,source:1},editorFocus:false,exec:function(m){if(m.mode=='wysiwyg')m.fire('saveSnapshot');m.getCommand('source').setState(0);m.setMode(m.mode=='source'?'wysiwyg':'source');},canUndo:false}}};(function(){j.add('stylescombo',{requires:['richcombo','styles'],init:function(n){var o=n.config,p=n.lang.stylesCombo,q={},r=[];function s(t){n.getStylesSet(function(u){if(!r.length){var v,w;for(var x=0,y=u.length;x0)return;if(T.type==1&&m.test(T.getName())&&!T.getCustomData('selected_cell')){h.setMarker(K,T,'selected_cell',true);J.push(T);}};for(var M=0;M1&&V&&U[Y]==V[Y]){Z=U[Y];Z.rowSpan+=1;}else{Z=new h(U[Y]).clone();Z.removeAttribute('rowSpan');!c&&Z.appendBogus();X.append(Z);Z=Z.$;}Y+=Z.colSpan-1;}H?X.insertBefore(S):X.insertAfter(S);};function q(G){if(G instanceof d.selection){var H=n(G),I=H[0],J=I.getAscendant('table'),K=e.buildTableMap(J),L=H[0].getParent(),M=L.$.rowIndex,N=H[H.length-1],O=N.getParent().$.rowIndex+N.$.rowSpan-1,P=[];for(var Q=M;Q<=O;Q++){var R=K[Q],S=new h(J.$.rows[Q]);for(var T=0;T=0;Q--)q(P[Q]);return Y;}else if(G instanceof h){J=G.getAscendant('table');if(J.$.rows.length==1)J.remove();else G.remove();}return null;};function r(G,H){var I=G.getParent(),J=I.$.cells,K=0;for(var L=0;LI)I=K;}return I;};function t(G,H){var I=n(G),J=I[0],K=J.getAscendant('table'),L=s(I,1),M=s(I),N=H?L:M,O=e.buildTableMap(K),P=[],Q=[],R=O.length;for(var S=0;S1&&Q.length&&Q[S]==P[S]){U=P[S];U.colSpan+=1;}else{U=new h(P[S]).clone();U.removeAttribute('colSpan');!c&&U.appendBogus();U[H?'insertBefore':'insertAfter'].call(U,new h(P[S]));U=U.$;}S+=U.rowSpan-1;}};function u(G){var H=n(G),I=H[0],J=H[H.length-1],K=I.getAscendant('table'),L=e.buildTableMap(K),M,N,O=[];for(var P=0,Q=L.length;P1){L=H[J-1]+1;break;}}if(!L)L=H[0]>0?H[0]-1:H[H.length-1]+1;var N=I.$.rows;for(J=0,K=N.length;J=0;K--)x(H[K]);if(J)z(J,true);else if(I)I.remove();}else if(G instanceof h){var L=G.getParent();if(L.getChildCount()==1)L.remove();else G.remove();}};function y(G){var H=G.getBogus();H&&H.remove();G.trim();};function z(G,H){var I=new d.range(G.getDocument());if(!I['moveToElementEdit'+(H?'End':'Start')](G)){I.selectNodeContents(G);I.collapse(H?false:true);}I.select(true);};function A(G,H,I){var J=G[H];if(typeof I=='undefined')return J;for(var K=0;J&&K=Q)M.removeAttribute('rowSpan');else M.$.rowSpan=Y;if(Y>=P)M.removeAttribute('colSpan');else M.$.colSpan=Z;var ak=new d.nodeList(N.$.rows),al=ak.count();for(ac=al-1;ac>=0;ac--){var am=ak.getItem(ac);if(!am.$.cells.length){am.remove();al++;continue;}}return M;}else return Y*Z==ab;};function D(G,H){var I=n(G);if(I.length>1)return false;else if(H)return true;var J=I[0],K=J.getParent(),L=K.getAscendant('table'),M=e.buildTableMap(L),N=K.$.rowIndex,O=A(M,N,J),P=J.$.rowSpan,Q,R,S,T;if(P>1){R=Math.ceil(P/2);S=Math.floor(P/2);T=N+R;var U=new h(L.$.rows[T]),V=A(M,T),W;Q=J.clone();for(var X=0;XO){Q.insertBefore(new h(W));break;}else W=null;}if(!W)U.append(Q,true);}else{S=R=1;U=K.clone();U.insertAfter(K);U.append(Q=J.clone());var Y=A(M,N);for(var Z=0;Z1)return false;else if(H)return true;var J=I[0],K=J.getParent(),L=K.getAscendant('table'),M=e.buildTableMap(L),N=K.$.rowIndex,O=A(M,N,J),P=J.$.colSpan,Q,R,S;if(P>1){R=Math.ceil(P/2);S=Math.floor(P/2);}else{S=R=1;var T=B(M,O);for(var U=0;U0?2:0};}},tablecell_insertBefore:{label:H.cell.insertBefore,group:'tablecell',command:'cellInsertBefore',order:5},tablecell_insertAfter:{label:H.cell.insertAfter,group:'tablecell',command:'cellInsertAfter',order:10},tablecell_delete:{label:H.cell.deleteCell,group:'tablecell',command:'cellDelete',order:15},tablecell_merge:{label:H.cell.merge,group:'tablecell',command:'cellMerge',order:16},tablecell_merge_right:{label:H.cell.mergeRight,group:'tablecell',command:'cellMergeRight',order:17},tablecell_merge_down:{label:H.cell.mergeDown,group:'tablecell',command:'cellMergeDown',order:18},tablecell_split_horizontal:{label:H.cell.splitHorizontal,group:'tablecell',command:'cellHorizontalSplit',order:19},tablecell_split_vertical:{label:H.cell.splitVertical,group:'tablecell',command:'cellVerticalSplit',order:20},tablecell_properties:{label:H.cell.title,group:'tablecellproperties',command:'cellProperties',order:21},tablerow:{label:H.row.menu,group:'tablerow',order:1,getItems:function(){return{tablerow_insertBefore:2,tablerow_insertAfter:2,tablerow_delete:2};}},tablerow_insertBefore:{label:H.row.insertBefore,group:'tablerow',command:'rowInsertBefore',order:5},tablerow_insertAfter:{label:H.row.insertAfter,group:'tablerow',command:'rowInsertAfter',order:10},tablerow_delete:{label:H.row.deleteRow,group:'tablerow',command:'rowDelete',order:15},tablecolumn:{label:H.column.menu,group:'tablecolumn',order:1,getItems:function(){return{tablecolumn_insertBefore:2,tablecolumn_insertAfter:2,tablecolumn_delete:2}; -}},tablecolumn_insertBefore:{label:H.column.insertBefore,group:'tablecolumn',command:'columnInsertBefore',order:5},tablecolumn_insertAfter:{label:H.column.insertAfter,group:'tablecolumn',command:'columnInsertAfter',order:10},tablecolumn_delete:{label:H.column.deleteColumn,group:'tablecolumn',command:'columnDelete',order:15}});if(G.contextMenu)G.contextMenu.addListener(function(I,J){if(!I||I.isReadOnly())return null;while(I){if(I.getName() in F)return{tablecell:2,tablerow:2,tablecolumn:2};I=I.getParent();}return null;});},getSelectedCells:n};j.add('tabletools',j.tabletools);})();e.buildTableMap=function(m){var n=m.$.rows,o=-1,p=[];for(var q=0;q'+u+'',u);}},onClick:function(t){m.focus();m.fire('saveSnapshot');var u=q[t],v=new d.elementPath(m.getSelection().getStartElement());u[u.checkActive(v)?'remove':'apply'](m.document);setTimeout(function(){m.fire('saveSnapshot');},0);},onRender:function(){m.on('selectionChange',function(t){var u=this.getValue(),v=t.data.path;for(var w in q){if(q[w].checkActive(v)){if(w!=u)this.setValue(w,m.lang.format['tag_'+w]);return;}}this.setValue('');},this);}});}});i.format_tags='p;h1;h2;h3;h4;h5;h6;pre;address;div';i.format_p={element:'p'};i.format_div={element:'div'};i.format_pre={element:'pre'};i.format_address={element:'address'};i.format_h1={element:'h1'};i.format_h2={element:'h2'};i.format_h3={element:'h3'};i.format_h4={element:'h4'};i.format_h5={element:'h5'};i.format_h6={element:'h6'};j.add('forms',{init:function(m){var n=m.lang;m.addCss('form{border: 1px dotted #FF0000;padding: 2px;}\n'); +m.addCss('img.cke_hidden{background-image: url('+a.getUrl(this.path+'images/hiddenfield.gif')+');'+'background-position: center center;'+'background-repeat: no-repeat;'+'border: 1px solid #a9a9a9;'+'width: 16px !important;'+'height: 16px !important;'+'}');var o=function(q,r,s){m.addCommand(r,new a.dialogCommand(r));m.ui.addButton(q,{label:n.common[q.charAt(0).toLowerCase()+q.slice(1)],command:r});a.dialog.add(r,s);},p=this.path+'dialogs/';o('Form','form',p+'form.js');o('Checkbox','checkbox',p+'checkbox.js');o('Radio','radio',p+'radio.js');o('TextField','textfield',p+'textfield.js');o('Textarea','textarea',p+'textarea.js');o('Select','select',p+'select.js');o('Button','button',p+'button.js');o('ImageButton','imagebutton',j.getPath('image')+'dialogs/image.js');o('HiddenField','hiddenfield',p+'hiddenfield.js');if(m.addMenuItems)m.addMenuItems({form:{label:n.form.menu,command:'form',group:'form'},checkbox:{label:n.checkboxAndRadio.checkboxTitle,command:'checkbox',group:'checkbox'},radio:{label:n.checkboxAndRadio.radioTitle,command:'radio',group:'radio'},textfield:{label:n.textfield.title,command:'textfield',group:'textfield'},hiddenfield:{label:n.hidden.title,command:'hiddenfield',group:'hiddenfield'},imagebutton:{label:n.image.titleButton,command:'imagebutton',group:'imagebutton'},button:{label:n.button.title,command:'button',group:'button'},select:{label:n.select.title,command:'select',group:'select'},textarea:{label:n.textarea.title,command:'textarea',group:'textarea'}});if(m.contextMenu){m.contextMenu.addListener(function(q){if(q&&q.hasAscendant('form',true)&&!q.isReadOnly())return{form:2};});m.contextMenu.addListener(function(q){if(q&&!q.isReadOnly()){var r=q.getName();if(r=='select')return{select:2};if(r=='textarea')return{textarea:2};if(r=='input')switch(q.getAttribute('type')){case 'button':case 'submit':case 'reset':return{button:2};case 'checkbox':return{checkbox:2};case 'radio':return{radio:2};case 'image':return{imagebutton:2};default:return{textfield:2};}if(r=='img'&&q.data('cke-real-element-type')=='hiddenfield')return{hiddenfield:2};}});}m.on('doubleclick',function(q){var r=q.data.element;if(r.is('form'))q.data.dialog='form';else if(r.is('select'))q.data.dialog='select';else if(r.is('textarea'))q.data.dialog='textarea';else if(r.is('img')&&r.data('cke-real-element-type')=='hiddenfield')q.data.dialog='hiddenfield';else if(r.is('input'))switch(r.getAttribute('type')){case 'button':case 'submit':case 'reset':q.data.dialog='button';break;case 'checkbox':q.data.dialog='checkbox'; +break;case 'radio':q.data.dialog='radio';break;case 'image':q.data.dialog='imagebutton';break;default:q.data.dialog='textfield';break;}});},afterInit:function(m){var n=m.dataProcessor,o=n&&n.htmlFilter,p=n&&n.dataFilter;if(c)o&&o.addRules({elements:{input:function(q){var r=q.attributes,s=r.type;if(!s)r.type='text';if(s=='checkbox'||s=='radio')r.value=='on'&&delete r.value;}}});if(p)p.addRules({elements:{input:function(q){if(q.attributes.type=='hidden')return m.createFakeParserElement(q,'cke_hidden','hiddenfield');}}});},requires:['image','fakeobjects']});if(c)h.prototype.hasAttribute=function(m){var p=this;var n=p.$.attributes.getNamedItem(m);if(p.getName()=='input')switch(m){case 'class':return p.$.className.length>0;case 'checked':return!!p.$.checked;case 'value':var o=p.getAttribute('type');return o=='checkbox'||o=='radio'?p.$.value!='on':p.$.value;}return!!(n&&n.specified);};(function(){var m={canUndo:false,exec:function(o){o.insertElement(o.document.createElement('hr'));}},n='horizontalrule';j.add(n,{init:function(o){o.addCommand(n,m);o.ui.addButton('HorizontalRule',{label:o.lang.horizontalrule,command:n});}});})();(function(){var m=/^[\t\r\n ]*(?: |\xa0)$/,n='{cke_protected}';function o(T){var U=T.children.length,V=T.children[U-1];while(V&&V.type==3&&!e.trim(V.value))V=T.children[--U];return V;};function p(T,U){var V=T.children,W=o(T);if(W){if((U||!c)&&W.type==1&&W.name=='br')V.pop();if(W.type==3&&m.test(W.value))V.pop();}};function q(T,U,V){if(!U&&(!V||typeof V=='function'&&V(T)===false))return false;if(U&&c&&(document.documentMode>7||T.name in f.tr||T.name in f.$listItem))return false;var W=o(T);return!W||W&&(W.type==1&&W.name=='br'||T.name=='form'&&W.name=='input');};function r(T,U){return function(V){p(V,!T);if(q(V,!T,U))if(T||c)V.add(new a.htmlParser.text('\xa0'));else V.add(new a.htmlParser.element('br',{}));};};var s=f,t=['caption','colgroup','col','thead','tfoot','tbody'],u=e.extend({},s.$block,s.$listItem,s.$tableContent);for(var v in u){if(!('br' in s[v]))delete u[v];}delete u.pre;var w={elements:{a:function(T){var U=T.attributes;if(U&&U['data-cke-saved-name'])U['class']=(U['class']?U['class']+' ':'')+'cke_anchor';}},attributeNames:[[/^on/,'data-cke-pa-on']]},x={elements:{}};for(v in u)x.elements[v]=r();var y={elementNames:[[/^cke:/,''],[/^\?xml:namespace$/,'']],attributeNames:[[/^data-cke-(saved|pa)-/,''],[/^data-cke-.*/,''],['hidefocus','']],elements:{$:function(T){var U=T.attributes;if(U){if(U['data-cke-temp'])return false;var V=['name','href','src'],W; +for(var X=0;Xe.indexOf(t,W.name)?1:-1:0;});},embed:function(T){var U=T.parent;if(U&&U.name=='object'){var V=U.attributes.width,W=U.attributes.height;V&&(T.attributes.width=V);W&&(T.attributes.height=W);}},param:function(T){T.children=[];T.isEmpty=true;return T;},a:function(T){if(!(T.children.length||T.attributes.name||T.attributes['data-cke-saved-name']))return false;},span:function(T){if(T.attributes['class']=='Apple-style-span')delete T.name;},pre:function(T){c&&p(T);},html:function(T){delete T.attributes.contenteditable;delete T.attributes['class'];},body:function(T){delete T.attributes.spellcheck;delete T.attributes.contenteditable;},style:function(T){var U=T.children[0];U&&U.value&&(U.value=e.trim(U.value));if(!T.attributes.type)T.attributes.type='text/css';},title:function(T){var U=T.children[0];U&&(U.value=T.attributes['data-cke-title']||'');}},attributes:{'class':function(T,U){return e.ltrim(T.replace(/(?:^|\s+)cke_[^\s]*/g,''))||false;}}};if(c)y.attributes.style=function(T,U){return T.replace(/(^|;)([^\:]+)/g,function(V){return V.toLowerCase();});};function z(T){var U=T.attributes;if(U.contenteditable!='false')U['data-cke-editable']=U.contenteditable?'true':1;U.contenteditable='false';};function A(T){var U=T.attributes;switch(U['data-cke-editable']){case 'true':U.contenteditable='true';break;case '1':delete U.contenteditable;break;}};for(v in {input:1,textarea:1}){w.elements[v]=z;y.elements[v]=A;}var B=/<(a|area|img|input)\b([^>]*)>/gi,C=/\b(href|src|name)\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|(?:[^ "'>]+))/gi,D=/(?:])[^>]*>[\s\S]*<\/style>)|(?:<(:?link|meta|base)[^>]*>)/gi,E=/([^<]*)<\/cke:encoded>/gi,F=/(<\/?)((?:object|embed|param|html|body|head|title)[^>]*>)/gi,G=/(<\/?)cke:((?:html|body|head|title)[^>]*>)/gi,H=/]*?)\/?>(?!\s*<\/cke:\1)/gi;function I(T){return T.replace(B,function(U,V,W){return '<'+V+W.replace(C,function(X,Y){if(W.indexOf('data-cke-saved-'+Y)==-1)return ' data-cke-saved-'+X+' '+X;return X;})+'>';});};function J(T){return T.replace(D,function(U){return ''+encodeURIComponent(U)+'';});};function K(T){return T.replace(E,function(U,V){return decodeURIComponent(V);});};function L(T){return T.replace(F,'$1cke:$2');};function M(T){return T.replace(G,'$1$2');};function N(T){return T.replace(H,''); +};function O(T){return T.replace(/(]*>)(\r\n|\n)/g,'$1$2$2');};function P(T){return T.replace(//g,function(U){return '';});};function Q(T){return T.replace(//g,function(U,V){return decodeURIComponent(V);});};function R(T,U){var V=U._.dataStore;return T.replace(//g,function(W,X){return decodeURIComponent(X);}).replace(/\{cke_protected_(\d+)\}/g,function(W,X){return V&&V[X]||'';});};function S(T,U){var V=[],W=U.config.protectedSource,X=U._.dataStore||(U._.dataStore={id:1}),Y=/<\!--\{cke_temp(comment)?\}(\d*?)-->/g,Z=[//gi,//gi].concat(W);T=T.replace(//g,function(ab){return '';});for(var aa=0;aa';});T=T.replace(Y,function(ab,ac,ad){return '';});return T.replace(/(['"]).*?\1/g,function(ab){return ab.replace(//g,function(ac,ad){X[X.id]=decodeURIComponent(ad);return '{cke_protected_'+X.id++ +'}';});});};j.add('htmldataprocessor',{requires:['htmlwriter'],init:function(T){var U=T.dataProcessor=new a.htmlDataProcessor(T);U.writer.forceSimpleAmpersand=T.config.forceSimpleAmpersand;U.dataFilter.addRules(w);U.dataFilter.addRules(x);U.htmlFilter.addRules(y);var V={elements:{}};for(v in u)V.elements[v]=r(true,T.config.fillEmptyBlocks);U.htmlFilter.addRules(V);},onLoad:function(){!('fillEmptyBlocks' in i)&&(i.fillEmptyBlocks=1);}});a.htmlDataProcessor=function(T){var U=this;U.editor=T;U.writer=new a.htmlWriter();U.dataFilter=new a.htmlParser.filter();U.htmlFilter=new a.htmlParser.filter();};a.htmlDataProcessor.prototype={toHtml:function(T,U){T=S(T,this.editor);T=I(T);T=J(T);T=L(T);T=N(T);T=O(T);var V=new h('div');V.setHtml('a'+T);T=V.getHtml().substr(1);T=M(T);T=K(T);T=Q(T);var W=a.htmlParser.fragment.fromHtml(T,U),X=new a.htmlParser.basicWriter();W.writeHtml(X,this.dataFilter);T=X.getHtml(true);T=P(T);return T;},toDataFormat:function(T,U){var V=this.writer,W=a.htmlParser.fragment.fromHtml(T,U);V.reset();W.writeHtml(V,this.htmlFilter);var X=V.getHtml(true);X=Q(X);X=R(X,this.editor);return X;}};})();(function(){function m(n,o){var p=n.createFakeParserElement(o,'cke_iframe','iframe',true),q=p.attributes.style||'',r=o.attributes.width,s=o.attributes.height; +if(typeof r!='undefined')q+='width:'+e.cssLength(r)+';';if(typeof s!='undefined')q+='height:'+e.cssLength(s)+';';p.attributes.style=q;return p;};j.add('iframe',{requires:['dialog','fakeobjects'],init:function(n){var o='iframe',p=n.lang.iframe;a.dialog.add(o,this.path+'dialogs/iframe.js');n.addCommand(o,new a.dialogCommand(o));n.addCss('img.cke_iframe{background-image: url('+a.getUrl(this.path+'images/placeholder.png')+');'+'background-position: center center;'+'background-repeat: no-repeat;'+'border: 1px solid #a9a9a9;'+'width: 80px;'+'height: 80px;'+'}');n.ui.addButton('Iframe',{label:p.toolbar,command:o});n.on('doubleclick',function(q){var r=q.data.element;if(r.is('img')&&r.data('cke-real-element-type')=='iframe')q.data.dialog='iframe';});if(n.addMenuItems)n.addMenuItems({iframe:{label:p.title,command:'iframe',group:'image'}});if(n.contextMenu)n.contextMenu.addListener(function(q,r){if(q&&q.is('img')&&q.data('cke-real-element-type')=='iframe')return{iframe:2};});},afterInit:function(n){var o=n.dataProcessor,p=o&&o.dataFilter;if(p)p.addRules({elements:{iframe:function(q){return m(n,q);}}});}});})();j.add('image',{init:function(m){var n='image';a.dialog.add(n,this.path+'dialogs/image.js');m.addCommand(n,new a.dialogCommand(n));m.ui.addButton('Image',{label:m.lang.common.image,command:n});m.on('doubleclick',function(o){var p=o.data.element;if(p.is('img')&&!p.data('cke-realelement')&&!p.isReadOnly())o.data.dialog='image';});if(m.addMenuItems)m.addMenuItems({image:{label:m.lang.image.menu,command:'image',group:'image'}});if(m.contextMenu)m.contextMenu.addListener(function(o,p){if(!o||!o.is('img')||o.data('cke-realelement')||o.isReadOnly())return null;return{image:2};});}});i.image_removeLinkByEmptyURL=true;(function(){var m={ol:1,ul:1},n=d.walker.whitespaces(true),o=d.walker.bookmark(false,true);function p(t){var B=this;var u=t.editor,v=t.data.path,w=v&&v.contains(m),x=v.block||v.blockLimit;if(w)return B.setState(2);if(!B.useIndentClasses&&B.name=='indent')return B.setState(2);if(!x)return B.setState(0);if(B.useIndentClasses){var y=x.$.className.match(B.classNameRegex),z=0;if(y){y=y[1];z=B.indentClassMap[y];}if(B.name=='outdent'&&!z||B.name=='indent'&&z==u.config.indentClasses.length)return B.setState(0);return B.setState(2);}else{var A=parseInt(x.getStyle(r(x)),10);if(isNaN(A))A=0;if(A<=0)return B.setState(0);return B.setState(2);}};function q(t,u){var w=this;w.name=u;w.useIndentClasses=t.config.indentClasses&&t.config.indentClasses.length>0;if(w.useIndentClasses){w.classNameRegex=new RegExp('(?:^|\\s+)('+t.config.indentClasses.join('|')+')(?=$|\\s)'); +w.indentClassMap={};for(var v=0;vY;T++)X[T].indent+=U;var aa=j.list.arrayToList(X,v,null,t.config.enterMode,M.getDirection());if(u.name=='outdent'){var ab;if((ab=M.getParent())&&ab.is('li')){var ac=aa.listNode.getChildren(),ad=[],ae=ac.count(),af;for(T=ae-1;T>=0;T--){if((af=ac.getItem(T))&&af.is&&af.is('li'))ad.push(af);}}}if(aa)aa.listNode.replace(M);if(ad&&ad.length)for(T=0;T0)M.addClass(t.config.indentClasses[P-1]);}else{var Q=r(M,N),R=parseInt(M.getStyle(Q),10);if(isNaN(R))R=0;var S=t.config.indentOffset||40;R+=(u.name=='indent'?1:-1)*S;if(R<0)return false;R=Math.max(R,0);R=Math.ceil(R/S)*S;M.setStyle(Q,R?R+(t.config.indentUnit||'px'):'');if(M.getAttribute('style')==='')M.removeAttribute('style');}h.setMarker(v,M,'indent_processed',1); +return true;};var z=t.getSelection(),A=z.createBookmarks(1),B=z&&z.getRanges(1),C,D=B.createIterator();while(C=D.getNextRange()){var E=C.getCommonAncestor(),F=E;while(F&&!(F.type==1&&m[F.getName()]))F=F.getParent();if(!F){var G=C.getEnclosedNode();if(G&&G.type==1&&G.getName() in m){C.setStartAt(G,1);C.setEndAt(G,2);F=G;}}if(F&&C.startContainer.type==1&&C.startContainer.getName() in m){var H=new d.walker(C);H.evaluator=s;C.startContainer=H.next();}if(F&&C.endContainer.type==1&&C.endContainer.getName() in m){H=new d.walker(C);H.evaluator=s;C.endContainer=H.previous();}if(F){var I=F.getFirst(s),J=!!I.getNext(s),K=C.startContainer,L=I.equals(K)||I.contains(K);if(!(L&&(u.name=='indent'||u.useIndentClasses||parseInt(F.getStyle(r(F)),10))&&y(F,!J&&I.getDirection())))w(F);}else x();}h.clearAllMarkers(v);t.forceNextSelectionCheck();z.selectBookmarks(A);}};j.add('indent',{init:function(t){var u=t.addCommand('indent',new q(t,'indent')),v=t.addCommand('outdent',new q(t,'outdent'));t.ui.addButton('Indent',{label:t.lang.indent,command:'indent'});t.ui.addButton('Outdent',{label:t.lang.outdent,command:'outdent'});t.on('selectionChange',e.bind(p,u));t.on('selectionChange',e.bind(p,v));if(b.ie6Compat||b.ie7Compat)t.addCss('ul,ol{\tmargin-left: 0px;\tpadding-left: 40px;}');t.on('dirChanged',function(w){var x=new d.range(t.document);x.setStartBefore(w.data.node);x.setEndAfter(w.data.node);var y=new d.walker(x),z;while(z=y.next()){if(z.type==1){if(!z.equals(w.data.node)&&z.getDirection()){x.setStartAfter(z);y=new d.walker(x);continue;}var A=t.config.indentClasses;if(A){var B=w.data.dir=='ltr'?['_rtl','']:['','_rtl'];for(var C=0;C=0;A--){x=v[A].createIterator();x.enlargeBr=t!=2;while(y=x.getNextParagraph(t==1?'p':'div')){y.removeAttribute('align');y.removeStyle('text-align');var B=w&&(y.$.className=e.ltrim(y.$.className.replace(D.cssClassRegex,''))),C=D.state==2&&(!z||n(y,true)!=D.value);if(w){if(C)y.addClass(w);else if(!B)y.removeAttribute('class');}else if(C)y.setStyle('text-align',D.value);}}r.focus();r.forceNextSelectionCheck();s.selectBookmarks(u);}};j.add('justify',{init:function(r){var s=new p(r,'justifyleft','left'),t=new p(r,'justifycenter','center'),u=new p(r,'justifyright','right'),v=new p(r,'justifyblock','justify');r.addCommand('justifyleft',s);r.addCommand('justifycenter',t);r.addCommand('justifyright',u);r.addCommand('justifyblock',v);r.ui.addButton('JustifyLeft',{label:r.lang.justify.left,command:'justifyleft'});r.ui.addButton('JustifyCenter',{label:r.lang.justify.center,command:'justifycenter'});r.ui.addButton('JustifyRight',{label:r.lang.justify.right,command:'justifyright'});r.ui.addButton('JustifyBlock',{label:r.lang.justify.block,command:'justifyblock'});r.on('selectionChange',e.bind(o,s));r.on('selectionChange',e.bind(o,u));r.on('selectionChange',e.bind(o,t));r.on('selectionChange',e.bind(o,v));r.on('dirChanged',q);},requires:['domiterator']});})();j.add('keystrokes',{beforeInit:function(m){m.keystrokeHandler=new a.keystrokeHandler(m); +m.specialKeys={};},init:function(m){var n=m.config.keystrokes,o=m.config.blockedKeystrokes,p=m.keystrokeHandler.keystrokes,q=m.keystrokeHandler.blockedKeystrokes;for(var r=0;r7))O.append(J.createText('\xa0'));O.append(V.listNode);M=V.nextIndex;}else if(R.indent==-1&&!G&&R.grandparent){if(m[R.grandparent.getName()]){O=R.element.clone(false,true);P=R.element.getDirection(1);R.grandparent.getDirection(1)!=P&&O.setAttribute('dir',P);}else if(I||R.element.hasAttributes()||H!=2){O=J.createElement(Q);R.element.copyAttributes(O,{type:1,value:1});P=R.element.getDirection()||I;P&&O.setAttribute('dir',P);if(!I&&H==2&&!O.hasAttributes())O=new d.documentFragment(J);}else O=new d.documentFragment(J);for(S=0;SH[J-1].indent+1){var N=H[J-1].indent+1-H[J].indent,O=H[J].indent;while(H[J]&&H[J].indent>=O){H[J].indent+=N;J++;}J--;}}var P=j.list.arrayToList(H,G,null,E.config.enterMode,F.root.getAttribute('dir')),Q=P.listNode,R,S;function T(U){if((R=Q[U?'getFirst':'getLast']())&&!(R.is&&R.isBlockBoundary())&&(S=F.root[U?'getPrevious':'getNext'](d.walker.whitespaces(true)))&&!(S.is&&S.isBlockBoundary({br:1})))E.document.createElement('br')[U?'insertBefore':'insertAfter'](R);};T(true);T();Q.replace(F.root);};function w(E,F){this.name=E;this.type=F;};w.prototype={exec:function(E){var F=E.document,G=E.config,H=E.getSelection(),I=H&&H.getRanges(true);if(!I||I.length<1)return;if(this.state==2){var J=F.getBody();if(!J.getFirst(q)){G.enterMode==2?J.appendBogus():I[0].fixBlock(1,G.enterMode==1?'p':'div');H.selectRanges(I);}else{var K=I.length==1&&I[0],L=K&&K.getEnclosedNode(); +if(L&&L.is&&this.type==L.getName())this.setState(1);}}var M=H.createBookmarks(true),N=[],O={},P=I.createIterator(),Q=0;while((K=P.getNextRange())&&++Q){var R=K.getBoundaryNodes(),S=R.startNode,T=R.endNode;if(S.type==1&&S.getName()=='td')K.setStartAt(R.startNode,1);if(T.type==1&&T.getName()=='td')K.setEndAt(R.endNode,2);var U=K.createIterator(),V;U.forceBrBreak=this.state==2;while(V=U.getNextParagraph()){if(V.getCustomData('list_block'))continue;else h.setMarker(O,V,'list_block',1);var W=new d.elementPath(V),X=W.elements,Y=X.length,Z=null,aa=0,ab=W.blockLimit,ac;for(var ad=Y-1;ad>=0&&(ac=X[ad]);ad--){if(m[ac.getName()]&&ab.contains(ac)){ab.removeCustomData('list_group_object_'+Q);var ae=ac.getCustomData('list_group_object');if(ae)ae.contents.push(V);else{ae={root:ac,contents:[V]};N.push(ae);h.setMarker(O,ac,'list_group_object',ae);}aa=1;break;}}if(aa)continue;var af=ab;if(af.getCustomData('list_group_object_'+Q))af.getCustomData('list_group_object_'+Q).contents.push(V);else{ae={root:af,contents:[V]};h.setMarker(O,af,'list_group_object_'+Q,ae);N.push(ae);}}}var ag=[];while(N.length>0){ae=N.shift();if(this.state==2){if(m[ae.root.getName()])s.call(this,E,ae,O,ag);else u.call(this,E,ae,ag);}else if(this.state==1&&m[ae.root.getName()])v.call(this,E,ae,O);}for(ad=0;ad0)for(var u=t.length-1;u>=0;u--){var v=t[u][0],w=t[u][1];if(w)v.insertBefore(w);else v.appendTo(s);}};function o(s,t){var u=m(s),v={},w=s.$;if(!t){v['class']=w.className||'';w.className='';}v.inline=w.style.cssText||'';if(!t)w.style.cssText='position: static; overflow: visible';n(u);return v;};function p(s,t){var u=m(s),v=s.$;if('class' in t)v.className=t['class'];if('inline' in t)v.style.cssText=t.inline;n(u);};function q(s){var t=a.instances;for(var u in t){var v=t[u];if(v.mode=='wysiwyg'){var w=v.document.getBody();w.setAttribute('contentEditable',false);w.setAttribute('contentEditable',true);}}if(s.focusManager.hasFocus){s.toolbox.focus();s.focus();}};function r(s){if(!c||b.version>6)return null;var t=h.createFromHtml('');return s.append(t,true);};j.add('maximize',{init:function(s){var t=s.lang,u=a.document,v=u.getWindow(),w,x,y,z; +function A(){var C=v.getViewPaneSize();z&&z.setStyles({width:C.width+'px',height:C.height+'px'});s.resize(C.width,C.height,null,true);};var B=2;s.addCommand('maximize',{modes:{wysiwyg:1,source:1},editorFocus:false,exec:function(){var C=s.container.getChild(1),D=s.getThemeSpace('contents');if(s.mode=='wysiwyg'){var E=s.getSelection();w=E&&E.getRanges();x=v.getScrollPosition();}else{var F=s.textarea.$;w=!c&&[F.selectionStart,F.selectionEnd];x=[F.scrollLeft,F.scrollTop];}if(this.state==2){v.on('resize',A);y=v.getScrollPosition();var G=s.container;while(G=G.getParent()){G.setCustomData('maximize_saved_styles',o(G));G.setStyle('z-index',s.config.baseFloatZIndex-1);}D.setCustomData('maximize_saved_styles',o(D,true));C.setCustomData('maximize_saved_styles',o(C,true));var H={overflow:b.webkit?'':'hidden',width:0,height:0};u.getDocumentElement().setStyles(H);!b.gecko&&u.getDocumentElement().setStyle('position','fixed');!(b.gecko&&b.quirks)&&u.getBody().setStyles(H);c?setTimeout(function(){v.$.scrollTo(0,0);},0):v.$.scrollTo(0,0);C.setStyle('position',b.gecko&&b.quirks?'fixed':'absolute');C.$.offsetLeft;C.setStyles({'z-index':s.config.baseFloatZIndex-1,left:'0px',top:'0px'});z=r(C);C.addClass('cke_maximized');A();var I=C.getDocumentPosition();C.setStyles({left:-1*I.x+'px',top:-1*I.y+'px'});b.gecko&&q(s);}else if(this.state==1){v.removeListener('resize',A);var J=[D,C];for(var K=0;K ');o=m.createFakeElement(o,'cke_pagebreak','div');o.setAttributes({alt:n,'aria-label':n,title:n});var p=m.getSelection().getRanges(true);m.fire('saveSnapshot');for(var q,r=p.length-1;r>=0;r--){q=p[r];if(r1&&n.substr(n.length-1,1)=='%')n=parseInt(window.screen.width*parseInt(n,10)/100,10);if(typeof o=='string'&&o.length>1&&o.substr(o.length-1,1)=='%')o=parseInt(window.screen.height*parseInt(o,10)/100,10);if(n<640)n=640;if(o<420)o=420;var q=parseInt((window.screen.height-o)/2,10),r=parseInt((window.screen.width-n)/2,10);p=(p||'location=no,menubar=no,toolbar=no,dependent=yes,minimizable=no,modal=yes,alwaysRaised=yes,resizable=yes,scrollbars=yes')+',width='+n+',height='+o+',top='+q+',left='+r;var s=window.open('',null,p,true);if(!s)return false;try{s.moveTo(r,q);s.resizeTo(n,o);s.focus();s.location.href=m;}catch(t){s=window.open(m,null,p,true);}return true;}});(function(){var m={modes:{wysiwyg:1,source:1},canUndo:false,exec:function(o){var p,q=o.config,r=q.baseHref?'':'',s=b.isCustomDomain();if(q.fullPage)p=o.getData().replace(//,'$&'+r).replace(/[^>]*(?=<\/title>)/,'$& — '+o.lang.preview);else{var t=''+''+r+''+o.lang.preview+''+e.buildStyleHtml(o.config.contentsCss)+''+t+o.getData()+''; +}var v=640,w=420,x=80;try{var y=window.screen;v=Math.round(y.width*0.8);w=Math.round(y.height*0.7);x=Math.round(y.width*0.1);}catch(B){}var z='';if(s){window._cke_htmlToLoad=p;z='javascript:void( (function(){document.open();document.domain="'+document.domain+'";'+'document.write( window.opener._cke_htmlToLoad );'+'document.close();'+'window.opener._cke_htmlToLoad = null;'+'})() )';}var A=window.open(z,null,'toolbar=yes,location=no,status=yes,menubar=yes,scrollbars=yes,resizable=yes,width='+v+',height='+w+',left='+x);if(!s){A.document.open();A.document.write(p);A.document.close();}}},n='preview';j.add(n,{init:function(o){o.addCommand(n,m);o.ui.addButton('Preview',{label:o.lang.preview,command:n});}});})();j.add('print',{init:function(m){var n='print',o=m.addCommand(n,j.print);m.ui.addButton('Print',{label:m.lang.print,command:n});}});j.print={exec:function(m){if(b.opera)return;else if(b.gecko)m.window.$.print();else m.document.$.execCommand('Print');},canUndo:false,modes:{wysiwyg:!b.opera}};j.add('removeformat',{requires:['selection'],init:function(m){m.addCommand('removeFormat',j.removeformat.commands.removeformat);m.ui.addButton('RemoveFormat',{label:m.lang.removeFormat,command:'removeFormat'});m._.removeFormat={filters:[]};}});j.removeformat={commands:{removeformat:{exec:function(m){var n=m._.removeFormatRegex||(m._.removeFormatRegex=new RegExp('^(?:'+m.config.removeFormatTags.replace(/,/g,'|')+')$','i')),o=m._.removeAttributes||(m._.removeAttributes=m.config.removeFormatAttributes.split(',')),p=j.removeformat.filter,q=m.getSelection().getRanges(1),r=q.createIterator(),s;while(s=r.getNextRange()){if(!s.collapsed)s.enlarge(1);var t=s.createBookmark(),u=t.startNode,v=t.endNode,w,x=function(z){var A=new d.elementPath(z),B=A.elements;for(var C=1,D;D=B[C];C++){if(D.equals(A.block)||D.equals(A.blockLimit))break;if(n.test(D.getName())&&p(m,D))z.breakParent(D);}};x(u);if(v){x(v);w=u.getNextSourceNode(true,1);while(w){if(w.equals(v))break;var y=w.getNextSourceNode(false,1);if(!(w.getName()=='img'&&w.data('cke-realelement'))&&p(m,w))if(n.test(w.getName()))w.remove(1);else{w.removeAttributes(o);m.fire('removeFormatCleanup',w);}w=y;}}s.moveToBookmark(t);}m.getSelection().selectRanges(q);}}},filter:function(m,n){var o=m._.removeFormat.filters;for(var p=0;pr.width&&(n.resize_minWidth=r.width);n.resize_minHeight>r.height&&(n.resize_minHeight=r.height);a.document.on('mousemove',u);a.document.on('mouseup',v);if(m.document){m.document.on('mousemove',u);m.document.on('mouseup',v);}});m.on('destroy',function(){e.removeFunction(w);});m.on('themeSpace',function(x){if(x.data.space=='bottom'){var y='';if(s&&!t)y=' cke_resizer_horizontal';if(!s&&t)y=' cke_resizer_vertical';var z='
';o=='ltr'&&y=='ltr'?x.data.html+=z:x.data.html=z+x.data.html;}},m,null,100);}}});(function(){var m={modes:{wysiwyg:1,source:1},exec:function(o){var p=o.element.$.form;if(p)try{p.submit();}catch(q){if(p.submit.click)p.submit.click();}}},n='save';j.add(n,{init:function(o){var p=o.addCommand(n,m);p.modes={wysiwyg:!!o.element.$.form};o.ui.addButton('Save',{label:o.lang.save,command:n});}});})();(function(){var m='scaytcheck',n='';function o(t,u){var v=0,w;for(w in u){if(u[w]==t){v=1;break;}}return v;};var p=function(){var t=this,u=function(){var y=t.config,z={};z.srcNodeRef=t.document.getWindow().$.frameElement;z.assocApp='CKEDITOR.'+a.version+'@'+a.revision;z.customerid=y.scayt_customerid||'1:WvF0D4-UtPqN1-43nkD4-NKvUm2-daQqk3-LmNiI-z7Ysb4-mwry24-T8YrS3-Q2tpq2'; +z.customDictionaryIds=y.scayt_customDictionaryIds||'';z.userDictionaryName=y.scayt_userDictionaryName||'';z.sLang=y.scayt_sLang||'en_US';z.onLoad=function(){if(!(c&&b.version<8))this.addStyle(this.selectorCss(),'padding-bottom: 2px !important;');if(t.focusManager.hasFocus&&!q.isControlRestored(t))this.focus();};z.onBeforeChange=function(){if(q.getScayt(t)&&!t.checkDirty())setTimeout(function(){t.resetDirty();},0);};var A=window.scayt_custom_params;if(typeof A=='object')for(var B in A)z[B]=A[B];if(q.getControlId(t))z.id=q.getControlId(t);var C=new window.scayt(z);C.afterMarkupRemove.push(function(E){new h(E,C.document).mergeSiblings();});var D=q.instances[t.name];if(D){C.sLang=D.sLang;C.option(D.option());C.paused=D.paused;}q.instances[t.name]=C;try{C.setDisabled(q.isPaused(t)===false);}catch(E){}t.fire('showScaytState');};t.on('contentDom',u);t.on('contentDomUnload',function(){var y=a.document.getElementsByTag('script'),z=/^dojoIoScript(\d+)$/i,A=/^https?:\/\/svc\.spellchecker\.net\/spellcheck\/script\/ssrv\.cgi/i;for(var B=0;B=0){this.setState(0);q.loadEngine(t);}}};j.add('scayt',{requires:['menubutton'],beforeInit:function(t){var u=t.config.scayt_contextMenuItemsOrder||'suggest|moresuggest|control',v='';u=u.split('|');if(u&&u.length)for(var w=0;w tr > td, .%1 table.%2 > tr > th,','.%1 table.%2 > tbody > tr > td, .%1 table.%2 > tbody > tr > th,','.%1 table.%2 > thead > tr > td, .%1 table.%2 > thead > tr > th,','.%1 table.%2 > tfoot > tr > td, .%1 table.%2 > tfoot > tr > th','{','border : #d3d3d3 1px dotted','}']).join('');n=o.replace(/%2/g,m).replace(/%1/g,'cke_show_borders ');var p={preserveState:true,editorFocus:false,exec:function(q){this.toggleState();this.refresh(q);},refresh:function(q){var r=this.state==1?'addClass':'removeClass';q.document.getBody()[r]('cke_show_borders');}};j.add('showborders',{requires:['wysiwygarea'],modes:{wysiwyg:1},init:function(q){var r=q.addCommand('showborders',p);r.canUndo=false;if(q.config.startupShowBorders!==false)r.setState(1);q.addCss(n);q.on('mode',function(){if(r.state!=0)r.refresh(q);},null,null,100);q.on('contentDom',function(){if(r.state!=0)r.refresh(q);});q.on('removeFormatCleanup',function(s){var t=s.data;if(q.getCommand('showborders').state==1&&t.is('table')&&(!t.hasAttribute('border')||parseInt(t.getAttribute('border'),10)<=0))t.addClass(m);});},afterInit:function(q){var r=q.dataProcessor,s=r&&r.dataFilter,t=r&&r.htmlFilter;if(s)s.addRules({elements:{table:function(u){var v=u.attributes,w=v['class'],x=parseInt(v.border,10);if(!x||x<=0)v['class']=(w||'')+' '+m;}}});if(t)t.addRules({elements:{table:function(u){var v=u.attributes,w=v['class'];w&&(v['class']=w.replace(m,'').replace(/\s{2}/,' ').replace(/^\s+|\s+$/,''));}}});}});a.on('dialogDefinition',function(q){var r=q.data.name;if(r=='table'||r=='tableProperties'){var s=q.data.definition,t=s.getContents('info'),u=t.get('txtBorder'),v=u.commit;u.commit=e.override(v,function(y){return function(z,A){y.apply(this,arguments); +var B=parseInt(this.getValue(),10);A[!B||B<=0?'addClass':'removeClass'](m);};});var w=s.getContents('advanced'),x=w&&w.get('advCSSClasses');if(x){x.setup=e.override(x.setup,function(y){return function(){y.apply(this,arguments);this.setValue(this.getValue().replace(/cke_show_border/,''));};});x.commit=e.override(x.commit,function(y){return function(z,A){y.apply(this,arguments);if(!parseInt(A.getAttribute('border'),10))A.addClass('cke_show_border');};});}}});})();j.add('sourcearea',{requires:['editingblock'],init:function(m){var n=j.sourcearea,o=a.document.getWindow();m.on('editingBlockReady',function(){var p,q;m.addMode('source',{load:function(r,s){if(c&&b.version<8)r.setStyle('position','relative');m.textarea=p=new h('textarea');p.setAttributes({dir:'ltr',tabIndex:b.webkit?-1:m.tabIndex,role:'textbox','aria-label':m.lang.editorTitle.replace('%1',m.name)});p.addClass('cke_source');p.addClass('cke_enable_context_menu');var t={width:b.ie7Compat?'99%':'100%',height:'100%',resize:'none',outline:'none','text-align':'left'};if(c){q=function(){p.hide();p.setStyle('height',r.$.clientHeight+'px');p.setStyle('width',r.$.clientWidth+'px');p.show();};m.on('resize',q);o.on('resize',q);setTimeout(q,0);}r.setHtml('');r.append(p);p.setStyles(t);m.fire('ariaWidget',p);p.on('blur',function(){m.focusManager.blur();});p.on('focus',function(){m.focusManager.focus();});m.mayBeDirty=true;this.loadData(s);var u=m.keystrokeHandler;if(u)u.attach(p);setTimeout(function(){m.mode='source';m.fire('mode');},b.gecko||b.webkit?100:0);},loadData:function(r){p.setValue(r);m.fire('dataReady');},getData:function(){return p.getValue();},getSnapshotData:function(){return p.getValue();},unload:function(r){p.clearCustomData();m.textarea=p=null;if(q){m.removeListener('resize',q);o.removeListener('resize',q);}if(c&&b.version<8)r.removeStyle('position');},focus:function(){p.focus();}});});m.addCommand('source',n.commands.source);if(m.ui.addButton)m.ui.addButton('Source',{label:m.lang.source,command:'source'});m.on('mode',function(){m.getCommand('source').setState(m.mode=='source'?1:2);});}});j.sourcearea={commands:{source:{modes:{wysiwyg:1,source:1},editorFocus:false,exec:function(m){if(m.mode=='wysiwyg')m.fire('saveSnapshot');m.getCommand('source').setState(0);m.setMode(m.mode=='source'?'wysiwyg':'source');},canUndo:false}}};(function(){j.add('stylescombo',{requires:['richcombo','styles'],init:function(n){var o=n.config,p=n.lang.stylesCombo,q={},r=[];function s(t){n.getStylesSet(function(u){if(!r.length){var v,w; +for(var x=0,y=u.length;x0)return;if(T.type==1&&m.test(T.getName())&&!T.getCustomData('selected_cell')){h.setMarker(K,T,'selected_cell',true);J.push(T);}};for(var M=0;M1&&V&&U[Y]==V[Y]){Z=U[Y];Z.rowSpan+=1;}else{Z=new h(U[Y]).clone();Z.removeAttribute('rowSpan');!c&&Z.appendBogus();X.append(Z);Z=Z.$;}Y+=Z.colSpan-1;}H?X.insertBefore(S):X.insertAfter(S);};function q(G){if(G instanceof d.selection){var H=n(G),I=H[0],J=I.getAscendant('table'),K=e.buildTableMap(J),L=H[0].getParent(),M=L.$.rowIndex,N=H[H.length-1],O=N.getParent().$.rowIndex+N.$.rowSpan-1,P=[];for(var Q=M;Q<=O;Q++){var R=K[Q],S=new h(J.$.rows[Q]);for(var T=0;T=0;Q--)q(P[Q]);return Y;}else if(G instanceof h){J=G.getAscendant('table');if(J.$.rows.length==1)J.remove();else G.remove();}return null;};function r(G,H){var I=G.getParent(),J=I.$.cells,K=0;for(var L=0;LI)I=K;}return I;};function t(G,H){var I=n(G),J=I[0],K=J.getAscendant('table'),L=s(I,1),M=s(I),N=H?L:M,O=e.buildTableMap(K),P=[],Q=[],R=O.length; +for(var S=0;S1&&Q.length&&Q[S]==P[S]){U=P[S];U.colSpan+=1;}else{U=new h(P[S]).clone();U.removeAttribute('colSpan');!c&&U.appendBogus();U[H?'insertBefore':'insertAfter'].call(U,new h(P[S]));U=U.$;}S+=U.rowSpan-1;}};function u(G){var H=n(G),I=H[0],J=H[H.length-1],K=I.getAscendant('table'),L=e.buildTableMap(K),M,N,O=[];for(var P=0,Q=L.length;P1){L=H[J-1]+1;break;}}if(!L)L=H[0]>0?H[0]-1:H[H.length-1]+1;var N=I.$.rows;for(J=0,K=N.length;J=0;K--)x(H[K]);if(J)z(J,true);else if(I)I.remove();}else if(G instanceof h){var L=G.getParent();if(L.getChildCount()==1)L.remove();else G.remove();}};function y(G){var H=G.getBogus();H&&H.remove();G.trim();};function z(G,H){var I=new d.range(G.getDocument());if(!I['moveToElementEdit'+(H?'End':'Start')](G)){I.selectNodeContents(G);I.collapse(H?false:true);}I.select(true);};function A(G,H,I){var J=G[H];if(typeof I=='undefined')return J;for(var K=0;J&&K=Q)M.removeAttribute('rowSpan');else M.$.rowSpan=Y;if(Y>=P)M.removeAttribute('colSpan');else M.$.colSpan=Z;var ak=new d.nodeList(N.$.rows),al=ak.count();for(ac=al-1;ac>=0;ac--){var am=ak.getItem(ac);if(!am.$.cells.length){am.remove();al++;continue;}}return M;}else return Y*Z==ab;};function D(G,H){var I=n(G);if(I.length>1)return false;else if(H)return true;var J=I[0],K=J.getParent(),L=K.getAscendant('table'),M=e.buildTableMap(L),N=K.$.rowIndex,O=A(M,N,J),P=J.$.rowSpan,Q,R,S,T;if(P>1){R=Math.ceil(P/2);S=Math.floor(P/2);T=N+R;var U=new h(L.$.rows[T]),V=A(M,T),W;Q=J.clone();for(var X=0;XO){Q.insertBefore(new h(W));break;}else W=null;}if(!W)U.append(Q,true);}else{S=R=1;U=K.clone();U.insertAfter(K);U.append(Q=J.clone());var Y=A(M,N);for(var Z=0;Z1)return false;else if(H)return true;var J=I[0],K=J.getParent(),L=K.getAscendant('table'),M=e.buildTableMap(L),N=K.$.rowIndex,O=A(M,N,J),P=J.$.colSpan,Q,R,S;if(P>1){R=Math.ceil(P/2);S=Math.floor(P/2);}else{S=R=1;var T=B(M,O);for(var U=0;U0?2:0};}},tablecell_insertBefore:{label:H.cell.insertBefore,group:'tablecell',command:'cellInsertBefore',order:5},tablecell_insertAfter:{label:H.cell.insertAfter,group:'tablecell',command:'cellInsertAfter',order:10},tablecell_delete:{label:H.cell.deleteCell,group:'tablecell',command:'cellDelete',order:15},tablecell_merge:{label:H.cell.merge,group:'tablecell',command:'cellMerge',order:16},tablecell_merge_right:{label:H.cell.mergeRight,group:'tablecell',command:'cellMergeRight',order:17},tablecell_merge_down:{label:H.cell.mergeDown,group:'tablecell',command:'cellMergeDown',order:18},tablecell_split_horizontal:{label:H.cell.splitHorizontal,group:'tablecell',command:'cellHorizontalSplit',order:19},tablecell_split_vertical:{label:H.cell.splitVertical,group:'tablecell',command:'cellVerticalSplit',order:20},tablecell_properties:{label:H.cell.title,group:'tablecellproperties',command:'cellProperties',order:21},tablerow:{label:H.row.menu,group:'tablerow',order:1,getItems:function(){return{tablerow_insertBefore:2,tablerow_insertAfter:2,tablerow_delete:2}; +}},tablerow_insertBefore:{label:H.row.insertBefore,group:'tablerow',command:'rowInsertBefore',order:5},tablerow_insertAfter:{label:H.row.insertAfter,group:'tablerow',command:'rowInsertAfter',order:10},tablerow_delete:{label:H.row.deleteRow,group:'tablerow',command:'rowDelete',order:15},tablecolumn:{label:H.column.menu,group:'tablecolumn',order:1,getItems:function(){return{tablecolumn_insertBefore:2,tablecolumn_insertAfter:2,tablecolumn_delete:2};}},tablecolumn_insertBefore:{label:H.column.insertBefore,group:'tablecolumn',command:'columnInsertBefore',order:5},tablecolumn_insertAfter:{label:H.column.insertAfter,group:'tablecolumn',command:'columnInsertAfter',order:10},tablecolumn_delete:{label:H.column.deleteColumn,group:'tablecolumn',command:'columnDelete',order:15}});if(G.contextMenu)G.contextMenu.addListener(function(I,J){if(!I||I.isReadOnly())return null;while(I){if(I.getName() in F)return{tablecell:2,tablerow:2,tablecolumn:2};I=I.getParent();}return null;});},getSelectedCells:n};j.add('tabletools',j.tabletools);})();e.buildTableMap=function(m){var n=m.$.rows,o=-1,p=[];for(var q=0;qp&&(!s||!t||vt){s=v;t=u;}}else{if(q&&u==p){s=v;break;}if(ut)){s=v;t=u;}}}if(s)s.focus();};(function(){j.add('templates',{requires:['dialog'],init:function(o){a.dialog.add('templates',a.getUrl(this.path+'dialogs/templates.js'));o.addCommand('templates',new a.dialogCommand('templates'));o.ui.addButton('Templates',{label:o.lang.templates.button,command:'templates'});}});var m={},n={};a.addTemplates=function(o,p){m[o]=p;};a.getTemplates=function(o){return m[o];};a.loadTemplates=function(o,p){var q=[];for(var r=0,s=o.length;r':' style="display:none">');s.push('',o.lang.toolbar,'');var v=o.toolbox.toolbars,w=o.config.toolbar instanceof Array?o.config.toolbar:o.config['toolbar_'+o.config.toolbar]; for(var x=0;x');u=0;}if(y==='/'){s.push('
');continue;}s.push('');var B=v.push(A)-1;if(B>0){A.previous=v[B-1];A.previous.next=A;}for(var C=0;C');u=1;}}else if(u){s.push('');u=0;}var F=D.render(o,s);B=A.items.push(F)-1;if(B>0){F.previous=A.items[B-1];F.previous.next=F;}F.toolbar=A;F.onkey=p;F.onfocus=function(){if(!o.toolbox.focusCommandExecuted)o.focus();};}}if(u){s.push('');u=0;}s.push('');}s.push('');if(o.config.toolbarCanCollapse){var G=e.addFunction(function(){o.execCommand('toolbarCollapse');});o.on('destroy',function(){e.removeFunction(G);});var H=e.getNextId();o.addCommand('toolbarCollapse',{exec:function(I){var J=a.document.getById(H),K=J.getPrevious(),L=I.getThemeSpace('contents'),M=K.getParent(),N=parseInt(L.$.style.height,10),O=M.$.offsetHeight,P=!K.isVisible();if(!P){K.hide();J.addClass('cke_toolbox_collapser_min');J.setAttribute('title',I.lang.toolbarExpand);}else{K.show();J.removeClass('cke_toolbox_collapser_min');J.setAttribute('title',I.lang.toolbarCollapse);}J.getFirst().setText(P?'▲':'◀');var Q=M.$.offsetHeight-O;L.setStyle('height',N-Q+'px');I.fire('resize');},modes:{wysiwyg:1,source:1}});s.push('','','');}q.data.html+=s.join('');}});o.on('destroy',function(){var q,r=0,s,t,u;q=this.toolbox.toolbars;for(;r');return{};}};i.toolbarLocation='top';i.toolbar_Basic=[['Bold','Italic','-','NumberedList','BulletedList','-','Link','Unlink','-','About']];i.toolbar_Full=[['Source','-','Save','NewPage','Preview','-','Templates'],['Cut','Copy','Paste','PasteText','PasteFromWord','-','Print','SpellChecker','Scayt'],['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],['Form','Checkbox','Radio','TextField','Textarea','Select','Button','ImageButton','HiddenField'],'/',['Bold','Italic','Underline','Strike','-','Subscript','Superscript'],['NumberedList','BulletedList','-','Outdent','Indent','Blockquote','CreateDiv'],['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],['BidiLtr','BidiRtl'],['Link','Unlink','Anchor'],['Image','Flash','Table','HorizontalRule','Smiley','SpecialChar','PageBreak','Iframe'],'/',['Styles','Format','Font','FontSize'],['TextColor','BGColor'],['Maximize','ShowBlocks','-','About']]; -i.toolbar='Full';i.toolbarCanCollapse=true;(function(){j.add('undo',{requires:['selection','wysiwygarea'],init:function(s){var t=new o(s),u=s.addCommand('undo',{exec:function(){if(t.undo()){s.selectionChange();this.fire('afterUndo');}},state:0,canUndo:false}),v=s.addCommand('redo',{exec:function(){if(t.redo()){s.selectionChange();this.fire('afterRedo');}},state:0,canUndo:false});t.onChange=function(){u.setState(t.undoable()?2:0);v.setState(t.redoable()?2:0);};function w(x){if(t.enabled&&x.data.command.canUndo!==false)t.save();};s.on('beforeCommandExec',w);s.on('afterCommandExec',w);s.on('saveSnapshot',function(){t.save();});s.on('contentDom',function(){s.document.on('keydown',function(x){if(!x.data.$.ctrlKey&&!x.data.$.metaKey)t.type(x);});});s.on('beforeModeUnload',function(){s.mode=='wysiwyg'&&t.save(true);});s.on('mode',function(){t.enabled=s.mode=='wysiwyg';t.onChange();});s.ui.addButton('Undo',{label:s.lang.undo,command:'undo'});s.ui.addButton('Redo',{label:s.lang.redo,command:'redo'});s.resetUndo=function(){t.reset();s.fire('saveSnapshot');};s.on('updateSnapshot',function(){if(t.currentImage&&new m(s).equals(t.currentImage))setTimeout(function(){t.update();},0);});}});j.undo={};var m=j.undo.Image=function(s){this.editor=s;var t=s.getSnapshot(),u=t&&s.getSelection();c&&t&&(t=t.replace(/\s+data-cke-expando=".*?"/g,''));this.contents=t;this.bookmarks=u&&u.createBookmarks2(true);},n=/\b(?:href|src|name)="[^"]*?"/gi;m.prototype={equals:function(s,t){var u=this.contents,v=s.contents;if(c&&(b.ie7Compat||b.ie6Compat)){u=u.replace(n,'');v=v.replace(n,'');}if(u!=v)return false;if(t)return true;var w=this.bookmarks,x=s.bookmarks;if(w||x){if(!w||!x||w.length!=x.length)return false;for(var y=0;y25){this.save(false,null,false);this.modifiersCount=1;}}else if(!y){this.modifiersCount=0;this.typesCount++;if(this.typesCount>25){this.save(false,null,false);this.typesCount=1;}}},reset:function(){var s=this;s.lastKeystroke=0;s.snapshots=[];s.index=-1;s.limit=s.editor.config.undoStackSize||20;s.currentImage=null;s.hasUndo=false;s.hasRedo=false;s.resetType();},resetType:function(){var s=this;s.typing=false;delete s.lastKeystroke;s.typesCount=0;s.modifiersCount=0;},fireChange:function(){var s=this;s.hasUndo=!!s.getNextImage(true);s.hasRedo=!!s.getNextImage(false);s.resetType();s.onChange();},save:function(s,t,u){var w=this;var v=w.snapshots;if(!t)t=new m(w.editor);if(t.contents===false)return false;if(w.currentImage&&t.equals(w.currentImage,s))return false;v.splice(w.index+1,v.length-w.index-1);if(v.length==w.limit)v.shift();w.index=v.push(t)-1;w.currentImage=t;if(u!==false)w.fireChange();return true;},restoreImage:function(s){var u=this;u.editor.loadSnapshot(s.contents);if(s.bookmarks)u.editor.getSelection().selectBookmarks(s.bookmarks);else if(c){var t=u.editor.document.getBody().$.createTextRange();t.collapse(true);t.select();}u.index=s.index;u.update();u.fireChange();},getNextImage:function(s){var x=this;var t=x.snapshots,u=x.currentImage,v,w;if(u)if(s)for(w=x.index-1;w>=0;w--){v=t[w];if(!u.equals(v,true)){v.index=w;return v;}}else for(w=x.index+1;w]*>)\s*<(p|div|address|h\d|center)[^>]*>\s*(?:]*>| |\u00A0| )?\s*(:?<\/\2>)?\s*(?=$|<\/body>)/gi,o=d.walker.whitespaces(true);function p(D){return D.getName() in m||D.isBlockBoundary()&&f.$empty[D.getName()];};function q(D){return function(E){if(this.mode=='wysiwyg'){this.focus();this.fire('saveSnapshot');D.call(this,E.data);e.setTimeout(function(){this.fire('saveSnapshot'); -},0,this);}};};function r(D){var J=this;if(J.dataProcessor)D=J.dataProcessor.toHtml(D);var E=J.getSelection(),F=E.getRanges()[0];if(F.checkReadOnly())return;if(c){var G=E.isLocked;if(G)E.unlock();var H=E.getNative();if(H.type=='Control')H.clear();else if(E.getType()==2){F=E.getRanges()[0];var I=F&&F.endContainer;if(I&&I.type==1&&I.getAttribute('contenteditable')=='false'&&F.checkBoundaryOfElement(I,2)){F.setEndAfter(F.endContainer);F.deleteContents();}}try{H.createRange().pasteHTML(D);}catch(K){}if(G)J.getSelection().lock();}else J.document.$.execCommand('inserthtml',false,D);if(b.webkit){E=J.getSelection();E.scrollIntoView();}};function s(D){var E=this.getSelection(),F=E.getStartElement().hasAscendant('pre',true)?2:this.config.enterMode,G=F==2,H=e.htmlEncode(D.replace(/\r\n|\r/g,'\n'));H=H.replace(/^[ \t]+|[ \t]+$/g,function(N,O,P){if(N.length==1)return ' ';else if(!O)return e.repeat(' ',N.length-1)+' ';else return ' '+e.repeat(' ',N.length-1);});H=H.replace(/[ \t]{2,}/g,function(N){return e.repeat(' ',N.length-1)+' ';});var I=F==1?'p':'div';if(!G)H=H.replace(/(\n{2})([\s\S]*?)(?:$|\1)/g,function(N,O,P){return '<'+I+'>'+P+'';});H=H.replace(/\n/g,'
');if(!(G||c))H=H.replace(new RegExp('
(?=)'),function(N){return e.repeat(N,2);});if(b.gecko||b.webkit){var J=new d.elementPath(E.getStartElement()),K=[];for(var L=0;L/));else if(M in f.$block)break;}H=K.join('')+H;}r.call(this,H);};function t(D){var E=this.getSelection(),F=E.getRanges(),G=D.getName(),H=f.$block[G],I=E.isLocked;if(I)E.unlock();var J,K,L,M;for(var N=F.length-1;N>=0;N--){J=F[N];if(!J.checkReadOnly()){J.deleteContents(1);K=!N&&D||D.clone(1);var O,P;if(H)while((O=J.getCommonAncestor(0,1))&&(P=f[O.getName()])&&!(P&&P[G])){if(O.getName() in f.span)J.splitElement(O);else if(J.checkStartOfBlock()&&J.checkEndOfBlock()){J.setStartBefore(O);J.collapse(true);O.remove();}else J.splitBlock();}J.insertNode(K);if(!L)L=K;}}if(L){J.moveToPosition(L,4);if(H){var Q=L.getNext(o),R=Q&&Q.type==1&&Q.getName();if(R&&f.$block[R]&&f[R]['#'])J.moveToElementEditStart(Q);}}E.selectRanges([J]);if(I)this.getSelection().lock();};function u(D){if(!D.checkDirty())setTimeout(function(){D.resetDirty();},0);};var v=d.walker.whitespaces(true),w=d.walker.bookmark(false,true);function x(D){return v(D)&&w(D);};function y(D){return D.type==3&&e.trim(D.getText()).match(/^(?: |\xa0)$/); -};function z(D){if(D.isLocked){D.unlock();setTimeout(function(){D.lock();},0);}};function A(D){return D.getOuterHtml().match(n);};v=d.walker.whitespaces(true);function B(D){var E=D.window,F=D.document,G=D.document.getBody(),H=G.getChildren().count();if(!H||H==1&&G.getFirst().hasAttribute('_moz_editor_bogus_node')){u(D);var I=D.element.getDocument(),J=I.getDocumentElement(),K=J.$.scrollTop,L=J.$.scrollLeft,M=F.$.createEvent('KeyEvents');M.initKeyEvent('keypress',true,true,E.$,false,false,false,false,0,32);F.$.dispatchEvent(M);if(K!=J.$.scrollTop||L!=J.$.scrollLeft)I.getWindow().$.scrollTo(L,K);H&&G.getFirst().remove();F.getBody().appendBogus();var N=new d.range(F);N.setStartAt(G,1);N.select();}};function C(D){var E=D.editor,F=D.data.path,G=F.blockLimit,H=D.data.selection,I=H.getRanges()[0],J=E.document.getBody(),K=E.config.enterMode;if(b.gecko){B(E);var L=F.block||F.blockLimit;if(L&&!L.getBogus()){E.fire('updateSnapshot');u(E);L.appendBogus();}}if(K!=2&&I.collapsed&&G.getName()=='body'&&!F.block){E.fire('updateSnapshot');u(E);c&&z(H);var M=I.fixBlock(true,E.config.enterMode==3?'div':'p');if(c){var N=M.getFirst(x);N&&y(N)&&N.remove();}if(A(M)){var O=M.getNext(v);if(O&&O.type==1&&!p(O)){I.moveToElementEditStart(O);M.remove();}else{O=M.getPrevious(v);if(O&&O.type==1&&!p(O)){I.moveToElementEditEnd(O);M.remove();}}}I.select();if(!c){E.forceNextSelectionCheck();E.selectionChange();}}var P=new d.range(E.document),Q=new d.walker(P);P.selectNodeContents(J);Q.evaluator=function(S){return S.type==1&&S.getName() in m;};Q.guard=function(S,T){return!(S.type==3&&v(S)||T);};if(Q.previous()){E.fire('updateSnapshot');u(E);c&&z(H);var R;if(K!=2)R=J.append(new h(K==1?'p':'div'));else R=J;if(!c)R.appendBogus();}};j.add('wysiwygarea',{requires:['editingblock'],init:function(D){var E=D.config.enterMode!=2?D.config.enterMode==3?'div':'p':false,F=D.lang.editorTitle.replace('%1',D.name),G;D.on('editingBlockReady',function(){var M,N,O,P,Q,R,S=b.isCustomDomain(),T=function(W){if(N)N.remove();var X='document.open();'+(S?'document.domain="'+document.domain+'";':'')+'document.close();';X=b.air?'javascript:void(0)':c?'javascript:void(function(){'+encodeURIComponent(X)+'}())':'';N=h.createFromHtml('');if(document.location.protocol=='chrome:')a.event.useCapture=true;N.on('load',function(ab){Q=1;ab.removeListener();var ac=N.getFrameDocument(); -ac.write(W);b.air&&V(ac.getWindow().$);});if(document.location.protocol=='chrome:')a.event.useCapture=false;var Y=D.element,Z=b.gecko&&!Y.isVisible(),aa={};if(Z){Y.show();aa={position:Y.getStyle('position'),top:Y.getStyle('top')};Y.setStyles({position:'absolute',top:'-3000px'});}M.append(N);if(Z)setTimeout(function(){Y.hide();Y.setStyles(aa);},1000);};G=e.addFunction(V);var U='';function V(W){if(!Q)return;Q=0;D.fire('ariaWidget',N);var X=W.document,Y=X.body,Z=X.getElementById('cke_actscrpt');Z&&Z.parentNode.removeChild(Z);Y.spellcheck=!D.config.disableNativeSpellChecker;if(c){Y.hideFocus=true;Y.disabled=true;Y.contentEditable=true;Y.removeAttribute('disabled');}else setTimeout(function(){if(b.gecko&&b.version>=10900||b.opera)X.$.body.contentEditable=true;else if(b.webkit)X.$.body.parentNode.contentEditable=true;else X.$.designMode='on';},0);b.gecko&&e.setTimeout(B,0,null,D);W=D.window=new d.window(W);X=D.document=new g(X);X.on('dblclick',function(af){var ag=af.data.getTarget(),ah={element:ag,dialog:''};D.fire('doubleclick',ah);ah.dialog&&D.openDialog(ah.dialog);});c&&X.on('click',function(af){var ag=af.data.getTarget();if(ag.is('input')){var ah=ag.getAttribute('type');if(ah=='submit'||ah=='reset')af.data.preventDefault();}});if(!(c||b.opera))X.on('mousedown',function(af){var ag=af.data.getTarget();if(ag.is('img','hr','input','textarea','select'))D.getSelection().selectElement(ag);});if(b.gecko)X.on('mouseup',function(af){if(af.data.$.button==2){var ag=af.data.getTarget();if(!ag.getOuterHtml().replace(n,'')){var ah=new d.range(X);ah.moveToElementEditStart(ag);ah.select(true);}}});X.on('click',function(af){af=af.data;if(af.getTarget().is('a')&&af.$.button!=2)af.preventDefault();});if(b.webkit){X.on('click',function(af){if(af.data.getTarget().is('input','select'))af.data.preventDefault();});X.on('mouseup',function(af){if(af.data.getTarget().is('input','textarea'))af.data.preventDefault();});}if(c&&X.$.compatMode=='CSS1Compat'||b.gecko||b.opera){var aa=X.getDocumentElement();aa.on('mousedown',function(af){if(af.data.getTarget().equals(aa)){if(b.gecko&&b.version>=10900)K();L.focus();}});}var ab=c?N:W;ab.on('blur',function(){D.focusManager.blur();});var ac;ab.on('focus',function(){var af=D.document;if(b.gecko&&b.version>=10900)K();else if(b.opera)af.getBody().focus();else if(b.webkit)if(!ac){D.document.getDocumentElement().focus(); -ac=1;}D.focusManager.focus();});var ad=D.keystrokeHandler;if(ad)ad.attach(X);if(c){X.getDocumentElement().addClass(X.$.compatMode);X.on('keydown',function(af){var ag=af.data.getKeystroke();if(ag in {8:1,46:1}){var ah=D.getSelection(),ai=ah.getSelectedElement();if(ai){D.fire('saveSnapshot');var aj=ah.getRanges()[0].createBookmark();ai.remove();ah.selectBookmarks([aj]);D.fire('saveSnapshot');af.data.preventDefault();}}});if(X.$.compatMode=='CSS1Compat'){var ae={33:1,34:1};X.on('keydown',function(af){if(af.data.getKeystroke() in ae)setTimeout(function(){D.getSelection().scrollIntoView();},0);});}}if(D.contextMenu)D.contextMenu.addTarget(X,D.config.browserContextMenuOnCtrl!==false);setTimeout(function(){D.fire('contentDom');if(R){D.mode='wysiwyg';D.fire('mode');R=false;}O=false;if(P){D.focus();P=false;}setTimeout(function(){D.fire('dataReady');},0);try{D.document.$.execCommand('enableInlineTableEditing',false,!D.config.disableNativeTableHandles);}catch(af){}if(D.config.disableObjectResizing)try{D.document.$.execCommand('enableObjectResizing',false,false);}catch(ag){D.document.getBody().on(c?'resizestart':'resize',function(ah){ah.data.preventDefault();});}if(c)setTimeout(function(){if(D.document){var ah=D.document.$.body;ah.runtimeStyle.marginBottom='0px';ah.runtimeStyle.marginBottom='';}},1000);},0);};D.addMode('wysiwyg',{load:function(W,X,Y){M=W;if(c&&b.quirks)W.setStyle('position','relative');D.mayBeDirty=true;R=true;if(Y)this.loadSnapshotData(X);else this.loadData(X);},loadData:function(W){O=true;var X=D.config,Y=X.fullPage,Z=X.docType,aa='';!Y&&(aa=e.buildStyleHtml(D.config.contentsCss)+aa);var ab=X.baseHref?'':'';if(Y)W=W.replace(/]*>/i,function(ac){D.docType=Z=ac;return '';});if(D.dataProcessor)W=D.dataProcessor.toHtml(W,E);if(Y){if(!/]/.test(W))W=''+W;if(!/]/.test(W))W=''+W+'';if(!/]/.test(W))W=W.replace(/]*>/,'$&');else if(!/]/.test(W))W=W.replace(/]*>/,'$&');ab&&(W=W.replace(//,'$&'+ab));W=W.replace(/<\/head\s*>/,aa+'$&');W=Z+W;}else W=X.docType+''+''+''+F+''+ab+aa+''+''+W+'';W+=U;this.onDispose(); -T(W);},getData:function(){var W=D.config,X=W.fullPage,Y=X&&D.docType,Z=N.getFrameDocument(),aa=X?Z.getDocumentElement().getOuterHtml():Z.getBody().getHtml();if(D.dataProcessor)aa=D.dataProcessor.toDataFormat(aa,E);if(W.ignoreEmptyParagraph)aa=aa.replace(n,function(ab,ac){return ac;});if(Y)aa=Y+'\n'+aa;return aa;},getSnapshotData:function(){return N.getFrameDocument().getBody().getHtml();},loadSnapshotData:function(W){N.getFrameDocument().getBody().setHtml(W);},onDispose:function(){if(!D.document)return;D.document.getDocumentElement().clearCustomData();D.document.getBody().clearCustomData();D.window.clearCustomData();D.document.clearCustomData();N.clearCustomData();N.remove();},unload:function(W){this.onDispose();D.window=D.document=N=M=P=null;D.fire('contentDomUnload');},focus:function(){var W=D.window;if(O)P=true;else if(b.opera&&D.document){var X=D.window.$.frameElement;X.blur(),X.focus();D.document.getBody().focus();D.selectionChange();}else if(!b.opera&&W){b.air?setTimeout(function(){W.focus();},0):W.focus();D.selectionChange();}}});D.on('insertHtml',q(r),null,null,20);D.on('insertElement',q(t),null,null,20);D.on('insertText',q(s),null,null,20);D.on('selectionChange',C,null,null,1);});var H;D.on('contentDom',function(){var M=D.document.getElementsByTag('title').getItem(0);M.data('cke-title',D.document.$.title);D.document.$.title=F;});if(a.document.$.documentMode>=8){D.addCss('html.CSS1Compat [contenteditable=false]{ min-height:0 !important;}');var I=[];for(var J in f.$removeEmpty)I.push('html.CSS1Compat '+J+'[contenteditable=false]');D.addCss(I.join(',')+'{ display:inline-block;}');}else if(b.gecko)D.addCss('html { height: 100% !important; }');function K(M){e.tryThese(function(){D.document.$.designMode='on';setTimeout(function(){D.document.$.designMode='off';if(a.currentInstance==D)D.document.getBody().focus();},50);},function(){D.document.$.designMode='off';var N=D.document.getBody();N.setAttribute('contentEditable',false);N.setAttribute('contentEditable',true);!M&&K(1);});};if(b.gecko||c||b.opera){var L;D.on('uiReady',function(){L=D.container.append(h.createFromHtml(''));L.on('focus',function(){D.focus();});D.focusGrabber=L;});D.on('destroy',function(){e.removeFunction(G);L.clearCustomData();delete D.focusGrabber;});}D.on('insertElement',function(M){var N=M.data;if(N.type==1&&(N.is('input')||N.is('textarea'))){if(!N.isReadOnly())N.data('cke-editable',N.hasAttribute('contenteditable')?'true':'1'); -N.setAttribute('contentEditable',false);}});}});if(b.gecko)(function(){var D=document.body;if(!D)window.addEventListener('load',arguments.callee,false);else{var E=D.getAttribute('onpageshow');D.setAttribute('onpageshow',(E?E+';':'')+'event.persisted && (function(){'+'var allInstances = CKEDITOR.instances, editor, doc;'+'for ( var i in allInstances )'+'{'+'\teditor = allInstances[ i ];'+'\tdoc = editor.document;'+'\tif ( doc )'+'\t{'+'\t\tdoc.$.designMode = "off";'+'\t\tdoc.$.designMode = "on";'+'\t}'+'}'+'})();');}})();})();i.disableObjectResizing=false;i.disableNativeTableHandles=true;i.disableNativeSpellChecker=true;i.ignoreEmptyParagraph=true;j.add('wsc',{requires:['dialog'],init:function(m){var n='checkspell',o=m.addCommand(n,new a.dialogCommand(n));o.modes={wysiwyg:!b.opera&&!b.air&&document.domain==window.location.hostname};m.ui.addButton('SpellChecker',{label:m.lang.spellCheck.toolbar,command:n});a.dialog.add(n,this.path+'dialogs/wsc.js');}});i.wsc_customerId=i.wsc_customerId||'1:ua3xw1-2XyGJ3-GWruD3-6OFNT1-oXcuB1-nR6Bp4-hgQHc-EcYng3-sdRXG3-NOfFk';i.wsc_customLoaderScript=i.wsc_customLoaderScript||null;a.DIALOG_RESIZE_NONE=0;a.DIALOG_RESIZE_WIDTH=1;a.DIALOG_RESIZE_HEIGHT=2;a.DIALOG_RESIZE_BOTH=3;(function(){var m=e.cssLength;function n(P){return!!this._.tabs[P][0].$.offsetHeight;};function o(){var T=this;var P=T._.currentTabId,Q=T._.tabIdList.length,R=e.indexOf(T._.tabIdList,P)+Q;for(var S=R-1;S>R-Q;S--){if(n.call(T,T._.tabIdList[S%Q]))return T._.tabIdList[S%Q];}return null;};function p(){var T=this;var P=T._.currentTabId,Q=T._.tabIdList.length,R=e.indexOf(T._.tabIdList,P);for(var S=R+1;S1){ab._.tabBarMode=true;ab._.tabs[ab._.currentTabId][0].focus();af=1;}else if((ao==37||ao==39)&&ab._.tabBarMode){ar=ao==(ap?39:37)?o.call(ab):p.call(ab);ab.selectPage(ar);ab._.tabs[ar][0].focus();af=1;}else if((ao==13||ao==32)&&ab._.tabBarMode){as.selectPage(as._.currentTabId);as._.tabBarMode=false;as._.currentFocusIndex=-1;ae(true);af=1;}if(af){an.stop();an.data.preventDefault();}};function ah(an){af&&an.data.preventDefault();};var ai=this._.element;this.on('show',function(){ai.on('keydown',ag,this,null,0);if(b.opera||b.gecko&&b.mac)ai.on('keypress',ah,this);});this.on('hide',function(){ai.removeListener('keydown',ag);if(b.opera||b.gecko&&b.mac)ai.removeListener('keypress',ah);});this.on('iframeAdded',function(an){var ao=new g(an.data.iframe.$.contentWindow.document);ao.on('keydown',ag,this,null,0);});this.on('show',function(){var ar=this;ad();if(P.config.dialog_startupFocusTab&&ab._.pageCount>1){ab._.tabBarMode=true;ab._.tabs[ab._.currentTabId][0].focus();}else if(!ar._.hasFocus){ar._.currentFocusIndex=-1;if(R.onFocus){var an=R.onFocus.call(ar);an&&an.focus();}else ae(true);if(ar._.editor.mode=='wysiwyg'&&c){var ao=P.document.$.selection,ap=ao.createRange();if(ap)if(ap.parentElement&&ap.parentElement().ownerDocument==P.document.$||ap.item&&ap.item(0).ownerDocument==P.document.$){var aq=document.body.createTextRange();aq.moveToElementText(ar.getElement().getFirst().$);aq.collapse(true);aq.select();}}}},this,null,4294967295);if(b.ie6Compat)this.on('load',function(an){var ao=this.getElement(),ap=ao.getFirst();ap.remove();ap.appendTo(ao);},this);y(this);z(this);new d.text(R.title,a.document).appendTo(this.parts.title);for(var aj=0;aj0?Q:0)+'px',top:(R>0?R:0)+'px'});S&&(V._.moved=1);};})(),getPosition:function(){return e.extend({},this._.position);},show:function(){var P=this._.element,Q=this.definition;if(!(P.getParent()&&P.getParent().equals(a.document.getBody())))P.appendTo(a.document.getBody());else P.setStyle('display','block');if(b.gecko&&b.version<10900){var R=this.parts.dialog;R.setStyle('position','absolute');setTimeout(function(){R.setStyle('position','fixed');},0);}this.resize(this._.contentSize&&this._.contentSize.width||Q.minWidth,this._.contentSize&&this._.contentSize.height||Q.minHeight);this.reset();this.selectPage(this.definition.contents[0].id);if(a.dialog._.currentZIndex===null)a.dialog._.currentZIndex=this._.editor.config.baseFloatZIndex;this._.element.getFirst().setStyle('z-index',a.dialog._.currentZIndex+=10);if(a.dialog._.currentTop===null){a.dialog._.currentTop=this;this._.parentDialog=null;D(this._.editor);P.on('keydown',H);P.on(b.opera?'keypress':'keyup',I);for(var S in {keyup:1,keydown:1,keypress:1})P.on(S,O);}else{this._.parentDialog=a.dialog._.currentTop;var T=this._.parentDialog.getElement().getFirst();T.$.style.zIndex-=Math.floor(this._.editor.config.baseFloatZIndex/2);a.dialog._.currentTop=this;}J(this,this,'\x1b',null,function(){this.getButton('cancel')&&this.getButton('cancel').click();});this._.hasFocus=false;e.setTimeout(function(){this.layout();this.parts.dialog.setStyle('visibility','');this.fireOnce('load',{});k.fire('ready',this); -this.fire('show',{});this._.editor.fire('dialogShow',this);this.foreach(function(U){U.setInitValue&&U.setInitValue();});},100,this);},layout:function(){var R=this;var P=a.document.getWindow().getViewPaneSize(),Q=R.getSize();R.move(R._.moved?R._.position.x:(P.width-Q.width)/2,R._.moved?R._.position.y:(P.height-Q.height)/2);},foreach:function(P){var S=this;for(var Q in S._.contents)for(var R in S._.contents[Q])P(S._.contents[Q][R]);return S;},reset:(function(){var P=function(Q){if(Q.reset)Q.reset(1);};return function(){this.foreach(P);return this;};})(),setupContent:function(){var P=arguments;this.foreach(function(Q){if(Q.setup)Q.setup.apply(Q,P);});},commitContent:function(){var P=arguments;this.foreach(function(Q){if(Q.commit)Q.commit.apply(Q,P);});},hide:function(){if(!this.parts.dialog.isVisible())return;this.fire('hide',{});this._.editor.fire('dialogHide',this);var P=this._.element;P.setStyle('display','none');this.parts.dialog.setStyle('visibility','hidden');K(this);while(a.dialog._.currentTop!=this)a.dialog._.currentTop.hide();if(!this._.parentDialog)E();else{var Q=this._.parentDialog.getElement().getFirst();Q.setStyle('z-index',parseInt(Q.$.style.zIndex,10)+Math.floor(this._.editor.config.baseFloatZIndex/2));}a.dialog._.currentTop=this._.parentDialog;if(!this._.parentDialog){a.dialog._.currentZIndex=null;P.removeListener('keydown',H);P.removeListener(b.opera?'keypress':'keyup',I);for(var R in {keyup:1,keydown:1,keypress:1})P.removeListener(R,O);var S=this._.editor;S.focus();if(S.mode=='wysiwyg'&&c){var T=S.getSelection();T&&T.unlock(true);}}else a.dialog._.currentZIndex-=10;delete this._.parentDialog;this.foreach(function(U){U.resetInitValue&&U.resetInitValue();});},addPage:function(P){var ab=this;var Q=[],R=P.label?' title="'+e.htmlEncode(P.label)+'"':'',S=P.elements,T=a.dialog._.uiElementBuilders.vbox.build(ab,{type:'vbox',className:'cke_dialog_page_contents',children:P.elements,expand:!!P.expand,padding:P.padding,style:P.style||'width: 100%;'},Q),U=h.createFromHtml(Q.join(''));U.setAttribute('role','tabpanel');var V=b,W='cke_'+P.id+'_'+e.getNextNumber(),X=h.createFromHtml(['0?' cke_last':'cke_first',R,!!P.hidden?' style="display:none"':'',' id="',W,'"',V.gecko&&V.version>=10900&&!V.hc?'':' href="javascript:void(0)"',' tabIndex="-1"',' hidefocus="true"',' role="tab">',P.label,''].join(''));U.setAttribute('aria-labelledby',W);ab._.tabs[P.id]=[X,U];ab._.tabIdList.push(P.id);!P.hidden&&ab._.pageCount++;ab._.lastTab=X; -ab.updateStyle();var Y=ab._.contents[P.id]={},Z,aa=T.getChild();while(Z=aa.shift()){Y[Z.id]=Z;if(typeof Z.getChild=='function')aa.push.apply(aa,Z.getChild());}U.setAttribute('name',P.id);U.appendTo(ab.parts.contents);X.unselectable();ab.parts.tabs.append(X);if(P.accessKey){J(ab,ab,'CTRL+'+P.accessKey,M,L);ab._.accessKeyMap['CTRL+'+P.accessKey]=P.id;}},selectPage:function(P){if(this._.currentTabId==P)return;if(this.fire('selectPage',{page:P,currentPage:this._.currentTabId})===true)return;for(var Q in this._.tabs){var R=this._.tabs[Q][0],S=this._.tabs[Q][1];if(Q!=P){R.removeClass('cke_dialog_tab_selected');S.hide();}S.setAttribute('aria-hidden',Q!=P);}var T=this._.tabs[P];T[0].addClass('cke_dialog_tab_selected');if(b.ie6Compat||b.ie7Compat){q(T[1]);T[1].show();setTimeout(function(){q(T[1],1);},0);}else T[1].show();this._.currentTabId=P;this._.currentTabIndex=e.indexOf(this._.tabIdList,P);},updateStyle:function(){this.parts.dialog[(this._.pageCount===1?'add':'remove')+'Class']('cke_single_page');},hidePage:function(P){var R=this;var Q=R._.tabs[P]&&R._.tabs[P][0];if(!Q||R._.pageCount==1||!Q.isVisible())return;else if(P==R._.currentTabId)R.selectPage(o.call(R));Q.hide();R._.pageCount--;R.updateStyle();},showPage:function(P){var R=this;var Q=R._.tabs[P]&&R._.tabs[P][0];if(!Q)return;Q.show();R._.pageCount++;R.updateStyle();},getElement:function(){return this._.element;},getName:function(){return this._.name;},getContentElement:function(P,Q){var R=this._.contents[P];return R&&R[Q];},getValueOf:function(P,Q){return this.getContentElement(P,Q).getValue();},setValueOf:function(P,Q,R){return this.getContentElement(P,Q).setValue(R);},getButton:function(P){return this._.buttons[P];},click:function(P){return this._.buttons[P].click();},disableButton:function(P){return this._.buttons[P].disable();},enableButton:function(P){return this._.buttons[P].enable();},getPageCount:function(){return this._.pageCount;},getParentEditor:function(){return this._.editor;},getSelectedElement:function(){return this.getParentEditor().getSelection().getSelectedElement();},addFocusable:function(P,Q){var S=this;if(typeof Q=='undefined'){Q=S._.focusList.length;S._.focusList.push(new r(S,P,Q));}else{S._.focusList.splice(Q,0,new r(S,P,Q));for(var R=Q+1;Raa.width-Z.width-U)af=aa.width-Z.width+(T.lang.dir=='rtl'?0:V[1]);else af=R.x;if(R.y+V[0]aa.height-Z.height-U)ag=aa.height-Z.height+V[2];else ag=R.y;P.move(af,ag,1);Y.data.preventDefault();};function X(Y){a.document.removeListener('mousemove',W);a.document.removeListener('mouseup',X);if(b.ie6Compat){var Z=C.getChild(0).getFrameDocument();Z.removeListener('mousemove',W);Z.removeListener('mouseup',X);}};P.parts.title.on('mousedown',function(Y){Q={x:Y.data.$.screenX,y:Y.data.$.screenY};a.document.on('mousemove',W);a.document.on('mouseup',X);R=P.getPosition();if(b.ie6Compat){var Z=C.getChild(0).getFrameDocument();Z.on('mousemove',W);Z.on('mouseup',X);}Y.data.preventDefault();},P);};function z(P){var Q=P.definition,R=Q.resizable;if(R==0)return;var S=P.getParentEditor(),T,U,V,W,X,Y;function Z(ad){if(P._.moved&&S.lang.dir=='rtl'){var ae=P._.element.getFirst();ae.setStyle('right',ad+'px');ae.removeStyle('left');}else if(!P._.moved)P.layout();};var aa=e.addFunction(function(ad){X=P.getSize();var ae=P.parts.contents,af=ae.$.getElementsByTagName('iframe').length;if(af){Y=h.createFromHtml('
');ae.append(Y);}U=X.height-P.parts.contents.getSize('height',!(b.gecko||b.opera||c&&b.quirks));T=X.width-P.parts.contents.getSize('width',1);W={x:ad.screenX,y:ad.screenY};V=a.document.getWindow().getViewPaneSize();a.document.on('mousemove',ab);a.document.on('mouseup',ac);if(b.ie6Compat){var ag=C.getChild(0).getFrameDocument();ag.on('mousemove',ab);ag.on('mouseup',ac);}ad.preventDefault&&ad.preventDefault();});P.on('load',function(){var ad='';if(R==1)ad=' cke_resizer_horizontal';else if(R==2)ad=' cke_resizer_vertical';var ae=h.createFromHtml('
');P.parts.footer.append(ae,1);});S.on('destroy',function(){e.removeFunction(aa);});function ab(ad){var ae=S.lang.dir=='rtl',af=(ad.data.$.screenX-W.x)*(ae?-1:1),ag=ad.data.$.screenY-W.y,ah=X.width,ai=X.height,aj=ah+af*(P._.moved?1:2),ak=ai+ag*(P._.moved?1:2),al=P._.element.getFirst(),am=ae&&al.getComputedStyle('right'),an=P.getPosition();if(am)am=am=='auto'?V.width-(an.x||0)-al.getSize('width'):parseInt(am,10);if(an.y+ak>V.height)ak=V.height-an.y;if((ae?am:an.x)+aj>V.width)aj=V.width-(ae?am:an.x);if((R==1||R==3)&&!(ae&&af>0&&!an.x))ah=Math.max(Q.minWidth||0,aj-T); -if(R==2||R==3)ai=Math.max(Q.minHeight||0,ak-U);P.resize(ah,ai);Z(am);ad.data.preventDefault();};function ac(){a.document.removeListener('mouseup',ac);a.document.removeListener('mousemove',ab);if(Y){Y.remove();Y=null;}if(b.ie6Compat){var ad=C.getChild(0).getFrameDocument();ad.removeListener('mouseup',ac);ad.removeListener('mousemove',ab);}if(S.lang.dir=='rtl'){var ae=P._.element.getFirst(),af=ae.getComputedStyle('left');if(af=='auto')af=V.width-parseInt(ae.getStyle('right'),10)-P.getSize().width;else af=parseInt(af,10);ae.removeStyle('right');P._.position.x+=1;P.move(af,P._.position.y);}};};var A,B={},C;function D(P){var Q=a.document.getWindow(),R=P.config,S=R.dialog_backgroundCoverColor||'white',T=R.dialog_backgroundCoverOpacity,U=R.baseFloatZIndex,V=e.genKey(S,T,U),W=B[V];if(!W){var X=['
'];if(b.ie6Compat){var Y=b.isCustomDomain(),Z="";X.push('');}X.push('
');W=h.createFromHtml(X.join(''));W.setOpacity(T!=undefined?T:0.5);W.appendTo(a.document.getBody());B[V]=W;}else W.show();C=W;var aa=function(){var ad=Q.getViewPaneSize();W.setStyles({width:ad.width+'px',height:ad.height+'px'});},ab=function(){var ad=Q.getScrollPosition(),ae=a.dialog._.currentTop;W.setStyles({left:ad.x+'px',top:ad.y+'px'});if(ae)do{var af=ae.getPosition();ae.move(af.x,af.y);}while(ae=ae._.parentDialog)};A=aa;Q.on('resize',aa);aa();if(!(b.mac&&b.webkit))W.focus();if(b.ie6Compat){var ac=function(){ab();arguments.callee.prevScrollHandler.apply(this,arguments);};Q.$.setTimeout(function(){ac.prevScrollHandler=window.onscroll||(function(){});window.onscroll=ac;},0);ab();}};function E(){if(!C)return;var P=a.document.getWindow();C.hide();P.removeListener('resize',A);if(b.ie6Compat)P.$.setTimeout(function(){var Q=window.onscroll&&window.onscroll.prevScrollHandler;window.onscroll=Q||null;},0);A=null;};function F(){for(var P in B)B[P].remove();B={};};var G={},H=function(P){var Q=P.data.$.ctrlKey||P.data.$.metaKey,R=P.data.$.altKey,S=P.data.$.shiftKey,T=String.fromCharCode(P.data.$.keyCode),U=G[(Q?'CTRL+':'')+(R?'ALT+':'')+(S?'SHIFT+':'')+T]; -if(!U||!U.length)return;U=U[U.length-1];U.keydown&&U.keydown.call(U.uiElement,U.dialog,U.key);P.data.preventDefault();},I=function(P){var Q=P.data.$.ctrlKey||P.data.$.metaKey,R=P.data.$.altKey,S=P.data.$.shiftKey,T=String.fromCharCode(P.data.$.keyCode),U=G[(Q?'CTRL+':'')+(R?'ALT+':'')+(S?'SHIFT+':'')+T];if(!U||!U.length)return;U=U[U.length-1];if(U.keyup){U.keyup.call(U.uiElement,U.dialog,U.key);P.data.preventDefault();}},J=function(P,Q,R,S,T){var U=G[R]||(G[R]=[]);U.push({uiElement:P,dialog:Q,key:R,keyup:T||P.accessKeyUp,keydown:S||P.accessKeyDown});},K=function(P){for(var Q in G){var R=G[Q];for(var S=R.length-1;S>=0;S--){if(R[S].dialog==P||R[S].uiElement==P)R.splice(S,1);}if(R.length===0)delete G[Q];}},L=function(P,Q){if(P._.accessKeyMap[Q])P.selectPage(P._.accessKeyMap[Q]);},M=function(P,Q){},N={27:1,13:1},O=function(P){if(P.data.getKeystroke() in N)P.data.stopPropagation();};(function(){k.dialog={uiElement:function(P,Q,R,S,T,U,V){if(arguments.length<4)return;var W=(S.call?S(Q):S)||'div',X=['<',W,' '],Y=(T&&T.call?T(Q):T)||{},Z=(U&&U.call?U(Q):U)||{},aa=(V&&V.call?V.call(this,P,Q):V)||'',ab=this.domId=Z.id||e.getNextId()+'_uiElement',ac=this.id=Q.id,ad;Z.id=ab;var ae={};if(Q.type)ae['cke_dialog_ui_'+Q.type]=1;if(Q.className)ae[Q.className]=1;var af=Z['class']&&Z['class'].split?Z['class'].split(' '):[];for(ad=0;ad=0;ad--){if(ah[ad]==='')ah.splice(ad,1);}if(ah.length>0)Z.style=(Z.style?Z.style+'; ':'')+ah.join('; ');for(ad in Z)X.push(ad+'="'+e.htmlEncode(Z[ad])+'" ');X.push('>',aa,'');R.push(X.join(''));(this._||(this._={})).dialog=P;if(typeof Q.isChanged=='boolean')this.isChanged=function(){return Q.isChanged;};if(typeof Q.isChanged=='function')this.isChanged=Q.isChanged;a.event.implementOn(this);this.registerEvents(Q);if(this.accessKeyUp&&this.accessKeyDown&&Q.accessKey)J(this,P,'CTRL+'+Q.accessKey);var ai=this;P.on('load',function(){if(ai.getInputElement())ai.getInputElement().on('focus',function(){P._.tabBarMode=false;P._.hasFocus=true;ai.fire('focus');},ai);});if(this.keyboardFocusable){this.tabIndex=Q.tabIndex||0;this.focusIndex=P._.focusList.push(this)-1;this.on('focus',function(){P._.currentFocusIndex=ai.focusIndex;});}e.extend(this,Q);},hbox:function(P,Q,R,S,T){if(arguments.length<4)return;this._||(this._={}); -var U=this._.children=Q,V=T&&T.widths||null,W=T&&T.height||null,X={},Y,Z=function(){var ab=[''];for(Y=0;Y0)ab.push('style="'+ad.join('; ')+'" ');ab.push('>',R[Y],'');}ab.push('');return ab.join('');},aa={role:'presentation'};T&&T.align&&(aa.align=T.align);k.dialog.uiElement.call(this,P,T||{type:'hbox'},S,'table',X,aa,Z);},vbox:function(P,Q,R,S,T){if(arguments.length<3)return;this._||(this._={});var U=this._.children=Q,V=T&&T.width||null,W=T&&T.heights||null,X=function(){var Y=['');for(var Z=0;Z');}Y.push('
0)Y.push('style="',aa.join('; '),'" ');Y.push(' class="cke_dialog_ui_vbox_child">',R[Z],'
');return Y.join('');};k.dialog.uiElement.call(this,P,T||{type:'vbox'},S,'div',null,{role:'presentation'},X);}};})();k.dialog.uiElement.prototype={getElement:function(){return a.document.getById(this.domId);},getInputElement:function(){return this.getElement();},getDialog:function(){return this._.dialog;},setValue:function(P,Q){this.getInputElement().setValue(P);!Q&&this.fire('change',{value:P});return this;},getValue:function(){return this.getInputElement().getValue();},isChanged:function(){return false;},selectParentTab:function(){var S=this;var P=S.getInputElement(),Q=P,R;while((Q=Q.getParent())&&Q.$.className.search('cke_dialog_page_contents')==-1){}if(!Q)return S;R=Q.getAttribute('name');if(S._.dialog._.currentTabId!=R)S._.dialog.selectPage(R);return S;},focus:function(){this.selectParentTab().getInputElement().focus();return this;},registerEvents:function(P){var Q=/^on([A-Z]\w+)/,R,S=function(U,V,W,X){V.on('load',function(){U.getInputElement().on(W,X,U); -});};for(var T in P){if(!(R=T.match(Q)))continue;if(this.eventProcessors[T])this.eventProcessors[T].call(this,this._.dialog,P[T]);else S(this,this._.dialog,R[1].toLowerCase(),P[T]);}return this;},eventProcessors:{onLoad:function(P,Q){P.on('load',Q,this);},onShow:function(P,Q){P.on('show',Q,this);},onHide:function(P,Q){P.on('hide',Q,this);}},accessKeyDown:function(P,Q){this.focus();},accessKeyUp:function(P,Q){},disable:function(){var P=this.getInputElement();P.setAttribute('disabled','true');P.addClass('cke_disabled');},enable:function(){var P=this.getInputElement();P.removeAttribute('disabled');P.removeClass('cke_disabled');},isEnabled:function(){return!this.getInputElement().getAttribute('disabled');},isVisible:function(){return this.getInputElement().isVisible();},isFocusable:function(){if(!this.isEnabled()||!this.isVisible())return false;return true;}};k.dialog.hbox.prototype=e.extend(new k.dialog.uiElement(),{getChild:function(P){var Q=this;if(arguments.length<1)return Q._.children.concat();if(!P.splice)P=[P];if(P.length<2)return Q._.children[P[0]];else return Q._.children[P[0]]&&Q._.children[P[0]].getChild?Q._.children[P[0]].getChild(P.slice(1,P.length)):null;}},true);k.dialog.vbox.prototype=new k.dialog.hbox();(function(){var P={build:function(Q,R,S){var T=R.children,U,V=[],W=[];for(var X=0;X',T.name,'');return U.join('');}};a.style.getStyleText=function(T){var U=T._ST;if(U)return U;U=T.styles;var V=T.attributes&&T.attributes.style||'',W='';if(V.length)V=V.replace(o,';');for(var X in U){var Y=U[X],Z=(X+':'+Y).replace(o,';');if(Y=='inherit')W+=Z;else V+=Z;}if(V.length)V=P(V);V+=W;return T._ST=V;};function q(T){var U,V;while(T=T.getParent()){if(T.getName()=='body')break;if(T.getAttribute('data-nostyle'))U=T;else if(!V){var W=T.getAttribute('contentEditable');if(W=='false')U=T;else if(W=='true')V=1;}}return U;};function r(T){var ax=this;var U=T.document;if(T.collapsed){var V=I(ax,U);T.insertNode(V);T.moveToPosition(V,2);return;}var W=ax.element,X=ax._.definition,Y,Z=X.includeReadonly;if(Z==undefined)Z=U.getCustomData('cke_includeReadonly');var aa=f[W]||(Y=true,f.span);T.enlarge(1,1);T.trim();var ab=T.createBookmark(),ac=ab.startNode,ad=ab.endNode,ae=ac,af,ag=q(ac),ah=q(ad);if(ag)ae=ag.getNextSourceNode(true);if(ah)ad=ah; -if(ae.getPosition(ad)==2)ae=0;while(ae){var ai=false;if(ae.equals(ad)){ae=null;ai=true;}else{var aj=ae.type,ak=aj==1?ae.getName():null,al=ak&&ae.getAttribute('contentEditable')=='false',am=ak&&ae.getAttribute('data-nostyle');if(ak&&ae.data('cke-bookmark')){ae=ae.getNextSourceNode(true);continue;}if(!ak||aa[ak]&&!am&&(!al||Z)&&(ae.getPosition(ad)|4|0|8)==4+0+8&&(!X.childRule||X.childRule(ae))){var an=ae.getParent();if(an&&((an.getDtd()||f.span)[W]||Y)&&(!X.parentRule||X.parentRule(an))){if(!af&&(!ak||!f.$removeEmpty[ak]||(ae.getPosition(ad)|4|0|8)==4+0+8)){af=new d.range(U);af.setStartBefore(ae);}if(aj==3||al||aj==1&&!ae.getChildCount()){var ao=ae,ap;while((ai=!ao.getNext(p))&&(ap=ao.getParent(),aa[ap.getName()])&&(ap.getPosition(ac)|2|0|8)==2+0+8&&(!X.childRule||X.childRule(ap)))ao=ap;af.setEndAfter(ao);}}else ai=true;}else ai=true;ae=ae.getNextSourceNode(am||al);}if(ai&&af&&!af.collapsed){var aq=I(ax,U),ar=aq.hasAttributes(),as=af.getCommonAncestor(),at={styles:{},attrs:{},blockedStyles:{},blockedAttrs:{}},au,av,aw;while(aq&&as){if(as.getName()==W){for(au in X.attributes){if(at.blockedAttrs[au]||!(aw=as.getAttribute(av)))continue;if(aq.getAttribute(au)==aw)at.attrs[au]=1;else at.blockedAttrs[au]=1;}for(av in X.styles){if(at.blockedStyles[av]||!(aw=as.getStyle(av)))continue;if(aq.getStyle(av)==aw)at.styles[av]=1;else at.blockedStyles[av]=1;}}as=as.getParent();}for(au in at.attrs)aq.removeAttribute(au);for(av in at.styles)aq.removeStyle(av);if(ar&&!aq.hasAttributes())aq=null;if(aq){af.extractContents().appendTo(aq);F(ax,aq);af.insertNode(aq);aq.mergeSiblings();if(!c)aq.$.normalize();}else{aq=new h('span');af.extractContents().appendTo(aq);af.insertNode(aq);F(ax,aq);aq.remove(true);}af=null;}}T.moveToBookmark(ab);T.shrink(2);};function s(T){T.enlarge(1,1);var U=T.createBookmark(),V=U.startNode;if(T.collapsed){var W=new d.elementPath(V.getParent()),X;for(var Y=0,Z;Y'+V+'';else T.setHtml(V);U.remove();};function A(T){var U=/(\S\s*)\n(?:\s|(]+data-cke-bookmark.*?\/span>))*\n(?!$)/gi,V=T.getName(),W=B(T.getOuterHtml(),U,function(Y,Z,aa){return Z+''+aa+'
';}),X=[];W.replace(/([\s\S]*?)<\/pre>/gi,function(Y,Z){X.push(Z);});return X;};function B(T,U,V){var W='',X='';T=T.replace(/(^]+data-cke-bookmark.*?\/span>)|(]+data-cke-bookmark.*?\/span>$)/gi,function(Y,Z,aa){Z&&(W=Z);
-aa&&(X=aa);return '';});return W+T.replace(U,V)+X;};function C(T,U){var V;if(T.length>1)V=new d.documentFragment(U.getDocument());for(var W=0;W');X=X.replace(/[ \t]{2,}/g,function(Z){return e.repeat(' ',Z.length-1)+' ';});if(V){var Y=U.clone();Y.setHtml(X);V.append(Y);}else U.setHtml(X);}return V||U;};function D(T,U){var V=T.getBogus();V&&V.remove();var W=T.getHtml();W=B(W,/(?:^[ \t\n\r]+)|(?:[ \t\n\r]+$)/g,'');W=W.replace(/[ \t\r\n]*(]*>)[ \t\r\n]*/gi,'$1');W=W.replace(/([ \t\n\r]+| )/g,' ');W=W.replace(/]*>/gi,'\n');if(c){var X=T.getDocument().createElement('div');X.append(U);U.$.outerHTML='
'+W+'
';U.copyAttributes(X.getFirst());U=X.getFirst().remove();}else U.setHtml(W);return U;};function E(T,U){var V=T._.definition,W=e.extend({},V.attributes,N(T)[U.getName()]),X=V.styles,Y=e.isEmpty(W)&&e.isEmpty(X);for(var Z in W){if((Z=='class'||T._.definition.fullMatch)&&U.getAttribute(Z)!=O(Z,W[Z]))continue;Y=U.hasAttribute(Z);U.removeAttribute(Z);}for(var aa in X){if(T._.definition.fullMatch&&U.getStyle(aa)!=O(aa,X[aa],true))continue;Y=Y||!!U.getStyle(aa);U.removeStyle(aa);}if(Y)!f.$block[U.getName()]||T._.enterMode==2&&!U.hasAttributes()?H(U):U.renameNode(T._.enterMode==1?'p':'div');};function F(T,U){var V=T._.definition,W=V.attributes,X=V.styles,Y=N(T),Z=U.getElementsByTag(T.element);for(var aa=Z.count();--aa>=0;)E(T,Z.getItem(aa));for(var ab in Y){if(ab!=T.element){Z=U.getElementsByTag(ab);for(aa=Z.count()-1;aa>=0;aa--){var ac=Z.getItem(aa);G(ac,Y[ab]);}}}};function G(T,U){var V=U&&U.attributes;if(V)for(var W=0;W0)H+=(F.$.offsetWidth||0)-(F.$.clientWidth||0);H+=4;F.setStyle('width',H+'px');v.element.addClass('cke_frameLoaded');var I=v.element.$.scrollHeight;if(c&&b.quirks&&I>0)I+=(F.$.offsetHeight||0)-(F.$.clientHeight||0);F.setStyle('height',I+'px');u._.currentBlock.element.setStyle('display','none').removeStyle('display');}else F.removeStyle('height');var J=u.element,K=J.getWindow(),L=K.getScrollPosition(),M=K.getViewPaneSize(),N={height:J.$.offsetHeight,width:J.$.offsetWidth};if(A?B<0:B+N.width>M.width+L.x)B+=N.width*(A?1:-1);if(C+N.height>M.height+L.y)C-=N.height;if(c){var O=new h(w.$.offsetParent),P=O;if(P.getName()=='html')P=P.getDocument().getBody();if(P.getComputedStyle('direction')=='rtl')if(b.ie8Compat)B-=w.getDocument().getDocumentElement().$.scrollLeft*2;else B-=O.$.scrollWidth-O.$.clientWidth;}var Q=w.getFirst(),R;if(R=Q.getCustomData('activePanel'))R.onHide&&R.onHide.call(this,1); -Q.setCustomData('activePanel',this);w.setStyles({top:C+'px',left:B+'px'});w.setOpacity(1);},this);u.isLoaded?E():u.onLoad=E;e.setTimeout(function(){x.$.contentWindow.focus();this.allowBlur(true);},0,this);},b.air?200:0,this);this.visible=1;if(this.onShow)this.onShow.call(this);n=0;},hide:function(){var p=this;if(p.visible&&(!p.onHide||p.onHide.call(p)!==true)){p.hideChild();p.element.setStyle('display','none');p.visible=0;p.element.getFirst().removeCustomData('activePanel');}},allowBlur:function(p){var q=this._.panel;if(p!=undefined)q.allowBlur=p;return q.allowBlur;},showAsChild:function(p,q,r,s,t,u){if(this._.activeChild==p&&p._.panel._.offsetParentId==r.getId())return;this.hideChild();p.onHide=e.bind(function(){e.setTimeout(function(){if(!this._.focused)this.hide();},0,this);},this);this._.activeChild=p;this._.focused=false;p.showBlock(q,r,s,t,u);if(b.ie7Compat||b.ie8&&b.ie6Compat)setTimeout(function(){p.element.getChild(0).$.style.cssText+='';},100);},hideChild:function(){var p=this._.activeChild;if(p){delete p.onHide;delete this._.activeChild;p.hide();}}}});a.on('instanceDestroyed',function(){var p=e.isEmpty(a.instances);for(var q in m){var r=m[q];if(p)r.destroy();else r.element.hide();}p&&(m={});});})();j.add('menu',{beforeInit:function(m){var n=m.config.menu_groups.split(','),o=m._.menuGroups={},p=m._.menuItems={};for(var q=0;q'],B=r.length,C=B&&r[0].group;for(var D=0;D');C=E.group;}E.render(this,D,A);}A.push('');u.setHtml(A.join(''));k.fire('ready',this);if(this.parent)this.parent._.panel.showAsChild(t,this.id,n,o,p,q);else t.showBlock(this.id,n,o,p,q);s.fire('menuShow',[t]); -},addListener:function(n){this._.listeners.push(n);},hide:function(){var n=this;n._.onHide&&n._.onHide();n._.panel&&n._.panel.hide();}}});function m(n){n.sort(function(o,p){if(o.groupp.group)return 1;return o.orderp.order?1:0;});};a.menuItem=e.createClass({$:function(n,o,p){var q=this;e.extend(q,p,{order:0,className:'cke_button_'+o});q.group=n._.menuGroups[q.group];q.editor=n;q.name=o;},proto:{render:function(n,o,p){var w=this;var q=n.id+String(o),r=typeof w.state=='undefined'?2:w.state,s=' cke_'+(r==1?'on':r==0?'disabled':'off'),t=w.label;if(w.className)s+=' '+w.className;var u=w.getItems;p.push(''+''+'');if(u)p.push('','&#',w.editor.lang.dir=='rtl'?'9668':'9658',';','');p.push(t,'');}}});})();i.menu_groups='clipboard,form,tablecell,tablecellproperties,tablerow,tablecolumn,table,anchor,link,image,flash,checkbox,radio,textfield,hiddenfield,imagebutton,button,select,textarea,div';(function(){var m=function(o,p){return o._.modes&&o._.modes[p||o.mode];},n;j.add('editingblock',{init:function(o){if(!o.config.editingBlock)return;o.on('themeSpace',function(p){if(p.data.space=='contents')p.data.html+='
';});o.on('themeLoaded',function(){o.fireOnce('editingBlockReady');});o.on('uiReady',function(){o.setMode(o.config.startupMode);});o.on('afterSetData',function(){if(!n){function p(){n=true;m(o).loadData(o.getData());n=false;};if(o.mode)p();else o.on('mode',function(){p();o.removeListener('mode',arguments.callee);});}});o.on('beforeGetData',function(){if(!n&&o.mode){n=true; -o.setData(m(o).getData(),null,1);n=false;}});o.on('getSnapshot',function(p){if(o.mode)p.data=m(o).getSnapshotData();});o.on('loadSnapshot',function(p){if(o.mode)m(o).loadSnapshotData(p.data);});o.on('mode',function(p){p.removeListener();b.webkit&&o.container.on('focus',function(){o.focus();});if(o.config.startupFocus)o.focus();setTimeout(function(){o.fireOnce('instanceReady');a.fire('instanceReady',null,o);},0);});o.on('destroy',function(){var p=this;if(p.mode)p._.modes[p.mode].unload(p.getThemeSpace('contents'));});}});a.editor.prototype.mode='';a.editor.prototype.addMode=function(o,p){p.name=o;(this._.modes||(this._.modes={}))[o]=p;};a.editor.prototype.setMode=function(o){var p,q=this.getThemeSpace('contents'),r=this.checkDirty();if(this.mode){if(o==this.mode)return;this.fire('beforeModeUnload');var s=m(this);p=s.getData();s.unload(q);this.mode='';}q.setHtml('');var t=m(this,o);if(!t)throw '[CKEDITOR.editor.setMode] Unknown mode "'+o+'".';if(!r)this.on('mode',function(){this.resetDirty();this.removeListener('mode',arguments.callee);});t.load(q,typeof p!='string'?this.getData():p);};a.editor.prototype.focus=function(){var o=m(this);if(o)o.focus();};})();i.startupMode='wysiwyg';i.editingBlock=true;(function(){function m(){var w=this;try{var t=w.getSelection();if(!t||!t.document.getWindow().$)return;var u=t.getStartElement(),v=new d.elementPath(u);if(!v.compare(w._.selectionPreviousPath)){w._.selectionPreviousPath=v;w.fire('selectionChange',{selection:t,path:v,element:u});}}catch(x){}};var n,o;function p(){o=true;if(n)return;q.call(this);n=e.setTimeout(q,200,this);};function q(){n=null;if(o){e.setTimeout(m,0,this);o=false;}};var r={modes:{wysiwyg:1,source:1},exec:function(t){switch(t.mode){case 'wysiwyg':t.document.$.execCommand('SelectAll',false,null);t.forceNextSelectionCheck();t.selectionChange();break;case 'source':var u=t.textarea.$;if(c)u.createTextRange().execCommand('SelectAll');else{u.selectionStart=0;u.selectionEnd=u.value.length;}u.focus();}},canUndo:false};j.add('selection',{init:function(t){t.on('contentDom',function(){var u=t.document,v=u.getBody(),w=u.getDocumentElement();if(c){var x,y,z=1;v.on('focusin',function(D){if(D.data.$.srcElement.nodeName!='BODY')return;if(x){var E=u.getCustomData('cke_locked_selection');if(z&&!E)try{x.select();}catch(F){}x=null;}});v.on('focus',function(){y=1;C();});v.on('beforedeactivate',function(D){if(D.data.$.toElement)return;y=0;z=1;});if(c&&b.version<8)t.on('blur',function(D){try{t.document&&t.document.$.selection.empty(); -}catch(E){}});w.on('mousedown',function(){z=0;});w.on('mouseup',function(){z=1;});if(c&&(b.ie7Compat||b.version<8||b.quirks))w.on('click',function(D){if(D.data.getTarget().getName()=='html')t.getSelection().getRanges()[0].select();});var A;v.on('mousedown',function(D){if(D.data.$.button==2){var E=t.document.$.selection;if(E.type=='None')A=t.window.getScrollPosition();}B();});v.on('mouseup',function(D){if(D.data.$.button==2&&A){t.document.$.documentElement.scrollLeft=A.x;t.document.$.documentElement.scrollTop=A.y;}A=null;y=1;setTimeout(function(){C(true);},0);});v.on('keydown',B);v.on('keyup',function(){y=1;C();});u.on('selectionchange',C);function B(){y=0;};function C(D){if(y){var E=t.document,F=t.getSelection(),G=F&&F.getNative();if(D&&G&&G.type=='None')if(!E.$.queryCommandEnabled('InsertImage')){e.setTimeout(C,50,this,true);return;}var H;if(G&&G.type&&G.type!='Control'&&(H=G.createRange())&&(H=H.parentElement())&&(H=H.nodeName)&&H.toLowerCase() in {input:1,textarea:1})return;x=G&&F.getRanges()[0];p.call(t);}};}else{u.on('mouseup',p,t);u.on('keyup',p,t);}});t.on('contentDomUnload',t.forceNextSelectionCheck,t);t.addCommand('selectAll',r);t.ui.addButton('SelectAll',{label:t.lang.selectAll,command:'selectAll'});t.selectionChange=p;}});a.editor.prototype.getSelection=function(){return this.document&&this.document.getSelection();};a.editor.prototype.forceNextSelectionCheck=function(){delete this._.selectionPreviousPath;};g.prototype.getSelection=function(){var t=new d.selection(this);return!t||t.isInvalid?null:t;};a.SELECTION_NONE=1;a.SELECTION_TEXT=2;a.SELECTION_ELEMENT=3;d.selection=function(t){var w=this;var u=t.getCustomData('cke_locked_selection');if(u)return u;w.document=t;w.isLocked=0;w._={cache:{}};if(c){var v=w.getNative().createRange();if(!v||v.item&&v.item(0).ownerDocument!=w.document.$||v.parentElement&&v.parentElement().ownerDocument!=w.document.$)w.isInvalid=true;}return w;};var s={img:1,hr:1,li:1,table:1,tr:1,td:1,th:1,embed:1,object:1,ol:1,ul:1,a:1,input:1,form:1,select:1,textarea:1,button:1,fieldset:1,th:1,thead:1,tfoot:1};d.selection.prototype={getNative:c?function(){return this._.cache.nativeSel||(this._.cache.nativeSel=this.document.$.selection);}:function(){return this._.cache.nativeSel||(this._.cache.nativeSel=this.document.getWindow().$.getSelection());},getType:c?function(){var t=this._.cache;if(t.type)return t.type;var u=1;try{var v=this.getNative(),w=v.type;if(w=='Text')u=2;if(w=='Control')u=3;if(v.createRange().parentElement)u=2;}catch(x){}return t.type=u; -}:function(){var t=this._.cache;if(t.type)return t.type;var u=2,v=this.getNative();if(!v)u=1;else if(v.rangeCount==1){var w=v.getRangeAt(0),x=w.startContainer;if(x==w.endContainer&&x.nodeType==1&&w.endOffset-w.startOffset==1&&s[x.childNodes[w.startOffset].nodeName.toLowerCase()])u=3;}return t.type=u;},getRanges:(function(){var t=c?(function(){function u(w){return new d.node(w).getIndex();};var v=function(w,x){w=w.duplicate();w.collapse(x);var y=w.parentElement();if(!y.hasChildNodes())return{container:y,offset:0};var z=y.children,A,B=w.duplicate(),C=0,D=z.length-1,E=-1,F,G;while(C<=D){E=Math.floor((C+D)/2);A=z[E];B.moveToElementText(A);F=B.compareEndPoints('StartToStart',w);if(F>0)D=E-1;else if(F<0)C=E+1;else return{container:y,offset:u(A)};}if(E==-1||E==z.length-1&&F<0){B.moveToElementText(y);B.setEndPoint('StartToStart',w);G=B.text.replace(/(\r\n|\r)/g,'\n').length;z=y.childNodes;if(!G){A=z[z.length-1];if(A.nodeType==1)return{container:y,offset:z.length};else return{container:A,offset:A.nodeValue.length};}var H=z.length;while(G>0)G-=z[--H].nodeValue.length;return{container:z[H],offset:-G};}else{B.collapse(F>0?true:false);B.setEndPoint(F>0?'StartToStart':'EndToStart',w);G=B.text.replace(/(\r\n|\r)/g,'\n').length;if(!G)return{container:y,offset:u(A)+(F>0?0:1)};while(G>0){A=A[F>0?'previousSibling':'nextSibling'];try{G-=A.nodeValue.length;}catch(I){return{container:y,offset:u(A)};}}return{container:A,offset:F>0?-G:A.nodeValue.length+G};}};return function(){var G=this;var w=G.getNative(),x=w&&w.createRange(),y=G.getType(),z;if(!w)return[];if(y==2){z=new d.range(G.document);var A=v(x,true);z.setStart(new d.node(A.container),A.offset);A=v(x);z.setEnd(new d.node(A.container),A.offset);if(z.endContainer.getPosition(z.startContainer)&4&&z.endOffset<=z.startContainer.getIndex())z.collapse();return[z];}else if(y==3){var B=[];for(var C=0;C=A.getLength())E.setStartAfter(A);else E.setStartBefore(A);if(B&&B.type==3)if(!D)E.setEndBefore(B);else E.setEndAfter(B);var G=new d.walker(E);G.evaluator=function(H){if(H.type==1&&H.isReadOnly()){var I=y.clone();y.setEndBefore(H);if(y.collapsed)w.splice(x--,1);if(!(H.getPosition(E.endContainer)&16)){I.setStartAfter(H);if(!I.collapsed)w.splice(x+1,0,I);}return true;}return false;};G.next();}}return v.ranges;};})(),getStartElement:function(){var A=this;var t=A._.cache;if(t.startElement!==undefined)return t.startElement;var u,v=A.getNative();switch(A.getType()){case 3:return A.getSelectedElement();case 2:var w=A.getRanges()[0];if(w){if(!w.collapsed){w.optimize();while(1){var x=w.startContainer,y=w.startOffset;if(y==(x.getChildCount?x.getChildCount():x.getLength())&&!x.isBlockBoundary())w.setStartAfter(x);else break;}u=w.startContainer;if(u.type!=1)return u.getParent();u=u.getChild(w.startOffset);if(!u||u.type!=1)u=w.startContainer;else{var z=u.getFirst();while(z&&z.type==1){u=z;z=z.getFirst();}}}else{u=w.startContainer;if(u.type!=1)u=u.getParent();}u=u.$;}}return t.startElement=u?new h(u):null;},getSelectedElement:function(){var t=this._.cache;if(t.selectedElement!==undefined)return t.selectedElement;var u=this,v=e.tryThese(function(){return u.getNative().createRange().item(0);},function(){var w=u.getRanges()[0],x,y;for(var z=2;z&&!((x=w.getEnclosedNode())&&x.type==1&&s[x.getName()]&&(y=x));z--)w.shrink(1);return y.$;});return t.selectedElement=v?new h(v):null;},lock:function(){var t=this;t.getRanges();t.getStartElement();t.getSelectedElement();t._.cache.nativeSel={};t.isLocked=1;t.document.setCustomData('cke_locked_selection',t);},unlock:function(t){var y=this;var u=y.document,v=u.getCustomData('cke_locked_selection');if(v){u.setCustomData('cke_locked_selection',null);if(t){var w=v.getSelectedElement(),x=!w&&v.getRanges();y.isLocked=0;y.reset();u.getBody().focus();if(w)y.selectElement(w);else y.selectRanges(x);}}if(!v||!t){y.isLocked=0;y.reset();}},reset:function(){this._.cache={};},selectElement:function(t){var w=this;if(w.isLocked){var u=new d.range(w.document);u.setStartBefore(t);u.setEndAfter(t);w._.cache.selectedElement=t; -w._.cache.startElement=t;w._.cache.ranges=new d.rangeList(u);w._.cache.type=3;return;}if(c){w.getNative().empty();try{u=w.document.$.body.createControlRange();u.addElement(t.$);u.select();}catch(x){u=w.document.$.body.createTextRange();u.moveToElementText(t.$);u.select();}finally{w.document.fire('selectionchange');}w.reset();}else{u=w.document.$.createRange();u.selectNode(t.$);var v=w.getNative();v.removeAllRanges();v.addRange(u);w.reset();}},selectRanges:function(t){var F=this;if(F.isLocked){F._.cache.selectedElement=null;F._.cache.startElement=t[0]&&t[0].getTouchedStartNode();F._.cache.ranges=new d.rangeList(t);F._.cache.type=2;return;}if(c){if(t.length>1){var u=t[t.length-1];t[0].setEnd(u.endContainer,u.endOffset);t.length=1;}if(t[0])t[0].select();F.reset();}else{var v=F.getNative();if(t.length)v.removeAllRanges();for(var w=0;w=0){s.collapse(true);q.setEnd(s.endContainer.$,s.endOffset);}else throw t;}var r=s.document.getSelection().getNative();if(r){r.removeAllRanges();r.addRange(q);}};})();(function(){var m={elements:{$:function(n){var o=n.attributes,p=o&&o['data-cke-realelement'],q=p&&new a.htmlParser.fragment.fromHtml(decodeURIComponent(p)),r=q&&q.children[0];if(r&&n.attributes['data-cke-resizable']){var s=n.attributes.style;if(s){var t=/(?:^|\s)width\s*:\s*(\d+)/i.exec(s),u=t&&t[1];t=/(?:^|\s)height\s*:\s*(\d+)/i.exec(s);var v=t&&t[1];if(u)r.attributes.width=u;if(v)r.attributes.height=v;}}return r;}}};j.add('fakeobjects',{requires:['htmlwriter'],afterInit:function(n){var o=n.dataProcessor,p=o&&o.htmlFilter;if(p)p.addRules(m);}});})();a.editor.prototype.createFakeElement=function(m,n,o,p){var q=this.lang.fakeobjects,r=q[o]||q.unknown,s={'class':n,src:a.getUrl('images/spacer.gif'),'data-cke-realelement':encodeURIComponent(m.getOuterHtml()),'data-cke-real-node-type':m.type,alt:r,title:r,align:m.getAttribute('align')||''};if(o)s['data-cke-real-element-type']=o;if(p)s['data-cke-resizable']=p;return this.document.createElement('img',{attributes:s});};a.editor.prototype.createFakeParserElement=function(m,n,o,p){var q=this.lang.fakeobjects,r=q[o]||q.unknown,s,t=new a.htmlParser.basicWriter();m.writeHtml(t);s=t.getHtml();var u={'class':n,src:a.getUrl('images/spacer.gif'),'data-cke-realelement':encodeURIComponent(s),'data-cke-real-node-type':m.type,alt:r,title:r,align:m.attributes.align||''};if(o)u['data-cke-real-element-type']=o;if(p)u['data-cke-resizable']=p;return new a.htmlParser.element('img',u);};a.editor.prototype.restoreRealElement=function(m){if(m.data('cke-real-node-type')!=1)return null; -return h.createFromHtml(decodeURIComponent(m.data('cke-realelement')),this.document);};j.add('richcombo',{requires:['floatpanel','listblock','button'],beforeInit:function(m){m.ui.addHandler(3,k.richCombo.handler);}});a.UI_RICHCOMBO=3;k.richCombo=e.createClass({$:function(m){var o=this;e.extend(o,m,{title:m.label,modes:{wysiwyg:1}});var n=o.panel||{};delete o.panel;o.id=e.getNextNumber();o.document=n&&n.parent&&n.parent.getDocument()||a.document;n.className=(n.className||'')+' cke_rcombopanel';n.block={multiSelect:n.multiSelect,attributes:n.attributes};o._={panelDefinition:n,items:{},state:2};},statics:{handler:{create:function(m){return new k.richCombo(m);}}},proto:{renderHtml:function(m){var n=[];this.render(m,n);return n.join('');},render:function(m,n){var o=b,p='cke_'+this.id,q=e.addFunction(function(t){var w=this;var u=w._;if(u.state==0)return;w.createPanel(m);if(u.on){u.panel.hide();return;}w.commit();var v=w.getValue();if(v)u.list.mark(v);else u.list.unmarkAll();u.panel.showBlock(w.id,new h(t),4);},this),r={id:p,combo:this,focus:function(){var t=a.document.getById(p).getChild(1);t.focus();},clickFn:q};m.on('mode',function(){this.setState(this.modes[m.mode]?2:0);this.setValue('');},this);var s=e.addFunction(function(t,u){t=new d.event(t);var v=t.getKeystroke();switch(v){case 13:case 32:case 40:e.callFunction(q,u);break;default:r.onkey(r,v);}t.preventDefault();});r.keyDownFn=s;n.push('','','',this.label,'','=10900&&!o.hc?'':" href=\"javascript:void('"+this.label+"')\"",' role="button" aria-labelledby="',p,'_label" aria-describedby="',p,'_text" aria-haspopup="true"');if(b.opera||b.gecko&&b.mac)n.push(' onkeypress="return false;"');if(b.gecko)n.push(' onblur="this.style.cssText = this.style.cssText;"');n.push(' onkeydown="CKEDITOR.tools.callFunction( ',s,', event, this );" onclick="CKEDITOR.tools.callFunction(',q,', this); return false;">'+this.label+''+''+''+(b.hc?'':b.air?' ':'')+''+''+''+'');if(this.onRender)this.onRender();return r;},createPanel:function(m){if(this._.panel)return;var n=this._.panelDefinition,o=this._.panelDefinition.block,p=n.parent||a.document.getBody(),q=new k.floatPanel(m,p,n),r=q.addListBlock(this.id,o),s=this; -q.onShow=function(){if(s.className)this.element.getFirst().addClass(s.className+'_panel');s.setState(1);r.focus(!s.multiSelect&&s.getValue());s._.on=1;if(s.onOpen)s.onOpen();};q.onHide=function(t){if(s.className)this.element.getFirst().removeClass(s.className+'_panel');s.setState(s.modes&&s.modes[m.mode]?2:0);s._.on=0;if(!t&&s.onClose)s.onClose();};q.onEscape=function(){q.hide();s.document.getById('cke_'+s.id).getFirst().getNext().focus();};r.onClick=function(t,u){s.document.getWindow().focus();if(s.onClick)s.onClick.call(s,t,u);if(u)s.setValue(t,s._.items[t]);else s.setValue('');q.hide();};this._.panel=q;this._.list=r;q.getBlock(this.id).onHide=function(){s._.on=0;s.setState(2);};if(this.init)this.init();},setValue:function(m,n){var p=this;p._.value=m;var o=p.document.getById('cke_'+p.id+'_text');if(o){if(!(m||n)){n=p.label;o.addClass('cke_inline_label');}else o.removeClass('cke_inline_label');o.setHtml(typeof n!='undefined'?n:m);}},getValue:function(){return this._.value||'';},unmarkAll:function(){this._.list.unmarkAll();},mark:function(m){this._.list.mark(m);},hideItem:function(m){this._.list.hideItem(m);},hideGroup:function(m){this._.list.hideGroup(m);},showAll:function(){this._.list.showAll();},add:function(m,n,o){this._.items[m]=o||m;this._.list.add(m,n,o);},startGroup:function(m){this._.list.startGroup(m);},commit:function(){var m=this;if(!m._.committed){m._.list.commit();m._.committed=1;k.fire('ready',m);}m._.committed=1;},setState:function(m){var n=this;if(n._.state==m)return;n.document.getById('cke_'+n.id).setState(m);n._.state=m;}}});k.prototype.addRichCombo=function(m,n){this.add(m,3,n);};j.add('htmlwriter');a.htmlWriter=e.createClass({base:a.htmlParser.basicWriter,$:function(){var o=this;o.base();o.indentationChars='\t';o.selfClosingEnd=' />';o.lineBreakChars='\n';o.forceSimpleAmpersand=0;o.sortAttributes=1;o._.indent=0;o._.indentation='';o._.inPre=0;o._.rules={};var m=f;for(var n in e.extend({},m.$nonBodyContent,m.$block,m.$listItem,m.$tableContent))o.setRules(n,{indent:1,breakBeforeOpen:1,breakAfterOpen:1,breakBeforeClose:!m[n]['#'],breakAfterClose:1});o.setRules('br',{breakAfterOpen:1});o.setRules('title',{indent:0,breakAfterOpen:0});o.setRules('style',{indent:0,breakBeforeClose:1});o.setRules('pre',{indent:0});},proto:{openTag:function(m,n){var p=this;var o=p._.rules[m];if(p._.indent)p.indentation();else if(o&&o.breakBeforeOpen){p.lineBreak();p.indentation();}p._.output.push('<',m);},openTagClose:function(m,n){var p=this;var o=p._.rules[m]; -if(n)p._.output.push(p.selfClosingEnd);else{p._.output.push('>');if(o&&o.indent)p._.indentation+=p.indentationChars;}if(o&&o.breakAfterOpen)p.lineBreak();m=='pre'&&(p._.inPre=1);},attribute:function(m,n){if(typeof n=='string'){this.forceSimpleAmpersand&&(n=n.replace(/&/g,'&'));n=e.htmlEncodeAttr(n);}this._.output.push(' ',m,'="',n,'"');},closeTag:function(m){var o=this;var n=o._.rules[m];if(n&&n.indent)o._.indentation=o._.indentation.substr(o.indentationChars.length);if(o._.indent)o.indentation();else if(n&&n.breakBeforeClose){o.lineBreak();o.indentation();}o._.output.push('');m=='pre'&&(o._.inPre=0);if(n&&n.breakAfterClose)o.lineBreak();},text:function(m){var n=this;if(n._.indent){n.indentation();!n._.inPre&&(m=e.ltrim(m));}n._.output.push(m);},comment:function(m){if(this._.indent)this.indentation();this._.output.push('');},lineBreak:function(){var m=this;if(!m._.inPre&&m._.output.length>0)m._.output.push(m.lineBreakChars);m._.indent=1;},indentation:function(){var m=this;if(!m._.inPre)m._.output.push(m._.indentation);m._.indent=0;},setRules:function(m,n){var o=this._.rules[m];if(o)e.extend(o,n,true);else this._.rules[m]=n;}}});j.add('menubutton',{requires:['button','menu'],beforeInit:function(m){m.ui.addHandler(5,k.menuButton.handler);}});a.UI_MENUBUTTON=5;(function(){var m=function(n){var o=this._;if(o.state===0)return;o.previousState=o.state;var p=o.menu;if(!p){p=o.menu=new a.menu(n,{panel:{className:n.skinClass+' cke_contextmenu',attributes:{'aria-label':n.lang.common.options}}});p.onHide=e.bind(function(){this.setState(this.modes&&this.modes[n.mode]?o.previousState:0);},this);if(this.onMenu)p.addListener(this.onMenu);}if(o.on){p.hide();return;}this.setState(1);p.show(a.document.getById(this._.id),4);};k.menuButton=e.createClass({base:k.button,$:function(n){var o=n.panel;delete n.panel;this.base(n);this.hasArrow=true;this.click=m;},statics:{handler:{create:function(n){return new k.menuButton(n);}}}});})();j.add('dialogui');(function(){var m=function(u){var x=this;x._||(x._={});x._['default']=x._.initValue=u['default']||'';x._.required=u.required||false;var v=[x._];for(var w=1;w',v.label,'','');else{var D={type:'hbox',widths:v.widths,padding:0,children:[{type:'html',html:'
';else T.setHtml(V);U.remove();};function B(T){var U=/(\S\s*)\n(?:\s|(]+data-cke-bookmark.*?\/span>))*\n(?!$)/gi,V=T.getName(),W=C(T.getOuterHtml(),U,function(Y,Z,aa){return Z+''+aa+'
';}),X=[];W.replace(/([\s\S]*?)<\/pre>/gi,function(Y,Z){X.push(Z);});return X;};function C(T,U,V){var W='',X='';T=T.replace(/(^]+data-cke-bookmark.*?\/span>)|(]+data-cke-bookmark.*?\/span>$)/gi,function(Y,Z,aa){Z&&(W=Z);aa&&(X=aa);return '';});return W+T.replace(U,V)+X;};function D(T,U){var V;if(T.length>1)V=new d.documentFragment(U.getDocument());for(var W=0;W');X=X.replace(/[ \t]{2,}/g,function(Z){return e.repeat(' ',Z.length-1)+' ';});if(V){var Y=U.clone();Y.setHtml(X);V.append(Y);}else U.setHtml(X);}return V||U;};function E(T,U){var V=T.getBogus();V&&V.remove();var W=T.getHtml();W=C(W,/(?:^[ \t\n\r]+)|(?:[ \t\n\r]+$)/g,'');W=W.replace(/[ \t\r\n]*(]*>)[ \t\r\n]*/gi,'$1');W=W.replace(/([ \t\n\r]+| )/g,' ');W=W.replace(/]*>/gi,'\n');if(c){var X=T.getDocument().createElement('div');X.append(U);U.$.outerHTML='
'+W+'
';U.copyAttributes(X.getFirst());U=X.getFirst().remove();}else U.setHtml(W);return U;};function F(T,U){var V=T._.definition,W=e.extend({},V.attributes,N(T)[U.getName()]),X=V.styles,Y=e.isEmpty(W)&&e.isEmpty(X);for(var Z in W){if((Z=='class'||T._.definition.fullMatch)&&U.getAttribute(Z)!=O(Z,W[Z]))continue;Y=U.hasAttribute(Z);U.removeAttribute(Z);}for(var aa in X){if(T._.definition.fullMatch&&U.getStyle(aa)!=O(aa,X[aa],true))continue;Y=Y||!!U.getStyle(aa);U.removeStyle(aa);}if(Y)!f.$block[U.getName()]||T._.enterMode==2&&!U.hasAttributes()?I(U):U.renameNode(T._.enterMode==1?'p':'div');};function G(T,U){var V=T._.definition,W=V.attributes,X=V.styles,Y=N(T),Z=U.getElementsByTag(T.element);for(var aa=Z.count();--aa>=0;)F(T,Z.getItem(aa));for(var ab in Y){if(ab!=T.element){Z=U.getElementsByTag(ab); +for(aa=Z.count()-1;aa>=0;aa--){var ac=Z.getItem(aa);H(ac,Y[ab]);}}}};function H(T,U){var V=U&&U.attributes;if(V)for(var W=0;W0)H+=(F.$.offsetWidth||0)-(F.$.clientWidth||0);H+=4;F.setStyle('width',H+'px'); +v.element.addClass('cke_frameLoaded');var I=v.element.$.scrollHeight;if(c&&b.quirks&&I>0)I+=(F.$.offsetHeight||0)-(F.$.clientHeight||0);F.setStyle('height',I+'px');u._.currentBlock.element.setStyle('display','none').removeStyle('display');}else F.removeStyle('height');var J=u.element,K=J.getWindow(),L=K.getScrollPosition(),M=K.getViewPaneSize(),N={height:J.$.offsetHeight,width:J.$.offsetWidth};if(A?B<0:B+N.width>M.width+L.x)B+=N.width*(A?1:-1);if(C+N.height>M.height+L.y)C-=N.height;if(c){var O=new h(w.$.offsetParent),P=O;if(P.getName()=='html')P=P.getDocument().getBody();if(P.getComputedStyle('direction')=='rtl')if(b.ie8Compat)B-=w.getDocument().getDocumentElement().$.scrollLeft*2;else B-=O.$.scrollWidth-O.$.clientWidth;}var Q=w.getFirst(),R;if(R=Q.getCustomData('activePanel'))R.onHide&&R.onHide.call(this,1);Q.setCustomData('activePanel',this);w.setStyles({top:C+'px',left:B+'px'});w.setOpacity(1);},this);u.isLoaded?E():u.onLoad=E;e.setTimeout(function(){x.$.contentWindow.focus();this.allowBlur(true);},0,this);},b.air?200:0,this);this.visible=1;if(this.onShow)this.onShow.call(this);n=0;},hide:function(){var p=this;if(p.visible&&(!p.onHide||p.onHide.call(p)!==true)){p.hideChild();p.element.setStyle('display','none');p.visible=0;p.element.getFirst().removeCustomData('activePanel');}},allowBlur:function(p){var q=this._.panel;if(p!=undefined)q.allowBlur=p;return q.allowBlur;},showAsChild:function(p,q,r,s,t,u){if(this._.activeChild==p&&p._.panel._.offsetParentId==r.getId())return;this.hideChild();p.onHide=e.bind(function(){e.setTimeout(function(){if(!this._.focused)this.hide();},0,this);},this);this._.activeChild=p;this._.focused=false;p.showBlock(q,r,s,t,u);if(b.ie7Compat||b.ie8&&b.ie6Compat)setTimeout(function(){p.element.getChild(0).$.style.cssText+='';},100);},hideChild:function(){var p=this._.activeChild;if(p){delete p.onHide;delete this._.activeChild;p.hide();}}}});a.on('instanceDestroyed',function(){var p=e.isEmpty(a.instances);for(var q in m){var r=m[q];if(p)r.destroy();else r.element.hide();}p&&(m={});});})();j.add('menu',{beforeInit:function(m){var n=m.config.menu_groups.split(','),o=m._.menuGroups={},p=m._.menuItems={};for(var q=0;q'],B=r.length,C=B&&r[0].group;for(var D=0;D');C=E.group;}E.render(this,D,A);}A.push('');u.setHtml(A.join(''));k.fire('ready',this);if(this.parent)this.parent._.panel.showAsChild(t,this.id,n,o,p,q);else t.showBlock(this.id,n,o,p,q);s.fire('menuShow',[t]);},addListener:function(n){this._.listeners.push(n);},hide:function(){var n=this;n._.onHide&&n._.onHide();n._.panel&&n._.panel.hide();}}});function m(n){n.sort(function(o,p){if(o.groupp.group)return 1;return o.orderp.order?1:0;});};a.menuItem=e.createClass({$:function(n,o,p){var q=this;e.extend(q,p,{order:0,className:'cke_button_'+o});q.group=n._.menuGroups[q.group];q.editor=n;q.name=o;},proto:{render:function(n,o,p){var w=this;var q=n.id+String(o),r=typeof w.state=='undefined'?2:w.state,s=' cke_'+(r==1?'on':r==0?'disabled':'off'),t=w.label;if(w.className)s+=' '+w.className;var u=w.getItems;p.push(''+''+'');if(u)p.push('','&#',w.editor.lang.dir=='rtl'?'9668':'9658',';','');p.push(t,''); +}}});})();i.menu_groups='clipboard,form,tablecell,tablecellproperties,tablerow,tablecolumn,table,anchor,link,image,flash,checkbox,radio,textfield,hiddenfield,imagebutton,button,select,textarea,div';(function(){var m=function(o,p){return o._.modes&&o._.modes[p||o.mode];},n;j.add('editingblock',{init:function(o){if(!o.config.editingBlock)return;o.on('themeSpace',function(p){if(p.data.space=='contents')p.data.html+='
';});o.on('themeLoaded',function(){o.fireOnce('editingBlockReady');});o.on('uiReady',function(){o.setMode(o.config.startupMode);});o.on('afterSetData',function(){if(!n){function p(){n=true;m(o).loadData(o.getData());n=false;};if(o.mode)p();else o.on('mode',function(){p();o.removeListener('mode',arguments.callee);});}});o.on('beforeGetData',function(){if(!n&&o.mode){n=true;o.setData(m(o).getData(),null,1);n=false;}});o.on('getSnapshot',function(p){if(o.mode)p.data=m(o).getSnapshotData();});o.on('loadSnapshot',function(p){if(o.mode)m(o).loadSnapshotData(p.data);});o.on('mode',function(p){p.removeListener();b.webkit&&o.container.on('focus',function(){o.focus();});if(o.config.startupFocus)o.focus();setTimeout(function(){o.fireOnce('instanceReady');a.fire('instanceReady',null,o);},0);});o.on('destroy',function(){var p=this;if(p.mode)p._.modes[p.mode].unload(p.getThemeSpace('contents'));});}});a.editor.prototype.mode='';a.editor.prototype.addMode=function(o,p){p.name=o;(this._.modes||(this._.modes={}))[o]=p;};a.editor.prototype.setMode=function(o){this.fire('beforeSetMode',{newMode:o});var p,q=this.getThemeSpace('contents'),r=this.checkDirty();if(this.mode){if(o==this.mode)return;this.fire('beforeModeUnload');var s=m(this);p=s.getData();s.unload(q);this.mode='';}q.setHtml('');var t=m(this,o);if(!t)throw '[CKEDITOR.editor.setMode] Unknown mode "'+o+'".';if(!r)this.on('mode',function(){this.resetDirty();this.removeListener('mode',arguments.callee);});t.load(q,typeof p!='string'?this.getData():p);};a.editor.prototype.focus=function(){this.forceNextSelectionCheck();var o=m(this);if(o)o.focus();};})();i.startupMode='wysiwyg';i.editingBlock=true;(function(){function m(){var B=this;try{var y=B.getSelection();if(!y||!y.document.getWindow().$)return;var z=y.getStartElement(),A=new d.elementPath(z);if(!A.compare(B._.selectionPreviousPath)){B._.selectionPreviousPath=A;B.fire('selectionChange',{selection:y,path:A,element:z});}}catch(C){}};var n,o;function p(){o=true;if(n)return;q.call(this);n=e.setTimeout(q,200,this);};function q(){n=null;if(o){e.setTimeout(m,0,this); +o=false;}};function r(y){function z(C){return C&&C.type==1&&C.getName() in f.$removeEmpty;};var A=y.startContainer,B=y.startOffset;if(A.type==3)return false;return!e.trim(A.getHtml())?z(A):z(A.getChild(B-1))||z(A.getChild(B));};var s={modes:{wysiwyg:1,source:1},exec:function(y){switch(y.mode){case 'wysiwyg':y.document.$.execCommand('SelectAll',false,null);y.forceNextSelectionCheck();y.selectionChange();break;case 'source':var z=y.textarea.$;if(c)z.createTextRange().execCommand('SelectAll');else{z.selectionStart=0;z.selectionEnd=z.value.length;}z.focus();}},canUndo:false};function t(y){w(y);var z=y.createText('​');y.setCustomData('cke-fillingChar',z);return z;};function u(y){return y&&y.getCustomData('cke-fillingChar');};function v(y){var z=y&&u(y);if(z)if(z.getCustomData('ready'))w(y);else z.setCustomData('ready',1);};function w(y){var z=y&&y.removeCustomData('cke-fillingChar');if(z){z.setText(z.getText().replace(/\u200B/g,''));z=0;}};j.add('selection',{init:function(y){if(b.webkit){y.on('selectionChange',function(){v(y.document);});y.on('beforeSetMode',function(){w(y.document);});y.on('key',function(D){switch(D.data.keyCode){case 13:case 2000+13:case 37:case 39:case 8:w(y.document);}},null,null,10);var z,A;function B(){var D=y.document,E=u(D);if(E){var F=D.$.defaultView.getSelection();if(F.type=='Caret'&&F.anchorNode==E.$)A=1;z=E.getText();E.setText(z.replace(/\u200B/g,''));}};function C(){var D=y.document,E=u(D);if(E){E.setText(z);if(A){D.$.defaultView.getSelection().setPosition(E.$,E.getLength());A=0;}}};y.on('beforeUndoImage',B);y.on('afterUndoImage',C);y.on('beforeGetData',B,null,null,0);y.on('getData',C);}y.on('contentDom',function(){var D=y.document,E=D.getBody(),F=D.getDocumentElement();if(c){var G,H,I=1;E.on('focusin',function(M){if(M.data.$.srcElement.nodeName!='BODY')return;if(G){if(I){try{G.select();}catch(O){}var N=D.getCustomData('cke_locked_selection');if(N){N.unlock();N.lock();}}G=null;}});E.on('focus',function(){H=1;L();});E.on('beforedeactivate',function(M){if(M.data.$.toElement)return;H=0;I=1;});if(c&&b.version<8)y.on('blur',function(M){try{y.document&&y.document.$.selection.empty();}catch(N){}});F.on('mousedown',function(){I=0;});F.on('mouseup',function(){I=1;});if(c&&(b.ie7Compat||b.version<8||b.quirks))F.on('click',function(M){if(M.data.getTarget().getName()=='html')y.getSelection().getRanges()[0].select();});var J;E.on('mousedown',function(M){if(M.data.$.button==2){var N=y.document.$.selection;if(N.type=='None')J=y.window.getScrollPosition(); +}K();});E.on('mouseup',function(M){if(M.data.$.button==2&&J){y.document.$.documentElement.scrollLeft=J.x;y.document.$.documentElement.scrollTop=J.y;}J=null;H=1;setTimeout(function(){L(true);},0);});E.on('keydown',K);E.on('keyup',function(){H=1;L();});D.on('selectionchange',L);function K(){H=0;};function L(M){if(H){var N=y.document,O=y.getSelection(),P=O&&O.getNative();if(M&&P&&P.type=='None')if(!N.$.queryCommandEnabled('InsertImage')){e.setTimeout(L,50,this,true);return;}var Q;if(P&&P.type&&P.type!='Control'&&(Q=P.createRange())&&(Q=Q.parentElement())&&(Q=Q.nodeName)&&Q.toLowerCase() in {input:1,textarea:1})return;G=P&&O.getRanges()[0];p.call(y);}};}else{D.on('mouseup',p,y);D.on('keyup',p,y);}});y.on('contentDomUnload',y.forceNextSelectionCheck,y);y.addCommand('selectAll',s);y.ui.addButton('SelectAll',{label:y.lang.selectAll,command:'selectAll'});y.selectionChange=p;}});a.editor.prototype.getSelection=function(){return this.document&&this.document.getSelection();};a.editor.prototype.forceNextSelectionCheck=function(){delete this._.selectionPreviousPath;};g.prototype.getSelection=function(){var y=new d.selection(this);return!y||y.isInvalid?null:y;};a.SELECTION_NONE=1;a.SELECTION_TEXT=2;a.SELECTION_ELEMENT=3;d.selection=function(y){var B=this;var z=y.getCustomData('cke_locked_selection');if(z)return z;B.document=y;B.isLocked=0;B._={cache:{}};if(c){var A=B.getNative().createRange();if(!A||A.item&&A.item(0).ownerDocument!=B.document.$||A.parentElement&&A.parentElement().ownerDocument!=B.document.$)B.isInvalid=true;}return B;};var x={img:1,hr:1,li:1,table:1,tr:1,td:1,th:1,embed:1,object:1,ol:1,ul:1,a:1,input:1,form:1,select:1,textarea:1,button:1,fieldset:1,th:1,thead:1,tfoot:1};d.selection.prototype={getNative:c?function(){return this._.cache.nativeSel||(this._.cache.nativeSel=this.document.$.selection);}:function(){return this._.cache.nativeSel||(this._.cache.nativeSel=this.document.getWindow().$.getSelection());},getType:c?function(){var y=this._.cache;if(y.type)return y.type;var z=1;try{var A=this.getNative(),B=A.type;if(B=='Text')z=2;if(B=='Control')z=3;if(A.createRange().parentElement)z=2;}catch(C){}return y.type=z;}:function(){var y=this._.cache;if(y.type)return y.type;var z=2,A=this.getNative();if(!A)z=1;else if(A.rangeCount==1){var B=A.getRangeAt(0),C=B.startContainer;if(C==B.endContainer&&C.nodeType==1&&B.endOffset-B.startOffset==1&&x[C.childNodes[B.startOffset].nodeName.toLowerCase()])z=3;}return y.type=z;},getRanges:(function(){var y=c?(function(){function z(B){return new d.node(B).getIndex(); +};var A=function(B,C){B=B.duplicate();B.collapse(C);var D=B.parentElement(),E=D.ownerDocument;if(!D.hasChildNodes())return{container:D,offset:0};var F=D.children,G,H,I=B.duplicate(),J=0,K=F.length-1,L=-1,M,N;while(J<=K){L=Math.floor((J+K)/2);G=F[L];I.moveToElementText(G);M=I.compareEndPoints('StartToStart',B);if(M>0)K=L-1;else if(M<0)J=L+1;else if(b.ie9Compat&&G.tagName=='BR'){var O='cke_range_marker';B.execCommand('CreateBookmark',false,O);G=E.getElementsByName(O)[0];var P=z(G);D.removeChild(G);return{container:D,offset:P};}else return{container:D,offset:z(G)};}if(L==-1||L==F.length-1&&M<0){I.moveToElementText(D);I.setEndPoint('StartToStart',B);N=I.text.replace(/(\r\n|\r)/g,'\n').length;F=D.childNodes;if(!N){G=F[F.length-1];if(G.nodeType==1)return{container:D,offset:F.length};else return{container:G,offset:G.nodeValue.length};}var Q=F.length;while(N>0)N-=F[--Q].nodeValue.length;return{container:F[Q],offset:-N};}else{I.collapse(M>0?true:false);I.setEndPoint(M>0?'StartToStart':'EndToStart',B);N=I.text.replace(/(\r\n|\r)/g,'\n').length;if(!N)return{container:D,offset:z(G)+(M>0?0:1)};while(N>0)try{H=G[M>0?'previousSibling':'nextSibling'];N-=H.nodeValue.length;G=H;}catch(R){return{container:D,offset:z(G)};}return{container:G,offset:M>0?-N:G.nodeValue.length+N};}};return function(){var L=this;var B=L.getNative(),C=B&&B.createRange(),D=L.getType(),E;if(!B)return[];if(D==2){E=new d.range(L.document);var F=A(C,true);E.setStart(new d.node(F.container),F.offset);F=A(C);E.setEnd(new d.node(F.container),F.offset);if(E.endContainer.getPosition(E.startContainer)&4&&E.endOffset<=E.startContainer.getIndex())E.collapse();return[E];}else if(D==3){var G=[];for(var H=0;H=F.getLength())J.setStartAfter(F);else J.setStartBefore(F);if(G&&G.type==3)if(!I)J.setEndBefore(G);else J.setEndAfter(G);var L=new d.walker(J);L.evaluator=function(M){if(M.type==1&&M.isReadOnly()){var N=D.clone();D.setEndBefore(M);if(D.collapsed)B.splice(C--,1);if(!(M.getPosition(J.endContainer)&16)){N.setStartAfter(M);if(!N.collapsed)B.splice(C+1,0,N);}return true;}return false;};L.next();}}return A.ranges;};})(),getStartElement:function(){var F=this;var y=F._.cache;if(y.startElement!==undefined)return y.startElement;var z,A=F.getNative();switch(F.getType()){case 3:return F.getSelectedElement();case 2:var B=F.getRanges()[0];if(B){if(!B.collapsed){B.optimize();while(1){var C=B.startContainer,D=B.startOffset;if(D==(C.getChildCount?C.getChildCount():C.getLength())&&!C.isBlockBoundary())B.setStartAfter(C);else break;}z=B.startContainer;if(z.type!=1)return z.getParent();z=z.getChild(B.startOffset);if(!z||z.type!=1)z=B.startContainer;else{var E=z.getFirst();while(E&&E.type==1){z=E;E=E.getFirst();}}}else{z=B.startContainer;if(z.type!=1)z=z.getParent();}z=z.$;}}return y.startElement=z?new h(z):null;},getSelectedElement:function(){var y=this._.cache;if(y.selectedElement!==undefined)return y.selectedElement;var z=this,A=e.tryThese(function(){return z.getNative().createRange().item(0);},function(){var B=z.getRanges()[0],C,D;for(var E=2;E&&!((C=B.getEnclosedNode())&&C.type==1&&x[C.getName()]&&(D=C));E--)B.shrink(1);return D.$;});return y.selectedElement=A?new h(A):null;},lock:function(){var y=this;y.getRanges();y.getStartElement();y.getSelectedElement();y._.cache.nativeSel={};y.isLocked=1;y.document.setCustomData('cke_locked_selection',y);},unlock:function(y){var D=this;var z=D.document,A=z.getCustomData('cke_locked_selection');if(A){z.setCustomData('cke_locked_selection',null);if(y){var B=A.getSelectedElement(),C=!B&&A.getRanges();D.isLocked=0;D.reset();z.getBody().focus();if(B)D.selectElement(B);else D.selectRanges(C);}}if(!A||!y){D.isLocked=0;D.reset();}},reset:function(){this._.cache={};},selectElement:function(y){var A=this;if(A.isLocked){var z=new d.range(A.document);z.setStartBefore(y);z.setEndAfter(y);A._.cache.selectedElement=y;A._.cache.startElement=y;A._.cache.ranges=new d.rangeList(z);A._.cache.type=3;return;}z=new d.range(y.getDocument());z.setStartBefore(y);z.setEndAfter(y);z.select();A.document.fire('selectionchange'); +A.reset();},selectRanges:function(y){var M=this;if(M.isLocked){M._.cache.selectedElement=null;M._.cache.startElement=y[0]&&y[0].getTouchedStartNode();M._.cache.ranges=new d.rangeList(y);M._.cache.type=2;return;}if(c){if(y.length>1){var z=y[y.length-1];y[0].setEnd(z.endContainer,z.endOffset);y.length=1;}if(y[0])y[0].select();M.reset();}else{var A=M.getNative();if(!A)return;if(y.length){A.removeAllRanges();b.webkit&&w(M.document);}for(var B=0;B=0){H.collapse(1);I.setEnd(H.endContainer.$,H.endOffset);}else throw N;}A.addRange(I);}M.reset();}},createBookmarks:function(y){return this.getRanges().createBookmarks(y);},createBookmarks2:function(y){return this.getRanges().createBookmarks2(y);},selectBookmarks:function(y){var z=[];for(var A=0;A','','',this.label,'','=10900&&!o.hc?'':" href=\"javascript:void('"+this.label+"')\"",' role="button" aria-labelledby="',p,'_label" aria-describedby="',p,'_text" aria-haspopup="true"');if(b.opera||b.gecko&&b.mac)n.push(' onkeypress="return false;"');if(b.gecko)n.push(' onblur="this.style.cssText = this.style.cssText;"');n.push(' onkeydown="CKEDITOR.tools.callFunction( ',s,', event, this );" onclick="CKEDITOR.tools.callFunction(',q,', this); return false;">'+this.label+''+''+''+(b.hc?'▼':b.air?' ':'')+''+''+''+'');if(this.onRender)this.onRender();return r;},createPanel:function(m){if(this._.panel)return;var n=this._.panelDefinition,o=this._.panelDefinition.block,p=n.parent||a.document.getBody(),q=new k.floatPanel(m,p,n),r=q.addListBlock(this.id,o),s=this;q.onShow=function(){if(s.className)this.element.getFirst().addClass(s.className+'_panel');s.setState(1);r.focus(!s.multiSelect&&s.getValue());s._.on=1;if(s.onOpen)s.onOpen();};q.onHide=function(t){if(s.className)this.element.getFirst().removeClass(s.className+'_panel'); +s.setState(s.modes&&s.modes[m.mode]?2:0);s._.on=0;if(!t&&s.onClose)s.onClose();};q.onEscape=function(){q.hide();s.document.getById('cke_'+s.id).getFirst().getNext().focus();};r.onClick=function(t,u){s.document.getWindow().focus();if(s.onClick)s.onClick.call(s,t,u);if(u)s.setValue(t,s._.items[t]);else s.setValue('');q.hide();};this._.panel=q;this._.list=r;q.getBlock(this.id).onHide=function(){s._.on=0;s.setState(2);};if(this.init)this.init();},setValue:function(m,n){var p=this;p._.value=m;var o=p.document.getById('cke_'+p.id+'_text');if(o){if(!(m||n)){n=p.label;o.addClass('cke_inline_label');}else o.removeClass('cke_inline_label');o.setHtml(typeof n!='undefined'?n:m);}},getValue:function(){return this._.value||'';},unmarkAll:function(){this._.list.unmarkAll();},mark:function(m){this._.list.mark(m);},hideItem:function(m){this._.list.hideItem(m);},hideGroup:function(m){this._.list.hideGroup(m);},showAll:function(){this._.list.showAll();},add:function(m,n,o){this._.items[m]=o||m;this._.list.add(m,n,o);},startGroup:function(m){this._.list.startGroup(m);},commit:function(){var m=this;if(!m._.committed){m._.list.commit();m._.committed=1;k.fire('ready',m);}m._.committed=1;},setState:function(m){var n=this;if(n._.state==m)return;n.document.getById('cke_'+n.id).setState(m);n._.state=m;}}});k.prototype.addRichCombo=function(m,n){this.add(m,3,n);};j.add('htmlwriter');a.htmlWriter=e.createClass({base:a.htmlParser.basicWriter,$:function(){var o=this;o.base();o.indentationChars='\t';o.selfClosingEnd=' />';o.lineBreakChars='\n';o.forceSimpleAmpersand=0;o.sortAttributes=1;o._.indent=0;o._.indentation='';o._.inPre=0;o._.rules={};var m=f;for(var n in e.extend({},m.$nonBodyContent,m.$block,m.$listItem,m.$tableContent))o.setRules(n,{indent:1,breakBeforeOpen:1,breakAfterOpen:1,breakBeforeClose:!m[n]['#'],breakAfterClose:1});o.setRules('br',{breakAfterOpen:1});o.setRules('title',{indent:0,breakAfterOpen:0});o.setRules('style',{indent:0,breakBeforeClose:1});o.setRules('pre',{indent:0});},proto:{openTag:function(m,n){var p=this;var o=p._.rules[m];if(p._.indent)p.indentation();else if(o&&o.breakBeforeOpen){p.lineBreak();p.indentation();}p._.output.push('<',m);},openTagClose:function(m,n){var p=this;var o=p._.rules[m];if(n)p._.output.push(p.selfClosingEnd);else{p._.output.push('>');if(o&&o.indent)p._.indentation+=p.indentationChars;}if(o&&o.breakAfterOpen)p.lineBreak();m=='pre'&&(p._.inPre=1);},attribute:function(m,n){if(typeof n=='string'){this.forceSimpleAmpersand&&(n=n.replace(/&/g,'&')); +n=e.htmlEncodeAttr(n);}this._.output.push(' ',m,'="',n,'"');},closeTag:function(m){var o=this;var n=o._.rules[m];if(n&&n.indent)o._.indentation=o._.indentation.substr(o.indentationChars.length);if(o._.indent)o.indentation();else if(n&&n.breakBeforeClose){o.lineBreak();o.indentation();}o._.output.push('');m=='pre'&&(o._.inPre=0);if(n&&n.breakAfterClose)o.lineBreak();},text:function(m){var n=this;if(n._.indent){n.indentation();!n._.inPre&&(m=e.ltrim(m));}n._.output.push(m);},comment:function(m){if(this._.indent)this.indentation();this._.output.push('');},lineBreak:function(){var m=this;if(!m._.inPre&&m._.output.length>0)m._.output.push(m.lineBreakChars);m._.indent=1;},indentation:function(){var m=this;if(!m._.inPre)m._.output.push(m._.indentation);m._.indent=0;},setRules:function(m,n){var o=this._.rules[m];if(o)e.extend(o,n,true);else this._.rules[m]=n;}}});j.add('menubutton',{requires:['button','menu'],beforeInit:function(m){m.ui.addHandler(5,k.menuButton.handler);}});a.UI_MENUBUTTON=5;(function(){var m=function(n){var o=this._;if(o.state===0)return;o.previousState=o.state;var p=o.menu;if(!p){p=o.menu=new a.menu(n,{panel:{className:n.skinClass+' cke_contextmenu',attributes:{'aria-label':n.lang.common.options}}});p.onHide=e.bind(function(){this.setState(this.modes&&this.modes[n.mode]?o.previousState:0);},this);if(this.onMenu)p.addListener(this.onMenu);}if(o.on){p.hide();return;}this.setState(1);p.show(a.document.getById(this._.id),4);};k.menuButton=e.createClass({base:k.button,$:function(n){var o=n.panel;delete n.panel;this.base(n);this.hasArrow=true;this.click=m;},statics:{handler:{create:function(n){return new k.menuButton(n);}}}});})();j.add('dialogui');(function(){var m=function(u){var x=this;x._||(x._={});x._['default']=x._.initValue=u['default']||'';x._.required=u.required||false;var v=[x._];for(var w=1;w',v.label,'','');else{var D={type:'hbox',widths:v.widths,padding:0,children:[{type:'html',html:'