From 7149634bd7d8152f0570bd9e399040a73f2a2ff4 Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Tue, 24 Nov 2020 09:56:00 -0500 Subject: [PATCH] chore(oc): remove unused code of OpenChange --- Attic/Fixtures/bad_hex_and_cr.rtf | 1 - Attic/Fixtures/cyr_event_ru_editor.rtf | 1 - Attic/Fixtures/escapes.rtf | 6 - Attic/Fixtures/mini_russian.rtf | 1 - Attic/Fixtures/spanish_accents.rtf | 1 - Attic/Fixtures/zentyal_crash_2058.rtf | 21 - Attic/Fixtures/zentyal_crash_2089.rtf | 1 - Attic/Fixtures/zentyal_crash_6330.rtf | 33 - Attic/Fixtures/zentyal_crash_8346.rtf | 378 --- Attic/OpenChange/COPYING | 674 ------ Attic/OpenChange/Codepages.h | 34 - Attic/OpenChange/Codepages.m | 214 -- Attic/OpenChange/GNUmakefile | 200 -- Attic/OpenChange/GNUmakefile.preamble | 8 - Attic/OpenChange/MAPIApplication.h | 44 - Attic/OpenChange/MAPIApplication.m | 101 - Attic/OpenChange/MAPIStoreActiveTables.h | 47 - Attic/OpenChange/MAPIStoreActiveTables.m | 198 -- .../OpenChange/MAPIStoreAppointmentWrapper.h | 177 -- .../OpenChange/MAPIStoreAppointmentWrapper.m | 2115 ----------------- Attic/OpenChange/MAPIStoreAttachment.h | 59 - Attic/OpenChange/MAPIStoreAttachment.m | 194 -- Attic/OpenChange/MAPIStoreAttachmentTable.h | 31 - Attic/OpenChange/MAPIStoreAttachmentTable.m | 73 - Attic/OpenChange/MAPIStoreAuthenticator.h | 54 - Attic/OpenChange/MAPIStoreAuthenticator.m | 79 - Attic/OpenChange/MAPIStoreCalTaskFolder.h | 35 - Attic/OpenChange/MAPIStoreCalTaskFolder.m | 101 - Attic/OpenChange/MAPIStoreCalTaskMessage.h | 40 - Attic/OpenChange/MAPIStoreCalTaskMessage.m | 107 - .../OpenChange/MAPIStoreCalendarAttachment.h | 43 - .../OpenChange/MAPIStoreCalendarAttachment.m | 255 -- Attic/OpenChange/MAPIStoreCalendarContext.h | 32 - Attic/OpenChange/MAPIStoreCalendarContext.m | 64 - .../MAPIStoreCalendarEmbeddedMessage.h | 34 - .../MAPIStoreCalendarEmbeddedMessage.m | 215 -- Attic/OpenChange/MAPIStoreCalendarFolder.h | 32 - Attic/OpenChange/MAPIStoreCalendarFolder.m | 226 -- Attic/OpenChange/MAPIStoreCalendarMessage.h | 40 - Attic/OpenChange/MAPIStoreCalendarMessage.m | 669 ------ .../MAPIStoreCalendarMessageTable.h | 32 - .../MAPIStoreCalendarMessageTable.m | 193 -- .../OpenChange/MAPIStoreContactsAttachment.h | 41 - .../OpenChange/MAPIStoreContactsAttachment.m | 197 -- Attic/OpenChange/MAPIStoreContactsContext.h | 32 - Attic/OpenChange/MAPIStoreContactsContext.m | 59 - Attic/OpenChange/MAPIStoreContactsFolder.h | 32 - Attic/OpenChange/MAPIStoreContactsFolder.m | 157 -- Attic/OpenChange/MAPIStoreContactsMessage.h | 35 - Attic/OpenChange/MAPIStoreContactsMessage.m | 1619 ------------- .../MAPIStoreContactsMessageTable.h | 31 - .../MAPIStoreContactsMessageTable.m | 231 -- Attic/OpenChange/MAPIStoreContext.h | 125 - Attic/OpenChange/MAPIStoreContext.m | 644 ----- Attic/OpenChange/MAPIStoreDBBaseContext.h | 32 - Attic/OpenChange/MAPIStoreDBBaseContext.m | 114 - Attic/OpenChange/MAPIStoreDBFolder.h | 43 - Attic/OpenChange/MAPIStoreDBFolder.m | 382 --- Attic/OpenChange/MAPIStoreDBFolderTable.h | 31 - Attic/OpenChange/MAPIStoreDBFolderTable.m | 36 - Attic/OpenChange/MAPIStoreDBMessage.h | 31 - Attic/OpenChange/MAPIStoreDBMessage.m | 495 ---- Attic/OpenChange/MAPIStoreDBMessageTable.h | 31 - Attic/OpenChange/MAPIStoreDBMessageTable.m | 133 -- Attic/OpenChange/MAPIStoreEmbeddedMessage.h | 33 - Attic/OpenChange/MAPIStoreEmbeddedMessage.m | 154 -- Attic/OpenChange/MAPIStoreFAIMessage.h | 31 - Attic/OpenChange/MAPIStoreFAIMessage.m | 81 - Attic/OpenChange/MAPIStoreFAIMessageTable.h | 31 - Attic/OpenChange/MAPIStoreFAIMessageTable.m | 101 - Attic/OpenChange/MAPIStoreFallbackContext.h | 32 - Attic/OpenChange/MAPIStoreFallbackContext.m | 112 - Attic/OpenChange/MAPIStoreFolder.h | 209 -- Attic/OpenChange/MAPIStoreFolder.m | 1897 --------------- Attic/OpenChange/MAPIStoreFolderTable.h | 31 - Attic/OpenChange/MAPIStoreFolderTable.m | 118 - Attic/OpenChange/MAPIStoreGCSBaseContext.h | 37 - Attic/OpenChange/MAPIStoreGCSBaseContext.m | 145 -- Attic/OpenChange/MAPIStoreGCSFolder.h | 64 - Attic/OpenChange/MAPIStoreGCSFolder.m | 893 ------- Attic/OpenChange/MAPIStoreGCSMessage.h | 44 - Attic/OpenChange/MAPIStoreGCSMessage.m | 264 -- Attic/OpenChange/MAPIStoreGCSMessageTable.h | 36 - Attic/OpenChange/MAPIStoreGCSMessageTable.m | 260 -- Attic/OpenChange/MAPIStoreMIME.h | 37 - Attic/OpenChange/MAPIStoreMIME.m | 154 -- Attic/OpenChange/MAPIStoreMailAttachment.h | 41 - Attic/OpenChange/MAPIStoreMailAttachment.m | 204 -- Attic/OpenChange/MAPIStoreMailContext.h | 37 - Attic/OpenChange/MAPIStoreMailContext.m | 312 --- Attic/OpenChange/MAPIStoreMailFolder.h | 72 - Attic/OpenChange/MAPIStoreMailFolder.m | 1777 -------------- Attic/OpenChange/MAPIStoreMailFolderTable.h | 31 - Attic/OpenChange/MAPIStoreMailFolderTable.m | 42 - Attic/OpenChange/MAPIStoreMailMessage.h | 88 - Attic/OpenChange/MAPIStoreMailMessage.m | 2019 ---------------- Attic/OpenChange/MAPIStoreMailMessageTable.h | 35 - Attic/OpenChange/MAPIStoreMailMessageTable.m | 359 --- .../OpenChange/MAPIStoreMailVolatileMessage.h | 34 - .../OpenChange/MAPIStoreMailVolatileMessage.m | 1190 ---------- Attic/OpenChange/MAPIStoreMapping.h | 68 - Attic/OpenChange/MAPIStoreMapping.m | 327 --- Attic/OpenChange/MAPIStoreMessage.h | 90 - Attic/OpenChange/MAPIStoreMessage.m | 1018 -------- Attic/OpenChange/MAPIStoreMessageTable.h | 35 - Attic/OpenChange/MAPIStoreMessageTable.m | 93 - Attic/OpenChange/MAPIStoreNotesContext.h | 32 - Attic/OpenChange/MAPIStoreNotesContext.m | 77 - Attic/OpenChange/MAPIStoreNotesFolder.h | 31 - Attic/OpenChange/MAPIStoreNotesFolder.m | 41 - Attic/OpenChange/MAPIStoreNotesMessage.h | 31 - Attic/OpenChange/MAPIStoreNotesMessage.m | 56 - Attic/OpenChange/MAPIStoreObject.h | 103 - Attic/OpenChange/MAPIStoreObject.m | 395 --- Attic/OpenChange/MAPIStoreObjectProxy.h | 41 - Attic/OpenChange/MAPIStoreObjectProxy.m | 67 - Attic/OpenChange/MAPIStorePermissionsTable.h | 55 - Attic/OpenChange/MAPIStorePermissionsTable.m | 195 -- Attic/OpenChange/MAPIStoreRecurrenceUtils.h | 58 - Attic/OpenChange/MAPIStoreRecurrenceUtils.m | 483 ---- Attic/OpenChange/MAPIStoreSOGo.m | 1751 -------------- Attic/OpenChange/MAPIStoreSOGoObject.h | 86 - Attic/OpenChange/MAPIStoreSOGoObject.m | 232 -- Attic/OpenChange/MAPIStoreSamDBUtils.h | 37 - Attic/OpenChange/MAPIStoreSamDBUtils.m | 183 -- Attic/OpenChange/MAPIStoreSharingMessage.h | 101 - Attic/OpenChange/MAPIStoreSharingMessage.m | 463 ---- Attic/OpenChange/MAPIStoreTable.h | 129 - Attic/OpenChange/MAPIStoreTable.m | 889 ------- Attic/OpenChange/MAPIStoreTasksContext.h | 32 - Attic/OpenChange/MAPIStoreTasksContext.m | 63 - Attic/OpenChange/MAPIStoreTasksFolder.h | 32 - Attic/OpenChange/MAPIStoreTasksFolder.m | 201 -- Attic/OpenChange/MAPIStoreTasksMessage.h | 32 - Attic/OpenChange/MAPIStoreTasksMessage.m | 580 ----- Attic/OpenChange/MAPIStoreTasksMessageTable.h | 32 - Attic/OpenChange/MAPIStoreTasksMessageTable.m | 168 -- Attic/OpenChange/MAPIStoreTypes.h | 65 - Attic/OpenChange/MAPIStoreTypes.m | 369 --- Attic/OpenChange/MAPIStoreUserContext.h | 96 - Attic/OpenChange/MAPIStoreUserContext.m | 414 ---- Attic/OpenChange/NSArray+MAPIStore.h | 51 - Attic/OpenChange/NSArray+MAPIStore.m | 308 --- Attic/OpenChange/NSData+MAPIStore.h | 62 - Attic/OpenChange/NSData+MAPIStore.m | 291 --- Attic/OpenChange/NSDate+MAPIStore.h | 46 - Attic/OpenChange/NSDate+MAPIStore.m | 209 -- Attic/OpenChange/NSObject+MAPIStore.h | 76 - Attic/OpenChange/NSObject+MAPIStore.m | 270 --- Attic/OpenChange/NSObject+PropertyList.h | 64 - Attic/OpenChange/NSObject+PropertyList.m | 137 -- Attic/OpenChange/NSString+MAPIStore.h | 41 - Attic/OpenChange/NSString+MAPIStore.m | 201 -- Attic/OpenChange/NSValue+MAPIStore.h | 38 - Attic/OpenChange/NSValue+MAPIStore.m | 79 - Attic/OpenChange/RTFHandler.h | 141 -- Attic/OpenChange/RTFHandler.m | 1481 ------------ .../OpenChange/SOGoCacheGCSObject+MAPIStore.h | 32 - .../OpenChange/SOGoCacheGCSObject+MAPIStore.m | 68 - Attic/OpenChange/SOGoMAPIDBMessage.h | 32 - Attic/OpenChange/SOGoMAPIDBMessage.m | 61 - Attic/OpenChange/classes.txt | 26 - .../code-MAPIStorePropertySelectors.h | 27 - .../code-MAPIStorePropertySelectors.m | 73 - Attic/OpenChange/dbmsgreader.m | 160 -- Attic/OpenChange/gen-charset-table.py | 84 - Attic/OpenChange/gen-property-selectors.py | 266 --- Attic/OpenChange/iCalEvent+MAPIStore.h | 44 - Attic/OpenChange/iCalEvent+MAPIStore.m | 587 ----- Attic/OpenChange/iCalTimeZone+MAPIStore.h | 42 - Attic/OpenChange/iCalTimeZone+MAPIStore.m | 377 --- Attic/OpenChange/plreader.m | 99 - Attic/OpenChange/product.plist | 3 - Attic/OpenChange/samba-get-config.py | 9 - ...GoNativeOutlookConfigurationGuide.asciidoc | 878 ------- Attic/TestRTFHandler.m | 317 --- 176 files changed, 38330 deletions(-) delete mode 100644 Attic/Fixtures/bad_hex_and_cr.rtf delete mode 100644 Attic/Fixtures/cyr_event_ru_editor.rtf delete mode 100644 Attic/Fixtures/escapes.rtf delete mode 100644 Attic/Fixtures/mini_russian.rtf delete mode 100644 Attic/Fixtures/spanish_accents.rtf delete mode 100644 Attic/Fixtures/zentyal_crash_2058.rtf delete mode 100644 Attic/Fixtures/zentyal_crash_2089.rtf delete mode 100644 Attic/Fixtures/zentyal_crash_6330.rtf delete mode 100644 Attic/Fixtures/zentyal_crash_8346.rtf delete mode 100644 Attic/OpenChange/COPYING delete mode 100644 Attic/OpenChange/Codepages.h delete mode 100644 Attic/OpenChange/Codepages.m delete mode 100644 Attic/OpenChange/GNUmakefile delete mode 100644 Attic/OpenChange/GNUmakefile.preamble delete mode 100644 Attic/OpenChange/MAPIApplication.h delete mode 100644 Attic/OpenChange/MAPIApplication.m delete mode 100644 Attic/OpenChange/MAPIStoreActiveTables.h delete mode 100644 Attic/OpenChange/MAPIStoreActiveTables.m delete mode 100644 Attic/OpenChange/MAPIStoreAppointmentWrapper.h delete mode 100644 Attic/OpenChange/MAPIStoreAppointmentWrapper.m delete mode 100644 Attic/OpenChange/MAPIStoreAttachment.h delete mode 100644 Attic/OpenChange/MAPIStoreAttachment.m delete mode 100644 Attic/OpenChange/MAPIStoreAttachmentTable.h delete mode 100644 Attic/OpenChange/MAPIStoreAttachmentTable.m delete mode 100644 Attic/OpenChange/MAPIStoreAuthenticator.h delete mode 100644 Attic/OpenChange/MAPIStoreAuthenticator.m delete mode 100644 Attic/OpenChange/MAPIStoreCalTaskFolder.h delete mode 100644 Attic/OpenChange/MAPIStoreCalTaskFolder.m delete mode 100644 Attic/OpenChange/MAPIStoreCalTaskMessage.h delete mode 100644 Attic/OpenChange/MAPIStoreCalTaskMessage.m delete mode 100644 Attic/OpenChange/MAPIStoreCalendarAttachment.h delete mode 100644 Attic/OpenChange/MAPIStoreCalendarAttachment.m delete mode 100644 Attic/OpenChange/MAPIStoreCalendarContext.h delete mode 100644 Attic/OpenChange/MAPIStoreCalendarContext.m delete mode 100644 Attic/OpenChange/MAPIStoreCalendarEmbeddedMessage.h delete mode 100644 Attic/OpenChange/MAPIStoreCalendarEmbeddedMessage.m delete mode 100644 Attic/OpenChange/MAPIStoreCalendarFolder.h delete mode 100644 Attic/OpenChange/MAPIStoreCalendarFolder.m delete mode 100644 Attic/OpenChange/MAPIStoreCalendarMessage.h delete mode 100644 Attic/OpenChange/MAPIStoreCalendarMessage.m delete mode 100644 Attic/OpenChange/MAPIStoreCalendarMessageTable.h delete mode 100644 Attic/OpenChange/MAPIStoreCalendarMessageTable.m delete mode 100644 Attic/OpenChange/MAPIStoreContactsAttachment.h delete mode 100644 Attic/OpenChange/MAPIStoreContactsAttachment.m delete mode 100644 Attic/OpenChange/MAPIStoreContactsContext.h delete mode 100644 Attic/OpenChange/MAPIStoreContactsContext.m delete mode 100644 Attic/OpenChange/MAPIStoreContactsFolder.h delete mode 100644 Attic/OpenChange/MAPIStoreContactsFolder.m delete mode 100644 Attic/OpenChange/MAPIStoreContactsMessage.h delete mode 100644 Attic/OpenChange/MAPIStoreContactsMessage.m delete mode 100644 Attic/OpenChange/MAPIStoreContactsMessageTable.h delete mode 100644 Attic/OpenChange/MAPIStoreContactsMessageTable.m delete mode 100644 Attic/OpenChange/MAPIStoreContext.h delete mode 100644 Attic/OpenChange/MAPIStoreContext.m delete mode 100644 Attic/OpenChange/MAPIStoreDBBaseContext.h delete mode 100644 Attic/OpenChange/MAPIStoreDBBaseContext.m delete mode 100644 Attic/OpenChange/MAPIStoreDBFolder.h delete mode 100644 Attic/OpenChange/MAPIStoreDBFolder.m delete mode 100644 Attic/OpenChange/MAPIStoreDBFolderTable.h delete mode 100644 Attic/OpenChange/MAPIStoreDBFolderTable.m delete mode 100644 Attic/OpenChange/MAPIStoreDBMessage.h delete mode 100644 Attic/OpenChange/MAPIStoreDBMessage.m delete mode 100644 Attic/OpenChange/MAPIStoreDBMessageTable.h delete mode 100644 Attic/OpenChange/MAPIStoreDBMessageTable.m delete mode 100644 Attic/OpenChange/MAPIStoreEmbeddedMessage.h delete mode 100644 Attic/OpenChange/MAPIStoreEmbeddedMessage.m delete mode 100644 Attic/OpenChange/MAPIStoreFAIMessage.h delete mode 100644 Attic/OpenChange/MAPIStoreFAIMessage.m delete mode 100644 Attic/OpenChange/MAPIStoreFAIMessageTable.h delete mode 100644 Attic/OpenChange/MAPIStoreFAIMessageTable.m delete mode 100644 Attic/OpenChange/MAPIStoreFallbackContext.h delete mode 100644 Attic/OpenChange/MAPIStoreFallbackContext.m delete mode 100644 Attic/OpenChange/MAPIStoreFolder.h delete mode 100644 Attic/OpenChange/MAPIStoreFolder.m delete mode 100644 Attic/OpenChange/MAPIStoreFolderTable.h delete mode 100644 Attic/OpenChange/MAPIStoreFolderTable.m delete mode 100644 Attic/OpenChange/MAPIStoreGCSBaseContext.h delete mode 100644 Attic/OpenChange/MAPIStoreGCSBaseContext.m delete mode 100644 Attic/OpenChange/MAPIStoreGCSFolder.h delete mode 100644 Attic/OpenChange/MAPIStoreGCSFolder.m delete mode 100644 Attic/OpenChange/MAPIStoreGCSMessage.h delete mode 100644 Attic/OpenChange/MAPIStoreGCSMessage.m delete mode 100644 Attic/OpenChange/MAPIStoreGCSMessageTable.h delete mode 100644 Attic/OpenChange/MAPIStoreGCSMessageTable.m delete mode 100644 Attic/OpenChange/MAPIStoreMIME.h delete mode 100644 Attic/OpenChange/MAPIStoreMIME.m delete mode 100644 Attic/OpenChange/MAPIStoreMailAttachment.h delete mode 100644 Attic/OpenChange/MAPIStoreMailAttachment.m delete mode 100644 Attic/OpenChange/MAPIStoreMailContext.h delete mode 100644 Attic/OpenChange/MAPIStoreMailContext.m delete mode 100644 Attic/OpenChange/MAPIStoreMailFolder.h delete mode 100644 Attic/OpenChange/MAPIStoreMailFolder.m delete mode 100644 Attic/OpenChange/MAPIStoreMailFolderTable.h delete mode 100644 Attic/OpenChange/MAPIStoreMailFolderTable.m delete mode 100644 Attic/OpenChange/MAPIStoreMailMessage.h delete mode 100644 Attic/OpenChange/MAPIStoreMailMessage.m delete mode 100644 Attic/OpenChange/MAPIStoreMailMessageTable.h delete mode 100644 Attic/OpenChange/MAPIStoreMailMessageTable.m delete mode 100644 Attic/OpenChange/MAPIStoreMailVolatileMessage.h delete mode 100644 Attic/OpenChange/MAPIStoreMailVolatileMessage.m delete mode 100644 Attic/OpenChange/MAPIStoreMapping.h delete mode 100644 Attic/OpenChange/MAPIStoreMapping.m delete mode 100644 Attic/OpenChange/MAPIStoreMessage.h delete mode 100644 Attic/OpenChange/MAPIStoreMessage.m delete mode 100644 Attic/OpenChange/MAPIStoreMessageTable.h delete mode 100644 Attic/OpenChange/MAPIStoreMessageTable.m delete mode 100644 Attic/OpenChange/MAPIStoreNotesContext.h delete mode 100644 Attic/OpenChange/MAPIStoreNotesContext.m delete mode 100644 Attic/OpenChange/MAPIStoreNotesFolder.h delete mode 100644 Attic/OpenChange/MAPIStoreNotesFolder.m delete mode 100644 Attic/OpenChange/MAPIStoreNotesMessage.h delete mode 100644 Attic/OpenChange/MAPIStoreNotesMessage.m delete mode 100644 Attic/OpenChange/MAPIStoreObject.h delete mode 100644 Attic/OpenChange/MAPIStoreObject.m delete mode 100644 Attic/OpenChange/MAPIStoreObjectProxy.h delete mode 100644 Attic/OpenChange/MAPIStoreObjectProxy.m delete mode 100644 Attic/OpenChange/MAPIStorePermissionsTable.h delete mode 100644 Attic/OpenChange/MAPIStorePermissionsTable.m delete mode 100644 Attic/OpenChange/MAPIStoreRecurrenceUtils.h delete mode 100644 Attic/OpenChange/MAPIStoreRecurrenceUtils.m delete mode 100644 Attic/OpenChange/MAPIStoreSOGo.m delete mode 100644 Attic/OpenChange/MAPIStoreSOGoObject.h delete mode 100644 Attic/OpenChange/MAPIStoreSOGoObject.m delete mode 100644 Attic/OpenChange/MAPIStoreSamDBUtils.h delete mode 100644 Attic/OpenChange/MAPIStoreSamDBUtils.m delete mode 100644 Attic/OpenChange/MAPIStoreSharingMessage.h delete mode 100644 Attic/OpenChange/MAPIStoreSharingMessage.m delete mode 100644 Attic/OpenChange/MAPIStoreTable.h delete mode 100644 Attic/OpenChange/MAPIStoreTable.m delete mode 100644 Attic/OpenChange/MAPIStoreTasksContext.h delete mode 100644 Attic/OpenChange/MAPIStoreTasksContext.m delete mode 100644 Attic/OpenChange/MAPIStoreTasksFolder.h delete mode 100644 Attic/OpenChange/MAPIStoreTasksFolder.m delete mode 100644 Attic/OpenChange/MAPIStoreTasksMessage.h delete mode 100644 Attic/OpenChange/MAPIStoreTasksMessage.m delete mode 100644 Attic/OpenChange/MAPIStoreTasksMessageTable.h delete mode 100644 Attic/OpenChange/MAPIStoreTasksMessageTable.m delete mode 100644 Attic/OpenChange/MAPIStoreTypes.h delete mode 100644 Attic/OpenChange/MAPIStoreTypes.m delete mode 100644 Attic/OpenChange/MAPIStoreUserContext.h delete mode 100644 Attic/OpenChange/MAPIStoreUserContext.m delete mode 100644 Attic/OpenChange/NSArray+MAPIStore.h delete mode 100644 Attic/OpenChange/NSArray+MAPIStore.m delete mode 100644 Attic/OpenChange/NSData+MAPIStore.h delete mode 100644 Attic/OpenChange/NSData+MAPIStore.m delete mode 100644 Attic/OpenChange/NSDate+MAPIStore.h delete mode 100644 Attic/OpenChange/NSDate+MAPIStore.m delete mode 100644 Attic/OpenChange/NSObject+MAPIStore.h delete mode 100644 Attic/OpenChange/NSObject+MAPIStore.m delete mode 100644 Attic/OpenChange/NSObject+PropertyList.h delete mode 100644 Attic/OpenChange/NSObject+PropertyList.m delete mode 100644 Attic/OpenChange/NSString+MAPIStore.h delete mode 100644 Attic/OpenChange/NSString+MAPIStore.m delete mode 100644 Attic/OpenChange/NSValue+MAPIStore.h delete mode 100644 Attic/OpenChange/NSValue+MAPIStore.m delete mode 100644 Attic/OpenChange/RTFHandler.h delete mode 100644 Attic/OpenChange/RTFHandler.m delete mode 100644 Attic/OpenChange/SOGoCacheGCSObject+MAPIStore.h delete mode 100644 Attic/OpenChange/SOGoCacheGCSObject+MAPIStore.m delete mode 100644 Attic/OpenChange/SOGoMAPIDBMessage.h delete mode 100644 Attic/OpenChange/SOGoMAPIDBMessage.m delete mode 100644 Attic/OpenChange/classes.txt delete mode 100644 Attic/OpenChange/code-MAPIStorePropertySelectors.h delete mode 100644 Attic/OpenChange/code-MAPIStorePropertySelectors.m delete mode 100644 Attic/OpenChange/dbmsgreader.m delete mode 100755 Attic/OpenChange/gen-charset-table.py delete mode 100755 Attic/OpenChange/gen-property-selectors.py delete mode 100644 Attic/OpenChange/iCalEvent+MAPIStore.h delete mode 100644 Attic/OpenChange/iCalEvent+MAPIStore.m delete mode 100644 Attic/OpenChange/iCalTimeZone+MAPIStore.h delete mode 100644 Attic/OpenChange/iCalTimeZone+MAPIStore.m delete mode 100644 Attic/OpenChange/plreader.m delete mode 100644 Attic/OpenChange/product.plist delete mode 100755 Attic/OpenChange/samba-get-config.py delete mode 100644 Attic/SOGoNativeOutlookConfigurationGuide.asciidoc delete mode 100644 Attic/TestRTFHandler.m diff --git a/Attic/Fixtures/bad_hex_and_cr.rtf b/Attic/Fixtures/bad_hex_and_cr.rtf deleted file mode 100644 index a59fb2f8f..000000000 --- a/Attic/Fixtures/bad_hex_and_cr.rtf +++ /dev/null @@ -1 +0,0 @@ -{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch0\stshfloch37\stshfhich37\stshfbi37\deflang3082\deflangfe3082\themelang3082\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}{\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f39\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f39\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f409\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f410\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f412\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f413\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f416\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f417\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;}{\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp \f37\fs22\lang3082\langfe1033\langfenp1033 }{\*\defpap \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \f37\fs22\lang3082\langfe1033\cgrid\langnp3082\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af37\afs22\alang1025 \ltrch\fcs0 \f37\fs22\lang3082\langfe1033\cgrid\langnp3082\langfenp1033 \snext11 \ssemihidden \sunhideused Normal Table;}{\*\cs15 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf2 \sbasedon10 \ssemihidden \sunhideused \styrsid14902200 Hyperlink;}{\*\cs16 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf12 \sbasedon10 \ssemihidden \sunhideused \styrsid14902200 FollowedHyperlink;}{\*\cs17 \additive \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f37\fs22\cf0 \sbasedon10 \ssemihidden \spriority0 \spersonal \scompose \styrsid14902200 EmailStyle171;}}{\*\revtbl {Unknown;}}{\*\rsidtbl \rsid8201463\rsid9795044\rsid14902200}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1701\margr1701\margt1417\margb1417\gutter0\ltrsect \deftab708\widowctrl\ftnbj\aenddoc\hyphhotz425\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin150\dgvorigin0\dghshow1\dgvshow1\jexpand\viewkind5\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct\asianbrkrule\rsidroot9795044\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\endnhere\sectdefaultcl\sectrsid9795044\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14902200 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \f37\fs22\lang3082\langfe1033\cgrid\langnp3082\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \f410\cf0\insrsid9795044\charrsid14902200 Good hex:\'48 Bad1Hex:\'ZA Bad2Hex:\'A+ Ignored Carriadge Return}} \ No newline at end of file diff --git a/Attic/Fixtures/cyr_event_ru_editor.rtf b/Attic/Fixtures/cyr_event_ru_editor.rtf deleted file mode 100644 index abb222c79..000000000 --- a/Attic/Fixtures/cyr_event_ru_editor.rtf +++ /dev/null @@ -1 +0,0 @@ -{\rtf1\adeflang1025\ansi\ansicpg1251\uc1\adeff0\deff0\stshfdbch0\stshfloch37\stshfhich37\stshfbi37\deflang1049\deflangfe1049\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}{\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f179\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f180\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f182\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f183\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f184\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f185\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f186\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f187\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f179\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f180\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f182\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f183\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f184\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f185\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f186\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f187\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f549\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f550\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f552\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f553\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f556\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f557\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;}{\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp \f37\fs22 }{\*\defpap \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \f37\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af37\afs22\alang1025 \ltrch\fcs0 \f37\fs22\lang1049\langfe1049\cgrid\langnp1049\langfenp1049 \snext11 \ssemihidden \sunhideused Normal Table;}{\*\cs15 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf2 \sbasedon10 \ssemihidden \sunhideused \styrsid15146783 Hyperlink;}{\*\cs16 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf12 \sbasedon10 \ssemihidden \sunhideused \styrsid15146783 FollowedHyperlink;}{\*\cs17 \additive \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f37\fs22\cf0 \sbasedon10 \ssemihidden \spriority0 \spersonal \scompose \styrsid15146783 EmailStyle17;}}{\*\revtbl {Unknown;}}{\*\rsidtbl \rsid10516709\rsid14943922\rsid15146783}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect \deftab708\widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin150\dgvorigin0\dghshow1\dgvshow1\jexpand\viewkind4\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct\asianbrkrule\rsidroot10516709\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\endnhere\sectdefaultcl\sectrsid10516709\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid15146783 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \f37\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \f550\cf0\lang1049\langfe1033\langnp1049\insrsid14943922 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \cf0\lang1049\langfe1033\langnp1049\insrsid14943922\charrsid15146783\par }} \ No newline at end of file diff --git a/Attic/Fixtures/escapes.rtf b/Attic/Fixtures/escapes.rtf deleted file mode 100644 index c40bb300f..000000000 --- a/Attic/Fixtures/escapes.rtf +++ /dev/null @@ -1,6 +0,0 @@ -{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff31507\deff0\stshfdbch31506\stshfloch31506\stshfhich31506\stshfbi31507\deflang3082\deflangfe3082\themelang3082\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}{\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f180\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f181\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f183\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f184\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f185\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f186\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f187\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f188\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f180\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f181\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f183\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f184\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f185\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f186\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f187\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f188\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f550\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f551\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f553\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f554\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f557\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f558\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;}{\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;\red0\green0\blue255;\red128\green0\blue128;}{\*\defchp \f31506\fs22\lang3082\langfe1033\langfenp1033 }{\*\defpap \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang3082\langfe1033\cgrid\langnp3082\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang3082\langfe1033\cgrid\langnp3082\langfenp1033 \snext11 \ssemihidden \sunhideused Normal Table;}{\*\cs15 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf17 \sbasedon10 \ssemihidden \sunhideused \styrsid12347655 Hyperlink;}{\*\cs16 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf18 \sbasedon10 \ssemihidden \sunhideused \styrsid12347655 FollowedHyperlink;}{\*\cs17 \additive \rtlch\fcs1 \af31507\afs22 \ltrch\fcs0 \f31506\fs22\cf0 \sbasedon10 \ssemihidden \spriority0 \spersonal \scompose \styrsid12347655 EmailStyle17;}}{\*\revtbl {Unknown;}}{\*\rsidtbl \rsid5122362\rsid12347655}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1701\margr1701\margt1417\margb1417\gutter0\ltrsect \deftab708\widowctrl\ftnbj\aenddoc\hyphhotz425\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin150\dgvorigin0\dghshow1\dgvshow1\jexpand\viewkind5\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct\asianbrkrule\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\endnhere\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12347655 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang3082\langfe1033\cgrid\langnp3082\langfenp1033 -{\rtlch\fcs1 \af31507 \ltrch\fcs0 \cf0\insrsid12347655 x\341x\351x\372x\355x\363x\361x} -{\rtlch\fcs1 \af31507 \ltrch\fcs0 \cf0\insrsid12347655 S\~S\-S\_S\\S} -{\rtlch\fcs1 \af31507 \ltrch\fcs0 \cf0\insrsid12347655 U\u-2U\u345U} - -{\rtlch\fcs1 \af31507 \ltrch\fcs0 \cf0\insrsid12347655\charrsid12347655 \r\n\par }}} diff --git a/Attic/Fixtures/mini_russian.rtf b/Attic/Fixtures/mini_russian.rtf deleted file mode 100644 index a5cee57f5..000000000 --- a/Attic/Fixtures/mini_russian.rtf +++ /dev/null @@ -1 +0,0 @@ -{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch0\stshfloch37\stshfhich37\stshfbi37\deflang3082\deflangfe3082\themelang3082\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}{\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f39\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f39\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f409\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f410\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f412\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f413\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f416\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f417\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;}{\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp \f37\fs22\lang3082\langfe1033\langfenp1033 }{\*\defpap \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \f37\fs22\lang3082\langfe1033\cgrid\langnp3082\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af37\afs22\alang1025 \ltrch\fcs0 \f37\fs22\lang3082\langfe1033\cgrid\langnp3082\langfenp1033 \snext11 \ssemihidden \sunhideused Normal Table;}{\*\cs15 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf2 \sbasedon10 \ssemihidden \sunhideused \styrsid14902200 Hyperlink;}{\*\cs16 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf12 \sbasedon10 \ssemihidden \sunhideused \styrsid14902200 FollowedHyperlink;}{\*\cs17 \additive \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f37\fs22\cf0 \sbasedon10 \ssemihidden \spriority0 \spersonal \scompose \styrsid14902200 EmailStyle171;}}{\*\revtbl {Unknown;}}{\*\rsidtbl \rsid8201463\rsid9795044\rsid14902200}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1701\margr1701\margt1417\margb1417\gutter0\ltrsect \deftab708\widowctrl\ftnbj\aenddoc\hyphhotz425\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin150\dgvorigin0\dghshow1\dgvshow1\jexpand\viewkind5\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct\asianbrkrule\rsidroot9795044\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\endnhere\sectdefaultcl\sectrsid9795044\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14902200 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \f37\fs22\lang3082\langfe1033\cgrid\langnp3082\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \f410\cf0\insrsid9795044\charrsid14902200 XX\'e7\'fb\'ea \'ef\'ee\'eb\'fc\'f1\'ea\'e8, \'ef\'ee\'eb\'fc\'f9\'e8\'e7\'ed\'e0XX}} \ No newline at end of file diff --git a/Attic/Fixtures/spanish_accents.rtf b/Attic/Fixtures/spanish_accents.rtf deleted file mode 100644 index 3bb98acf9..000000000 --- a/Attic/Fixtures/spanish_accents.rtf +++ /dev/null @@ -1 +0,0 @@ -{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff31507\deff0\stshfdbch31506\stshfloch31506\stshfhich31506\stshfbi31507\deflang3082\deflangfe3082\themelang3082\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}{\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f40\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f41\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f43\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f44\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f45\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f46\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f47\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f48\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f40\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f41\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f43\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f44\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f45\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f46\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f47\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f48\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f410\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f411\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f413\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f414\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f417\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f418\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;}{\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;\red0\green0\blue255;\red128\green0\blue128;}{\*\defchp \f31506\fs22\lang3082\langfe1033\langfenp1033 }{\*\defpap \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang3082\langfe1033\cgrid\langnp3082\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang3082\langfe1033\cgrid\langnp3082\langfenp1033 \snext11 \ssemihidden \sunhideused Normal Table;}{\*\cs15 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf17 \sbasedon10 \ssemihidden \sunhideused \styrsid7169291 Hyperlink;}{\*\cs16 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf18 \sbasedon10 \ssemihidden \sunhideused \styrsid7169291 FollowedHyperlink;}{\*\cs17 \additive \rtlch\fcs1 \af31507\afs22 \ltrch\fcs0 \f31506\fs22\cf0 \sbasedon10 \ssemihidden \spriority0 \spersonal \scompose \styrsid7169291 EmailStyle17;}}{\*\revtbl {Unknown;}}{\*\rsidtbl \rsid7169291\rsid12336957}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1701\margr1701\margt1417\margb1417\gutter0\ltrsect \deftab708\widowctrl\ftnbj\aenddoc\hyphhotz425\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin150\dgvorigin0\dghshow1\dgvshow1\jexpand\viewkind5\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct\asianbrkrule\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\endnhere\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid7169291 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang3082\langfe1033\cgrid\langnp3082\langfenp1033 {\rtlch\fcs1 \af31507 \ltrch\fcs0 \cf0\insrsid7169291 xxxxxx}{\rtlch\fcs1 \af31507 \ltrch\fcs0 \cf0\insrsid7169291\charrsid7169291\par }} \ No newline at end of file diff --git a/Attic/Fixtures/zentyal_crash_2058.rtf b/Attic/Fixtures/zentyal_crash_2058.rtf deleted file mode 100644 index 085ed6d6a..000000000 --- a/Attic/Fixtures/zentyal_crash_2058.rtf +++ /dev/null @@ -1,21 +0,0 @@ -{\rtf1\ansi\deff3\adeflang1025 -{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\froman\fprq2\fcharset0 Times New Roman;}{\f4\fs -wiss\fprq2\fcharset0 Arial;}{\f5\fnil\fprq2\fcharset1 Ubuntu;}{\f6\fnil\fprq2\fcharset0 DejaVu Sans;}{\f7\fnil\fprq2\fcharset0 Lohit Hindi;}{\f8\fnil\fprq0\fcharset1 Lohit Hindi -;}} -{\colortbl;\red0\green0\blue0;\red128\green128\blue128;} -{\stylesheet{\s0\snext0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033 Normal;} -{\s15\sbasedon0\snext16\sb240\sa120\keepn\dbch\af6\dbch\af7\afs28\loch\f4\fs28 Heading;} -{\s16\sbasedon0\snext16\sb0\sa120 Text Body;} -{\s17\sbasedon16\snext17\sb0\sa120\dbch\af8 List;} -{\s18\sbasedon0\snext18\sb120\sa120\noline\i\dbch\af8\afs24\ai\fs24 Caption;} -{\s19\sbasedon0\snext19\noline\dbch\af8 Index;} -}{\info{\creatim\yr2014\mo8\dy4\hr16\min16}{\revtim\yr0\mo0\dy0\hr0\min0}{\printim\yr0\mo0\dy0\hr0\min0}{\comment LibreOffice}{\vern67175170}}\deftab709 -\viewscale100 -{\*\pgdsctbl -{\pgdsc0\pgdscuse451\pgwsxn11906\pghsxn16838\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\pgdscnxt0 Default Style;}} -\formshade\paperh16838\paperw11906\margl1134\margr1134\margt1134\margb1134\sectd\sbknone\sectunlocked1\pgndec\pgwsxn11906\pghsxn16838\marglsxn1134\margrsxn1134\margtsxn1134\marg -bsxn1134\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc -\pgndec\pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033{\rtlch \ltrch\loch\l -och\f5000 -foobar} -\par } diff --git a/Attic/Fixtures/zentyal_crash_2089.rtf b/Attic/Fixtures/zentyal_crash_2089.rtf deleted file mode 100644 index fae14fa91..000000000 --- a/Attic/Fixtures/zentyal_crash_2089.rtf +++ /dev/null @@ -1 +0,0 @@ -{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch0\stshfloch37\stshfhich37\stshfbi37\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 00000000000000000000}Cambria Math;}{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}{\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f39\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f379\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}{\f380\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;}{\f382\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f383\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f386\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}{\f409\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f410\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f412\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f413\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f416\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;}{\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp \f37\fs22 }{\*\defpap \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \f37\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tscellwidthfts0\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af37\afs22\alang1025 \ltrch\fcs0 \f37\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext11 \ssemihidden \sunhideused \sqformat Normal Table;}{\*\cs15 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf2 \sbasedon10 \ssemihidden \sunhideused \styrsid13856214 Hyperlink;}{\*\cs16 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf12 \sbasedon10 \ssemihidden \sunhideused \styrsid13856214 FollowedHyperlink;}{\*\cs17 \additive \rtlch\fcs1 \af0\afs22 \ltrch\fcs0 \f37\fs22\cf0 \sbasedon10 \ssemihidden \spriority0 \spersonal \scompose \styrsid13856214 EmailStyle171;}}{\*\revtbl {Unknown;}}{\*\rsidtbl \rsid13108976\rsid13856214}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect \widowctrl\ftnbj\aenddoc\trackmoves1\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin150\dgvorigin0\dghshow1\dgvshow1\jexpand\viewkind5\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct\asianbrkrule\rsidroot13108976\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\endnhere\sectdefaultcl\sectrsid13108976\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid13856214 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \f37\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \cf0\lang3082\langfe1033\langnp3082\insrsid13108976 Lorem Ipsum}{\rtlch\fcs1 \af0 \ltrch\fcs0 \cf0\lang3082\langfe1033\langnp3082\insrsid13108976\charrsid13108976 \r\n\par }{\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdpriority39 \lsdlocked0 toc 1;\lsdpriority39 \lsdlocked0 toc 2;\lsdpriority39 \lsdlocked0 toc 3;\lsdpriority39 \lsdlocked0 toc 4;\lsdpriority39 \lsdlocked0 toc 5;\lsdpriority39 \lsdlocked0 toc 6;\lsdpriority39 \lsdlocked0 toc 7;\lsdpriority39 \lsdlocked0 toc 8;\lsdpriority39 \lsdlocked0 toc 9;\lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdpriority59 \lsdlocked0 Table Grid;\lsdunhideused0 \lsdlocked0 Placeholder Text;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdunhideused0 \lsdlocked0 Revision;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}{\*\datastore 0105000002000000180000004d73786d6c322e534158584d4c5265616465722e352e3000000000000000000000060000d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffffec69d9888b8b3d4c859eaf6cd158be0f00000000000000000000000060aebc6702aecf01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000105000000000000}} diff --git a/Attic/Fixtures/zentyal_crash_6330.rtf b/Attic/Fixtures/zentyal_crash_6330.rtf deleted file mode 100644 index ca94d4f62..000000000 --- a/Attic/Fixtures/zentyal_crash_6330.rtf +++ /dev/null @@ -1,33 +0,0 @@ -{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi31507\deflang1033\deflangfe2052\themelang1033\themelangfe2052\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;}{\f13\fbidi \fnil\fcharset134\fprq2{\*\panose 02010600030101010101}SimSun{\*\falt };}{\f13\fbidi \fnil\fcharset134\fprq2{\*\panose 02010600030101010101}SimSun{\*\falt };}{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\f38\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604030504040204}Tahoma;}{\f47\fbidi \fnil\fcharset134\fprq2{\*\panose 02010600030101010101}@SimSun;}{\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31501\fbidi \fnil\fcharset134\fprq2{\*\panose 02010600030101010101}SimSun{\*\falt };}{\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}{\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f31505\fbidi \fnil\fcharset134\fprq2{\*\panose 02010600030101010101}SimSun{\*\falt };}{\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f308\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f309\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f311\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f312\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f313\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f314\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f315\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f316\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f318\fbidi \fswiss\fcharset238\fprq2 Arial CE;}{\f319\fbidi \fswiss\fcharset204\fprq2 Arial Cyr;}{\f321\fbidi \fswiss\fcharset161\fprq2 Arial Greek;}{\f322\fbidi \fswiss\fcharset162\fprq2 Arial Tur;}{\f323\fbidi \fswiss\fcharset177\fprq2 Arial (Hebrew);}{\f324\fbidi \fswiss\fcharset178\fprq2 Arial (Arabic);}{\f325\fbidi \fswiss\fcharset186\fprq2 Arial Baltic;}{\f326\fbidi \fswiss\fcharset163\fprq2 Arial (Vietnamese);}{\f440\fbidi \fnil\fcharset0\fprq2 SimSun Western{\*\falt };}{\f440\fbidi \fnil\fcharset0\fprq2 SimSun Western{\*\falt };}{\f678\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f679\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f681\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f682\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f685\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f686\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\f688\fbidi \fswiss\fcharset238\fprq2 Tahoma CE;}{\f689\fbidi \fswiss\fcharset204\fprq2 Tahoma Cyr;}{\f691\fbidi \fswiss\fcharset161\fprq2 Tahoma Greek;}{\f692\fbidi \fswiss\fcharset162\fprq2 Tahoma Tur;}{\f693\fbidi \fswiss\fcharset177\fprq2 Tahoma (Hebrew);}{\f694\fbidi \fswiss\fcharset178\fprq2 Tahoma (Arabic);}{\f695\fbidi \fswiss\fcharset186\fprq2 Tahoma Baltic;}{\f696\fbidi \fswiss\fcharset163\fprq2 Tahoma (Vietnamese);}{\f697\fbidi \fswiss\fcharset222\fprq2 Tahoma (Thai);}{\f780\fbidi \fnil\fcharset0\fprq2 @SimSun Western;}{\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31520\fbidi \fnil\fcharset0\fprq2 SimSun Western{\*\falt };}{\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;}{\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f31560\fbidi \fnil\fcharset0\fprq2 SimSun Western{\*\falt };}{\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;\red0\green0\blue255;\red128\green0\blue128;\red105\green190\blue40;\red80\green80\blue80;\red238\green238\blue238;\red245\green245\blue245;\red102\green102\blue102;}{\*\defchp \fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe2052\loch\f0\hich\af0\dbch\af31505\cgrid\langnp1033\langfenp2052 \snext0 \sqformat \spriority0 \styrsid8454727 Normal;}{\s1\ql \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\af0\afs48\alang1025 \ltrch\fcs0 \b\fs48\lang1033\langfe2052\kerning36\loch\f0\hich\af0\dbch\af31505\cgrid\langnp1033\langfenp2052 \sbasedon0 \snext1 \slink18 \sqformat \spriority9 \styrsid8454727 heading 1;}{\s4\ql \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel3\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\af0\afs24\alang1025 \ltrch\fcs0 \b\fs24\lang1033\langfe2052\loch\f0\hich\af0\dbch\af31505\cgrid\langnp1033\langfenp2052 \sbasedon0 \snext4 \slink19 \sqformat \spriority9 \styrsid8454727 heading 4;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe2052\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp2052 \snext11 \ssemihidden \sunhideused Normal Table;}{\*\cs15 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf17 \sbasedon10 \sunhideused \styrsid8454727 Hyperlink;}{\*\cs16 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf18 \sbasedon10 \ssemihidden \sunhideused \styrsid8454727 FollowedHyperlink;}{\*\cs17 \additive \rtlch\fcs1 \af37 \ltrch\fcs0 \f37 \sbasedon10 \ssemihidden \spriority0 \spersonal \scompose \styrsid8454727 EmailStyle17;}{\*\cs18 \additive \rtlch\fcs1 \ab\af0\afs48 \ltrch\fcs0 \b\f0\fs48\kerning36 \sbasedon10 \slink1 \slocked \spriority9 \styrsid8454727 Heading 1 Char;}{\*\cs19 \additive \rtlch\fcs1 \ab\af0\afs24 \ltrch\fcs0 \b\f0\fs24 \sbasedon10 \slink4 \slocked \spriority9 \styrsid8454727 Heading 4 Char;}{\s20\ql \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe2052\loch\f0\hich\af0\dbch\af31505\cgrid\langnp1033\langfenp2052 \sbasedon0 \snext20 \sunhideused \styrsid8454727 Normal (Web);}{\*\cs21 \additive \rtlch\fcs1 \ab\af0 \ltrch\fcs0 \b \sbasedon10 \sqformat \spriority22 \styrsid8454727 Strong;}{\*\cs22 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \sbasedon10 \spriority0 \styrsid8454727 usercontent;}{\*\cs23 \additive \rtlch\fcs1 \ai\af0 \ltrch\fcs0 \i \sbasedon10 \sqformat \spriority20 \styrsid8454727 Emphasis;}{\s24\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af38\afs16\alang1025 \ltrch\fcs0 \fs16\lang1033\langfe2052\loch\f38\hich\af38\dbch\af31505\cgrid\langnp1033\langfenp2052 \sbasedon0 \snext24 \slink25 \ssemihidden \sunhideused \styrsid8454727 Balloon Text;}{\*\cs25 \additive \rtlch\fcs1 \af38\afs16 \ltrch\fcs0 \f38\fs16 \sbasedon10 \slink24 \slocked \ssemihidden \styrsid8454727 Balloon Text Char;}}{\*\revtbl {Unknown;}}{\*\rsidtbl \rsid5784989\rsid8454727\rsid13448296}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect \widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin136\dgvorigin0\dghshow1\dgvshow1\jexpand\viewkind5\viewscale110\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct\asianbrkrule\rsidroot5784989\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sectrsid8454727\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\ltrrow\trowd \irow0\irowband0\lastrow \ltrrow\ts11\trqc\trgaph150\trleft-150\trftsWidth3\trwWidth12000\trautofit1\trspdfl3\trspdft3\trspdfb3\trspdfr3\trpaddl150\trpaddt150\trpaddb150\trpaddr150\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid14634989\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalc\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth1\clshdrawnil\clhidemark \cellx11850\pard\plain \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\pararsid14634989 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe2052\loch\af0\hich\af0\dbch\af31505\cgrid\langnp1033\langfenp2052 {\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid5784989 \hich\af0\dbch\af31505\loch\f0 \hich\af0\dbch\af31505\loch\f0 INCLUDEPICTURE \hich\af0\dbch\af31505\loch\f0 "http://www.zentyal.com/wp-content/uploads/2013/07/logo-lema-big.png" \\* MERGEFORMAT \\d\hich\af0\dbch\af31505\loch\f0 }}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0 \cf0\lang1024\langfe1024\dbch\af0\noproof\insrsid5784989\charrsid5784989 }}}\sectd \ltrsect\linex0\sectdefaultcl\sectrsid8454727\sftnbj {\rtlch\fcs1 \af0 \ltrch\fcs0 \cf0\dbch\af0\insrsid8454727\charrsid8454727 \cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \fs20\cf0\dbch\af0\insrsid8454727\charrsid8454727 \trowd \irow0\irowband0\lastrow \ltrrow\ts11\trqc\trgaph150\trleft-150\trftsWidth3\trwWidth12000\trautofit1\trspdfl3\trspdft3\trspdfb3\trspdfr3\trpaddl150\trpaddt150\trpaddb150\trpaddr150\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid14634989\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalc\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth1\clshdrawnil\clhidemark \cellx11850\row }\pard \ltrpar\qc \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid8454727 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f1\cf0\insrsid8454727\charrsid8454727 -\par }\pard\plain \ltrpar\s1\ql \li0\ri0\sa150\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap2\pararsid14634989 \rtlch\fcs1 \ab\af0\afs48\alang1025 \ltrch\fcs0 \b\fs48\lang1033\langfe2052\kerning36\loch\af0\hich\af0\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \ab0\af1\afs45 \ltrch\fcs0 \b0\f1\fs45\cf19\insrsid8454727\charrsid8454727 Hi Niels-Uwe, -\par }\pard\plain \ltrpar\s20\ql \li0\ri0\sb100\sa100\sbauto1\saauto1\sl360\slmult1\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap2\pararsid14634989 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe2052\loch\af0\hich\af0\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \ab\af1\afs21 \ltrch\fcs0 \cs21\b\f1\fs21\cf20\insrsid8454727\charrsid8454727 \hich\af1\dbch\af31505\loch\f1 Only 2 weeks}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf20\insrsid8454727\charrsid8454727 \hich\af1\dbch\af31505\loch\f1 are left before Zentyal releases the }{\rtlch\fcs1 \ab\af1\afs21 \ltrch\fcs0 \cs21\b\f1\fs21\cf20\insrsid8454727\charrsid8454727 \hich\af1\dbch\af31505\loch\f1 next mayor Community Edition of the Zentyal Small Business Server}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf20\insrsid8454727\charrsid8454727 \hich\af1\dbch\af31505\loch\f1 . And we also want to share with you that Zental has been}{\rtlch\fcs1 \ab\af1\afs21 \ltrch\fcs0 \cs21\b\f1\fs21\cf20\insrsid8454727\charrsid8454727 \hich\af1\dbch\af31505\loch\f1 featured on TechRepublic.com}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf20\insrsid8454727\charrsid8454727 .}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf20\insrsid8454727\charrsid8454727 \nestcell{\nonesttables -\par }}\pard\plain \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap2 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe2052\loch\af0\hich\af0\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \fs20\cf0\dbch\af0\insrsid8454727\charrsid8454727 {\*\nesttableprops\trowd \irow0\irowband0\lastrow \ltrrow\ts11\trgaph300\trleft0\trftsWidth3\trwWidth9000\trautofit1\trpaddl300\trpaddt300\trpaddb300\trpaddr300\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid14634989\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrs\brdrw120\brdrcf21 \clbrdrr\brdrtbl \cltxlrtb\clftsWidth1\clshdrawnil\clhidemark \cellx9000\nestrow}{\nonesttables -\par }\ltrrow}\trowd \irow0\irowband0\lastrow \ltrrow\ts11\trqc\trleft0\trftsWidth3\trwWidth12000\trautofit1\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid14634989\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \clcbpat8\cltxlrtb\clftsWidth3\clwWidth9000\clcbpatraw8\clhidemark \cellx9000\clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \clcbpat21\cltxlrtb\clftsWidth3\clwWidth3000\clcbpatraw21\clhidemark \cellx12000\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\pararsid14634989 {\rtlch\fcs1 \af0 \ltrch\fcs0 \v\cf0\dbch\af0\insrsid8454727 -\par }\pard\plain \ltrpar\s4\ql \li0\ri0\sa150\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\outlinelevel3\adjustright\rin0\lin0\itap2\pararsid14634989 \rtlch\fcs1 \ab\af0\afs24\alang1025 \ltrch\fcs0 \b\fs24\lang1033\langfe2052\loch\af0\hich\af0\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af0 \ltrch\fcs0 \cf0\lang1024\langfe1024\noproof\insrsid5784989 {\shp{\*\shpinst\shpleft0\shptop0\shpright2385\shpbottom4080\shpfhdr0\shpbxcolumn\shpbxignore\shpbypara\shpbyignore\shpwr2\shpwrk0\shpfblwtxt0\shpz0\shplid1026{\sp{\sn shapeType}{\sv 75}}{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fLockAspectRatio}{\sv 1}}{\sp{\sn fLockPosition}{\sv 0}}{\sp{\sn fLockAgainstSelect}{\sv 0}}{\sp{\sn fLockAgainstGrouping}{\sv 0}}{\sp{\sn pibName}{\sv http://go.zentyal.com/l/24292/2014-10-08/dmptm/24292/55816/zentyal_4_0_release_data_vertical_image.png}}{\sp{\sn pibFlags}{\sv 13}}{\sp{\sn pictureGray}{\sv 0}}{\sp{\sn pictureBiLevel}{\sv 0}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fNoFillHitTest}{\sv 0}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn wzName}{\sv Picture 4}}{\sp{\sn wzDescription}{\sv http://go.zentyal.com/l/24292/2014-10-08/dmptm/24292/55816/zentyal_4_0_release_data_vertical_image.png}}{\sp{\sn dxWrapDistLeft}{\sv 0}}{\sp{\sn dxWrapDistRight}{\sv 0}}{\sp{\sn posh}{\sv 3}}{\sp{\sn posrelv}{\sv 3}}{\sp{\sn dhgt}{\sv 251659264}}{\sp{\sn fLayoutInCell}{\sv 1}}{\sp{\sn fAllowOverlap}{\sv 0}}{\sp{\sn fBehindDocument}{\sv 0}}{\sp{\sn fHidden}{\sv 0}}{\sp{\sn fLayoutInCell}{\sv 1}}}{\shprslt\par\pard\intbl\ql \li0\ri0\widctlpar\posxr\wraparound\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\absnoovrlp1 {\pict\picscalex71\picscaley71\piccropl0\piccropr0\piccropt0\piccropb0\picw5900\pich10134\picwgoal3345\pichgoal5745\wmetafile8\bliptag-641113162{\*\blipuid d9c963b604fc4a8d8a51bbed15793a74}\bin257524    A (`)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JΥƥ!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J֭ƥ)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JΥƥ!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J֭ƥ)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JΥ!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J֭)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JΥ!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)Js)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)91J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1Jcs!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1Jk{)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)91J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JcsΥ{{{{{{{{{!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)Jk{ﭭ)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1Jcsƭ!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1Jk{ε)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JcsƔ{{{!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)Jk{!{s{Js{scƥ)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1Jcs)s{sssBss{sscƜ!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1Jk{{s{s{s{Js{s{s{)ƔJZ)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1Jcsss{sss{sB{sss{ss)ƽZk)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)Jk{{s{s{s{s{Js{s{s{s{BΜcs)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1Jcs1s{sss{!c{sss{ss{{{Zk)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1JZks{s{s{cs{s{s)Ɯcs)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)Bֵ1{sss{Zsss{sƔRRRsssZk)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1JνssskkkkkkRRR111999111999111999111999111{s{s{!{s{s{cƵ)))111999111999111999)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)Bֵkkkccc999111111111999111111111999111111111999111111111999111111111999sss{s{{sss9!!!111111999111111111)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1JΥkkkkkk999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111{s{s{Js{s{B999!!!111999111999111999)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B֥ssskkk111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111BBB!!!999111111111999111)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J֭kkkZZZ111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111!)cs{s{{BBB)))111999111999111999)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)Bֽssskkk111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999Δ֜!{sss!!!!!!111111999111111111){B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1JέkkkJJJ999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111BB{s{s{R111111999111999111999)s9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B֜cccBBB111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111֜9sss{s!!!111999111111111999111)s9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1JΜkkk111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111ZZZ΄޽cs{s{ssss!!!999111999111999111999)k9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J){Bccc999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111{{9sss{ss{111111111111111999111111111)s9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1kB111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999{{{Ό19s{{s{s{s{!)))111999111999111999111999)s9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1c9999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999ZZ޽B{sss{ss{9991111111119991111111119991111Z9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1kB111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111kkkBB޽Js{s{s{{111999111999111999111999111999)Z9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1c9111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111kkBss{ss!)))1111119991111111119991111111111Z9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1kB111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111޽BJ޽Js{s{9999991119991119991119991119991119991Z9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1c9999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111kkBBJRBR9991111119991111111119991111111119991111Z9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1kB111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111sss1119991119991119991119991119991119991119991R9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1c9111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111BBBRRR1111111119991111111119991111111119991111111111J9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1kB111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999BBBƌJJJ9991119991119991119991119991119991119991119991119991J9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1c9999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111RRRcccccccccZZZ1111111119991111111119991111111119991111111119991111111119991111J9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1kB1119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991J1)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1c9111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111199!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1kB111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1c9999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111)k9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J9R91119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991111c9)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J191111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999)R1)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J9991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991111J9)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1B111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J1c9999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999){9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1Z9111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111)s9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J9999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999)Z9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111111R9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J1119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991J9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1sB999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1kB111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111){B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J9111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999)k9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J9B91119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991111c9)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111J1)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J1{B9991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119J9)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1sB111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1Z9999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999)s9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1R9111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111)k9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J1119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991Z9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111RRRccckkkcccssskkkcccZZZ1111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111J9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1{B111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999RRRkkkν{{{kkk999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999191)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1c9111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999ZZZΜsssRRR111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J9R9111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111kkkƔZZZ999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111)sB)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1B1999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111JJJƄRRR111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111)c9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B999111999111999111999111999111999111999111999111999111999111999111999111999111999111999RRR猌9991119991119991119991119991119991119991119991119991119991119991119991119991119991119991111c9)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1B111111111999111111111999111111111999111111111999111111111999111111111999111111BBBJJJBBB1111111119991111111119991111111119991111111119991111111119991111111119991111111119991B1)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1kB999111999111999111999111999111999111999111999111999111999111999111999111999RRRRRRZZZJJJBBB1119991119991119991119991119991119991119991119991119991119991119991119991111B9)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1c9111999111111111999111111111999111111111999111111111999111111111999999JJJRRR{{{RRRRRRRRRRRR999111999111111111999111111111999111111111999111111111999111111111999111111111)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J1J9999111999111999111999111999111999111999111999111999111999111999999RRRRRRZZZRRRZZZRRRZZZ999999111999111999111999111999111999111999111999111999111999111999111999111999)s9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B999111111111999111111111999111111111999111111111999111111111999999RRRRRRRRRRRRRRRRRRRRRRRRJJJ1111111119991111111119991111111119991111111119991111111119991111111119991111c9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J111999111999111999111999111999111999111999111999111999111999111RRRRRRZZZRRRsssRRRZZZRRRZZZJJJ999111999111999111999111999111999111999111999111999111999111999111999111999)R9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)sB111111999111111111999111111111999111111111999111111111999111111RRRRRRRRRRRRRRRRRRRRRRRRRRR1119991111111119991111111119991111111119991111111119991111111119991111111111J9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1kB111999111999111999111999111999111999111999111999111999111999999ZZZRRRZZZRRRsssZZZRRRZZZRRR999111999111999111999111999111999111999111999111999111999111999111999111999191)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1R9999111111111999111111111999111111111999111111111999111111111BBBRRRRRRRRRRRRRRRRRRRRRRRR999111111999111111111999111111111999111111111999111111111999111111111999111111){9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J9B9111999111999111999111999111999111999111999111999111999111999BBBZZZRRRZZZRRRZZZRRRZZZRRRBBB1119991119991119991119991119991119991119991119991119991119991119991119991111sB)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J111111111999111111111999111111111999111111111999111111111999111JJJRRRRRRRRRRRRRRRRRRRRRRRRBBB999111111111999111111111999111111111999111111111999111111111999111111111999)Z9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1B999111999111999111999111999111999111999111999111999111999111999JJJZZZRRRZZZkkkZZZRRRZZZRRRRRR1119991119991119991119991119991119991119991119991119991119991119991119991111Z9)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1kB111999111111111999111111111999111111111999111111111999111111111RRRRRRRRRRRRsssRRRRRRRRRRRR1111119991111111119991111111119991111111119991111111119991111111119991111111B1)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J1c9999111999111999111999111999111999111999111999111999111999111BBBRRRZZZRRRZZZRRRZZZRRRZZZ999999111999111999111999111999111999111999111999111999111999111999111999111999)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1R9111111111999111111111999111111111999111111111999111111111999999RRRRRRRRRRRRRRRRRRRRRRRRBBB111111111999111111111999111111111999111111111999111111111999111111111999111){9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J191999111999111999111999111999111999111999111999111999111999111JJJRRRZZZRRRZZZRRRZZZRRRZZZBBB999111999111999111999111999111999111999111999111999111999111999111999111999)k9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B111111999111111111999111111111999111111111999111111111999111111JJJRRRRRRRRRRRRRRRRRRRRRRRRJJJ1119991111111119991111111119991111111119991111111119991111111119991111111111Z9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1B111999111999111999111999111999111999111999111999111999111999111RRRRRRZZZRRRkkkkkkZZZRRRZZZRRR9991119991119991119991119991119991119991119991119991119991119991119991119991R9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1c9999111111111999111111111999111111111999111111111999111111111999RRRRRRRRRRRR{{{{{{RRRRRRRRRRRR9991111119991111111119991111111119991111111119991111111119991111111119991111J9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J9ZB111999111999111999111999111999111999111999111999111999111999999ZZZRRRZZZRRRZZZRRRZZZRRRBBB111999111999111999111999111999111999111999111999111999111999111999111999111)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1B1111111999111111111999111111111999111111111999111111111999111BBBRRRRRRRRRRRRRRRRRRRRRRRRBBB999111111111999111111111999111111111999111111111999111111111999111111111999Zk)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J999111999111999111999111999111999111999111999111999111999111999BBBZZZRRRZZZRRRZZZRRRZZZRRRRRR111999111999111999111999111999111999111999111999111999111999111999111999111k{)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1B111999111111111999111111111999111111111999111111111999111111111JJJRRRRRRRRRRRRZZZRRRRRRRRRRRR111111999111111111999111111111999111111111999111111111999111111111999111111Jc)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J1sB999111999111999111999111999111999111999111999111999111999111999JJJZZZRRRZZZkkkRRRZZZRRRZZZ999999111999111999111999111999111999111999111999111999111999111999111999111{{{1J)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)Bk{k111111111999111111111999111111111999111111111999111111111999111RRRRRRRRRRRR{{{RRRRRRRRRRRRBBB111111111999111111111999111111111999111111111999111111111999111111111999ZZZ!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J֭kkk999111999111999111999111999111999111999111999111999111999111999RRRZZZRRRZZZΥRRRZZZRRRZZZBBB999111999111999111999111999111999111999111999111999111999111999111999111999)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)BZkBBB111999111111111999111111111999111111111999111111111999111111999RRRRRRRRRRRR΄BBB999111111111999111111111999sssRRRRRRRRRRRRJJJ111999111111111999111111111999111111111999111111111999111111111999111111111BZ!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J111999111999111999111999111999111999111999111999111999111999111JJJRRRZZZRRRZZZkkk999111999111999111999111999111999111999111kkkRRRZZZRRRZZZRRR999111999111999111999111999111999111999111999111999111999111999111999111999)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J{999111111111999111111111999111111111999111111111999111111111999JJJRRRRRRRRRRRR111111111999111111BBBkkksssssscccRRR111111111999111111RRRRRRRRRRRR111111111999111111111999111111111999111111111999111111111999111111111999111{)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J9R111999111999111999111999111999111999111999111999111999111999111RRRRRRZZZRRRkkkkkkBBB999BBBkkk111999111999BBBBBB111999111999ZZZRRRZZZRRRBBB111999111999111999111999111999111999111999111999111999111999111999111999sss1J)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)BΥ111111999111111111999111111111999111111111999111111111999111111RRRRRRRRRRRR{{{BBB999111111111999111111BBB111111111999111999111111RRRRRRRRRRRRBBB999111111111999111111111999111111111999111111111999111111111999111111111ZZZƥ!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1JBZZZZ111999111999111999111999111999111999111999111999111999111999999ZZZRRRZZZRRR111999111999111999111999111999111111999111BBBBBB999111999ZZZRRRZZZRRRJJJ1119991119991119991119991119991119991119991119991119991119991119991119991119J)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JΥ111999111111111999111111111999111111111999111111111999111111111BBBRRRRRRRRRRRR111999111111cccέccc999111111111BBB111111BBBBBB999111111RRRRRRRRRRRRJJJ111111999111111111999111111111999111111111999111111111999111111111999111111Ɯ)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J999111999111999111999111999111999111999111999111999111999111999BBBZZZRRRZZZRRRJJJ999111999BBB111999111999111999111999111kkksssRRRZZZRRRZZZ1119991119991119991119991119991119991119991119991119991119991119991119991111J)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)BƔ111111111999111111111999111111111999111111111999111111111999111JJJRRRRRRRRRRRR999111111999111111111999111999111RRRRRRRRRRRRBBB111111111999111111111999111111111999111111111999111111111999111111111999!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J999111999111999111999111999111999111999111999111999111999111999JJJZZZRRRZZZZZZ111999JJJZZZ999111999111BBB111999RRRZZZRRRZZZBBB999111999111999111999111999111999111999111999111999111999111999111999111kkk)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JRkkkk111999111111111999111111111999111111111999111111111999111111111RRRRRRRRRRRRccc111111111999111111111BBBRRRRRRRRRRRRJJJ111999111111111999111111111999111111111999111111111999111111111999111111JJJRc)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1JֵBBB999111999111999111999111999111999111999111999111999111999111999RRRZZZRRRZZZ޵999111999111999111RRRZZZRRRZZZJJJ999111999111999111999111999111999111999111999111999111999111999111999111999ε)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J999111111111999111111111999111111111999111111111999111111111999999RRRRRRRRRRRR111111111999111111kkkRRRRRRRRRRRR111111111999111111111999111111111999111111111999111111111999111111111999111)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1JRk111999111999111999111999111999111999111999111999111999111999111JJJRRRZZZRRRZZZ999111RRRkkk999111ZZZRRRZZZRRR999111999111999111999111999111999111999111999111999111999111999111999111999Rc)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)Bֵ111111999111111111999111111111999111111111999111111111999111111BBBRRRRRRRRRRRR111999ccckkk111999RRRRRRRRRRRRBBB999111111111999111111111999111111111999111111111999111111111999111111111ƥ!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J111999111999111999111999111999111999111999111999111999111999111RRRRRRZZZRRRccc999111kkkZZZRRRZZZRRRJJJ111999111999111999111999111999111999111999111999111999111999111999111999kkk)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JBZccc999111111111999111111111999111111111999111111111999111111111999RRRRRRRRRRRR{{{111111cccRRRRRRRRRRRRJJJ111111999111111111999111111111999111111111999111111111999111111111999111BBB!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1JƔ999111999111999111999111999111999111999111999111999111999111999999ZZZRRRZZZRRR999111kkkZZZRRRZZZRRRZZZ111999111999111999111999111999111999111999111999111999111999111999111999111Rk)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J޽111111111999111111111999111111111999111111111999111111111999111999RRRRRRRRRRRR111999ccc{{{RRRRRRRRRRRR999111111111999111111111999111111111999111111111999111111111999111111111999s)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J999111999111999111999111999111999111999111999111999111999111999BBBZZZRRRZZZRRR999111kkkέ{{{kkkcccRRRZZZRRRZZZBBB999111999111999111999111999111999111999111999111999111999111999111999111ƥ)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J111999111111111999111111111999111111111999111111111999111111111JJJRRRRRRRRRRRR111111ccc便ZZZ111999111111111999999RRRRRRRRRRRRBBB111999111111111999111111111999111111111999111111111999111111111999111111)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1Jcskkk999111999111999111999111999111999111999111999111999111999111999JJJZZZRRRZZZZZZZZZ999111RRRkkk111999111999111999111999111999RRRZZZRRRZZZJJJ999111999111999111999111999111999111999111999111999111999111999111999111kkk)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)BΜRRR111111111999111111111999111111111999111111111999111111111999111RRRRRRRRRRRRBBB111111999111ZZZJJJ999111111111999111111111999111111111RRRRRRRRRRRRRRR111111111999111111111999111111111999111111111999111111111999111111111999BBB)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1JΥ111999111999111999111999111999111999111999111999111999111999111999RRRZZZRRRZZZkkkBBB999111999111999111ccckkk111999111999111999111999111999111999111999JJJZZZRRRZZZRRR999111999111999111999111999111999111999111999111999111999111999111999111999Rc)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B111111999111111111999111111111999111111111999111111111999111111999RRRRRRRRRRRRBBB111111111999111ZZZBBB111111999111111111999111BBBBBB111999111111111999111111111999111111111999111BBBRRRRRRRRRRRR999999111111111999111111111999111111111999111111111999111111111999111111111cs!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J111999111999111999111999111999111999111999111999111999111999111JJJRRRZZZRRRZZZ999999111999111999111999111999sss111999111999111999111999111999111BBB999111999111999111999111999111999111999111999111999999ZZZRRRZZZRRRJJJ111999111999111999111999111999111999111999111999111999111999111999111999)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B999111111111999111111111999111111111999111111111999111111111999BBBRRRRRRRRRRRR111111999111111111999111111111999111RRR111111111999111111111999111111111999111BBB111111999111111111999111111111999111111111999111111111999RRRRRRRRRRRRJJJ111111999111111111999111111111999111111111999111111111999111111111999111ƥ!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1Jkkk111999111999111999111999111999111999111999111999111999111999111RRRRRRZZZRRRRRR111999111999111999111999111999111999111999RRR111999111999111999111999111999111999111999111BBB999111999111999111999111999111999111999111999111999111999111RRRRRRZZZRRRRRR111999111999111999111999111999111999111999111999111999111999111999111999kkk)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JJZ111111111999111111111999111111111999111111111999111111111999111111RRRRRRRRRRRRJJJ999111111111999111111111999111111111999111111111{{{111111111999111111111999111111111999111111111999111BBB111111999111111111999111111111999111111111999111111111999111111JJJRRRRRRRRRRRR999111111111999111111111999111111111999111111111999111111111999111111111999!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)Jk{999111999111999111999111999111999111999111999111999111999111999999ZZZRRRZZZRRRJJJ111999111999111999111999111999111999111999111999111RRR111999111999111999111999111999111999111999111999111999111BBB999111999111999111999111999111999111999111999111999111999111999111JJJRRRZZZRRRZZZ999999111999111999111999111999111999111999111999111999111999111999111999111)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1Jcs111999111111111999111111111999111111111999111111111999111111111BBBRRRRRRRRRRRRBBB111111999111111111999111111111999111111111999111111111999ZZZ111111111999111111111999111111111999111111111999111111111999111BBBBBB111999111111111999111111111999111111111999111111111999111111111999999RRRRRRRRRRRRBBB111999111111111999111111111999111111111999111111111999111111111999111111!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1Jk{999111999111999111999111999111999111999111999111999111999111999BBBZZZRRRZZZRRRBBB111999111999111999111999111999111999111999111999111999111999ccc111999111999111999111999111999111999111999111999111999111999111999111BBBZZZ111999111999111999111999111999111999111999111999111999111999111999111999RRRZZZRRRZZZJJJ9991119991119991119991119991119991119991119991119991119991119991119991111kB)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JƜ{{{111111111999111111111999111111111999111111111999111111111999111JJJRRRRRRRRRRRR111999111111111999111111111999111111111999111111111999111111111999ν111999111111111999111111111999111111111999111111111999111111111999111111111RRRRRRRRRRRRRRR1111111119991111111119991111111119991111111119991111111119991111111119991111J9)s9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B)B)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J֭RRR999111999111999111999111999111999111999111999111999111999111999JJJZZZRRRZZZRRR999111999111999111999111999111999111999111999111999111999111999111999BBB999111999111999111999111999111999111999111999111999111999111999111999111999JJJZZZRRRZZZRRR999111999111999111999111999111999111999111999111999111999111999111999111ZZZ999111999)c9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JΥ111111999111111111999111111111999111111111999111111111999111111111RRRRRRRRRRRRJJJ111111111999111111111999111111111999111111111999111111111999111111111BBB999111111111999111111111999111111111999111111111999111111111999111111111999111JJJRRRRRRRRRRRR999999111111111999111111111999111111111999111111111999111111111999111111111JJJ111111111)R1)B!9)B!9)B!9)B!9)B)B1J)B1J)B)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J֭111999111999111999111999111999111999111999111999111999111999111999RRRZZZRRRZZZBBB999111999111999111999111999111999111999111999111999111999111999111999111ZZZRRR111999111999111999111999111999111999111999111999111999111999111999111999111999BBBZZZRRRZZZRRRJJJ111999111999111999111999111999111999111999111999111999111999111999111999kkk1119991119991J9)B)9)B)9)B)B1J1J1J)J1J1J1J)B)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JΥ999111111111999111111111999111111111999111111111999111111111999999RRRRRRRRRRRRBBB111999111111111999111111111999111111111999111111111999111111111999111111111111111111999111111111999111111111999111111111999111111111999111111111999111111111999RRRRRRRRRRRRBBB111111999111111111999111111111999111111111999111111111999111111111999111ccc1111111111111111B1){B)9)B)B1J)B1J)B1J)B1J)B)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J֭111999111999111999111999111999111999111999111999111999111999111BBBRRRZZZRRRZZZ999999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111ZZZRRRZZZRRRRRR111999111999111999111999111999111999111999111999111999111999111999111999kkk1119991119991119991911J)J1J1J1J)J1J1J1J)J1J)B)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JΥccc111111999111111111999111111111999111111111999111111111999111111BBBRRRRRRRRRRRR999111111111999111111111999111111111999111111111999111111111999111111111999111111cccBBB111999111111111999111111111999111111111999111111111999111111111999111111111999111111JJJRRRRRRRRRRRR999111111111999111111111999111111111999111111111999111111111999111111111{{{ccc1111111111111111111111911B)B1J)B1J)B1J)B1J)B)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J֭999111999111999111999111999111999111999111999111999111999111999111RRRRRRZZZRRRRRR111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111JJJRRRZZZRRRZZZ999999111999111999111999111999111999111999111999111999111999111999111999ZZZkkk1119991119991119991119991911J)J1J1J1J)J1J1J1J)B)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J{111999111111111999111111111999111111111999111111111999111111111999RRRRRRRRRRRRJJJ111111999111111111999111111111999111111111999111111111999111111111999111111111999111kkk999111111111999111111111999111111111999111111111999111111111999111111111999111111111999BBBRRRRRRRRRRRRBBB111999111111111999111111111999111111111999111111111999111111111999111111ccc1111111111111111111111111111J91J)B1J)B1J)B1J)B)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)Jk{999111999111999111999111999111999111999111999111999111999111999999ZZZRRRZZZRRRJJJ111999111999111999111999111999111999111999111999111999111999111999111999111999111999111111999111999111999111999111999111999111999111999111999111999111999111999111999111999111BBBRRRZZZRRRZZZBBB9991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991B1J)J1J1J1J)J)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1Jcs111111111999111111111999111111111999111111111999111111111999111999RRRRRRRRRRRRBBB999111111111999111111111999111111111999111111111999111111111999111111111999111111111999ccc111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111RRRRRRRRRRRRJJJ1111111119991111111119991111111119991111111119991111111119991111111119991111111111111111111111111111111111R9)B1J)B1J)B1J!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1{Bk{ksss999111999111999111999111999111999111999111999111999111999111999BBBZZZRRRZZZRRRBBB111999111999111999111999111999111999111999111999111999111999111999111999111999111999111RRRRRR111999111999111999111999111999111999111999JJJssssssRRR999111999111999111999111999JJJZZZRRRZZZRRR9991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991111J1J1J)J1J)B)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1R9111111ZZZ111999111111111999111111111999111111111999111111111999111111111JJJRRRRRRRRRRRR111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111111999111111111999111111111999111111111JJJ{{{RRR111999111111111999111JJJRRRRRRRRRRRR999999111111111999111111111999111111111999111111111999111111111999111111ccc111111111111111111111111111111111111)B1J)B1J)9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J191999111999111999111999111999111999111999111999111999111999111999111999111999JJJZZZRRRZZZRRR999111999111999111999111999JJJsss{{{ZZZ999111999111999111999111999111999111999111999999111999111999111999111999111999111cccccc111999111999111999BBBZZZRRRZZZRRRBBB111999111999111999111999111999111999111999111999111999111999111999111RRR9991119991119991119991119991119991111B)J1J)B)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1kB111111111111111999111111111999111111111999111111111999111111111999111111111999111RRRRRRRRRRRRJJJ111999111111111999111JJJ{{{kkk111111111999111111111999111111111999111sss111111111999111111111999111111111JJJsssRRR111999111111111BBBRRRRRRRRRRRRBBB111111999111111111999111111111999111111111999111111111999111111111999111111111111111111111111111111111111111)B1J)B)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1ZB111999111999111999ƽ111999111999111999111999111999111999111999111999111999111999111999RRRZZZRRRZZZBBB999111999111999111ZZZ999999111999111999111999111999111999ZZZ999111999111999111999111999111999{{{)))sssBBB111999111999999ZZZRRRZZZRRRRRR1119991119991119991119991119991119991119991119991119991119991119991119999991119991119991119991119991119991911J)B)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1cB111111111111111111111111111999111111111999111111111999111111111999111111111999111111999RRRRRRRRRRRRBBB111111111999111RRR{{{111111111999111111111999111111111999ZZZ999111111111999111111111999ZZZ{{{ZZZccc111111999111111JJJRRRRRRRRRRRR9991111111119991111111119991111111119991111111119991111111119991111111111111111111111111111111111111111111R9)B)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1{B111999111999111999111999ssskkk111999111999111999111999111999111999111999111999111999111999111JJJRRRZZZRRRZZZ999999111999111999RRR111{{{ZZZ111999111999111999111999111999111kkk111999111999111999111999111{{{111999111999111JJJRRRZZZRRRZZZ999999111999111999111999111999111999111999111999111999111999111999111999kkk999111999111999111999111999111999)c9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J191111111111111111111111111RRRBBB999111111111999111111111999111111111999111111111999111111111999BBBRRRRRRRRRRRR999111999111111ccc!!!ZZZ999111111111999111111111999111111111111999111111111999111111sssccc999111111111999BBBRRRRRRRRRRRR999111999111111111999111111111999111111111999111111111999111111111999111kkkRRR111111111111111111111111111111191)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J9999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111RRRRRRZZZRRRZZZ111999111999111111RRR999111999111999111999111999111111999111999111999111999111JJJJJJ111999111999111BBBRRRZZZRRRZZZBBB999111999111999111999111999111999111999111999111999111999111999111999BBB1119991119991119991119991119991111k9)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J){B111111111111111111111111111111111111111111999111111111999111111111999111111111999111111111999111111RRRRRRRRRRRRJJJ999111111111999999kkk111999111111111999111111111999999111111111999111111111999ccc111111RRR111111999111111999RRRRRRRRRRRRJJJ1111111119991111111119991111111119991111111119991111111119991111111119991111111111111111111111111111111B1!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1ZB111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111ZZZRRRZZZRRRJJJ111999111999JJJcccsss999111999111999111999111999111RRR999111999111999111999111{{{111999111999111999RRRZZZRRRZZZRRR999111999111999111999111999111999111999111999111999111999111999111999111111999111999111999111999111999)s9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J191111111111111111111111111111111111111999111111111999111111111999111111111999111111111999111111111BBBRRRRRRRRRRRRBBB111111999111RRRZZZ{{{111111111999111111111999111111111999111111111999111111kkk111sss999111111111999111JJJRRRRRRRRRRRR111999111111111999111111111999111111111999111111111999111111111999111111sss1111111111111111111111111111Z9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J1B999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999BBBZZZRRRZZZRRRBBB111999111999999111111kkk999111999111999111999111999111999111999111999111999111BBB)))RRR111999111999111999BBBZZZRRRZZZRRRBBB111999111999111999111999111999111999111999111999111999111999111999111BBB1119991119991119991119991B11J)B)B)9)B)9)B)9)B)9)B)9)B)B1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1B111111111111111111111111111111111999111111111999111111111999111111111999111111111999111111111999111BBBRRRRRRRRRRRR999999111111111999sssZZZ111999111111111999111111111BBBJJJ111111999111111111999111kkkތ999!!!111ZZZ{{{111111111999111111111BBBRRRRRRRRRRRRBBB111111999111111111999111111111999111111111999111111111999111111111999ccc1111111111111111111111111911B)B1J)B)B!9)B!9)B!9)B!9)B)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1B999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999JJJZZZRRRZZZRRR999111999111999111sssJJJ999999111999111999111999111999kkk111999111999111999111999999999999111999111999111999999ZZZRRRZZZRRRJJJ111999111999111999111999111999111999111999111999111999111999111999111BBB9991119991119991119991111{B1J1J)J1J)B)B)9)B)9)B)B1J1J1J)J1J1J1J)J1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1B111111111111111111111111111111111111111999111111111999111111111999111111111999111111111999111111111RRRRRRRRRRRRJJJ111111111999111111BBBZZZccc999111111111999111111111999111RRR111111111999111111111999999{{{999111111999111111111999111111RRRRRRRRRRRRJJJ999111111111999111111111999111111111999111111111999111111111999111111111RRR1111111111111111111111cB)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999RRRZZZRRRZZZJJJ999111999111999111999ccc{{{{{{BBB111999111999111999111999111999999111999111999111999111999111RRRccc111999111999111999111999111999111RRRRRRZZZRRRZZZ1119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991111ZB1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J191111111111111111111111111111111999111111111999111111111999111111111999111111111999111111111999999RRRRRRRRRRRRBBB111999111111111999111111sssBBB111111111999111111111999111111111sss999111111111999111111111999111111999RRRJJJRRR999999111111111999111111111999111111111999BBBRRRRRRRRRRRR9991119991111111119991111111119991111111119991111111119991111111119991111111111111111111111Z9)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1kB111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111BBBRRRZZZRRRZZZ999999111999111999111999111999ccc{{{BBB111999111999111999111999111999111{{{BBB999111999111999111999111999111999111999111999111999111999111999111999111999111999111BBBRRRZZZRRRZZZBBB9991119991119991119991119991119991119991119991119991119991119991119991119991119991111ZB1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B111111111111111111111111111111111111999111111111999111111111999111111111999111111111999111111BBBRRRRRRRRRRRR999111111111999111111111999111111999ccc{{{sssJJJ999111111111999111111111999111111111999111999111111111999111111111999111111111999111111111999111111111999111111111999111111999RRRRRRRRRRRRJJJ1111111119991111111119991111111119991111111119991111111119991111111119991111111111cB)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1c9999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111RRRRRRZZZRRRZZZ111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999BBB111999111999111999111999111999111999111999111999111999111999111999111999111999111999RRRZZZRRRZZZJJJ9991119991119991119991119991119991119991119991119991119991119991119991119991911{B1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1B1111111111111111111111111999111111111999111111111999111111111999111111111999111111111999JJJRRRRRRRRRJJJ111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111999111111111999111111111999111111111999111111111999111111111999111111111999111RRRRRRRRRRRRRRR1119991111111119991111111119991111111119991111111119991111111119991111111J91J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J191999111999111999111999111999111999111999111999111999111999111999111999111999111999111ZZZRRRZZZRRRJJJ111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111BBB111999111999111999111999111999111999111999111999111999111999111999111999111999JJJZZZRRRZZZRRRBBB1119991119991119991119991119991119991119991119991119991119991119991111J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1{B111111111111111999111111111999111111111999111111111999111111111999111111111999111999RRRRRRRRRRRRBBB999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111BBB999111111111999111111111999111111111999111111111999111111111999111111111BBBRRRRRRRRRRRR9991111119991111111119991111111119991111111119991111111119991111111119991c91J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1{B111999111999111999111999111999111999111999111999111999111999111999111999111999BBBZZZRRRZZZRRRBBB111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999JJJZZZ999111999111999111999111999111999111999111999111999111999111999111999999ZZZRRRZZZRRRJJJ1119991119991119991119991119991119991119991119991119991119991119991111ZB)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1B191111111111111999111111111999111111111999111111111999111111111999111111111JJJRRRRRRRRRRRR111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111RRRRRRRRRRRRJJJ9991111111119991111111119991111111119991111111119991111111119991111111J91J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J9999111999111999111999111999111999111999111999111999111999111999111999JJJZZZRRRZZZRRR999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111111999111999111999111999111999111999111999111999111999111999111RRRRRRZZZRRRRRR1119991119991119991119991119991119991119991119991119991119991119991119991J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1R9999111111111999111111111999111111111999111111111999111111111999111RRRRRRRRRRRRJJJ111999111111111999111111111999111111111999111111111999111111111999111111111999111111111{{{BBB111999111111111999111111111999111111111999111111111999RRRRRRRRRRRRRRR9991119991111111119991111111119991111111119991111111119991111111119991111B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J9R9111999111999111999111999111999111999111999111999111999111999111999RRRZZZRRRZZZJJJ999111999111999111999111999111999111999111999111999111999111999111999111999111999111cccƌZZZ111999111999111999111999111999111BBBsssRRRZZZRRRZZZ9999991119991119991119991119991119991119991119991119991119991119991119991{B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J191111111999111111111999111111111999111111111999111111111999111111999RRRRRRRRRRRRJJJ111111111999111111111999111111111999111111111999111111111999111111111999111111111ZZZƜRRRRRRRRRRRRJJJ1111111119991111111119991111111119991111111119991111111119991111111111kB)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J999111999111999111999111999111999111999111999111999111999111999111BBBRRRZZZRRRZZZBBB999111999111999111999111999111999111999111999111999111999111999111999111999111cccRRRZZZRRRZZZJJJ9991119991119991119991119991119991119991119991119991119991119991119991R91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B1J)B)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1B111999111111111999111111111999111111111999111111111999111111111999BBBRRRRRRRRRRRR999111999111111111999111111111999111111111999111111111999111111111999111111111RRRRRRRRRRRRRRR1119991111111119991111111119991111111119991111111119991111111119991111J9)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B)B)B)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J1kB999111999111999111999111999111999111999111999111999111999111999111RRRRRRZZZRRRZZZ111999111999111999111999111999111999111999111999111999111999111999111999BBB{{{ZZZRRRZZZRRR9991119991119991119991119991119991119991119991119991119991119991119991111J1J1J)J1J1J1J)B1J)B)B)B)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1Z9111111111999111111111999111111111999111111111999111111111999111111JJJRRRRRRRRRJJJ999111111111999111111111999111111111999111111111999111111111999111111cccRRRRRRRRRRRR999111111999111111111999111111111999111111111999111111111999111111111999){B)B)B)B)9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J9999111999111999111999111999111999111999111999111999111999111999111ZZZRRRZZZRRRJJJ111999111999111999111999111999111999111999111999111999111999111RRRZZZRRRZZZRRRJJJ1119991119991119991119991119991119991119991119991119991119991119991111k9)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B111111999111111111999111111111999111111111999111111111999111111111BBBRRRRRRRRRRRRBBB111111999111111111999111111111999111111111999111111111999cccRRRRRRRRRRRRJJJ999111111111999111111111999111111111999111111111999111111111999111111)Z9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J111999111999111999111999111999111999111999111999111999111999111999999ZZZRRRZZZRRRkkk999111999111999111999111999111999111999111999ZZZRRRRRRZZZRRRRRR1119991119991119991119991119991119991119991119991119991119991119991111R9)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1{B999111111111999111111111999111111111999111111111999111111111999111999RRRRRRRRRRRR֜ccckkkZZZ999JJJkkkcccsssRRRRRRRRRRRR111111999111111111999111111111999111111111999111111111999111111111999191)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1kB111999111999111999111999111999111999111999111999111999111999111999111ZZZRRRZZZRRRRRRZZZRRRZZZ999999111999111999111999111999111999111999111999111999111999111999111999)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1R9111111999111111111999111111111999111111111999111111111999111111111999BBBRRRRRRkkkRRRRRRRRRRRRBBB111111111999111111111999111111111999111111111999111111111999111111111)s9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J9B9111999111999111999111999111999111999111999111999111999111999111999111BBBRRRZZZJcRƔRRRZZZRRRZZZJJJ999111999111999111999111999111999111999111999111999111999111999111999)c9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J111999111111111999111111111999111111111999111111111999111111111999111111111JJJRRRB{R)B9R֭RRRRRRRRRRRRJJJ1119991111111119991111111119991111111119991111111119991111111119991111Z9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J1{B999111999111999111999111999111999111999111999111999111999111999111999111999999ZZZ9{J1J1J1JJZcccZZZRRRZZZJJJ9991119991119991119991119991119991119991119991119991119991119991119991J1)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1sB111111111999111111111999111111111999111111111999111111111999111111111999111111BBB9R)B1J)B1J)Bc{ZkBcJRRRRRRRRRBBB1111111119991111111119991111111119991111111119991111111119991111111111B9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1c99991119991119991119991119991119991119991119991119991119991119991119991119991119999sJ1J)J1J1J1J)J1JcsֽBZ)9)B9kJZZZRRRRRR111999111999111999111999111999111999111999111999111999111999111999111999111)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1R91119991111111119991111111119991111111119991111111119991111111119991111111119991111R9)B1J)B1J)B1J)B1J)BJc֭ތ1J)B!9)B!91{BRRRRRR999111111999111111111999111111111999111111111999111111111999111111111999111111)k9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J1119991119991119991119991119991119991119991119991119991119991119991119991119991119991111J1J1J)J1J1J1J)J1J1J1J)JƔεRc)B)9)B)9)B)9)B){9ZZZJJJ9991119991119991119991119991119991119991119991119991119991119991119991119991111c9)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B9991111111119991111111119991111111119991111111119991111111119991111111119991111111119991c91J)B1J)B1J)B1J)B1J)B1J)B1JJZΜޥέJc)B!9)B!9)B!9)B!9)B!9)BJJJ999111999111111111999111111111999111111111999111111111999111111111999111111111999)R1)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1{B111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1JJZΜֽ{BR)B)9)B)9)B)9)B)9)B)9)B)9)B)91B91119991119991119991119991119991119991119991119991119991119991119991119991119991111J9)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1c91111119991111111119991111111119991111111119991111111119991111111119991111111119991111111111cB)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)Bc{Υޥέ{BZ!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9){9111999111111111999111111111999111111111999111111111999111111111999111111111999111111191)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1Z91119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991111B)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1Jcs֭֜ƥ{Rk)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B1R9999111999111999111999111999111999111999111999111999111999111999111999111999111999111999){9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1B99991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111911J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JcsƔΥֽƜƥcsRc)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B)s9999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111)s9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J9991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991J91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1JBZcsk{Υ֭޽֥εƥƥƥsZscsBR)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)91J9111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999)c9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1Z91111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111Z91J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91c91111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111111Z9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1cB1119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991kB1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9){B1919991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991J9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1sB1111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111sB1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B1B1111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991sB1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B1J99991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991111R9)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1B1911111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111sB1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B)R1111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111)c9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J99991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991c91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B1R99991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991111kB)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1R9111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B)R1111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999191)s9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1kB9991119991119991119991119991119991119991119991119991119991119991119991119991119R91J1sB1B19991119991119991119991119991119991119991119991111J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B1R9999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999191)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J){B1111119991111111119991111111119991111111119991111111119991111111119991111111111kB)B1J)B1J)s91B9111999111111111999111111111999111111111999){B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B)R11111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991B1)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J9B91119991119991119991119991119991119991119991119991119991119991119991119991911J1J1J)J1J1J1J)J1{B1J99991119991119991119991119991119991B91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)k99991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991R9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1c91119991111111119991111111119991111111119991111111119991111111119991111111B91J)B1J)B1J)B1J)B1J)B1J1{B1R91111111119991111111119991111{B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91Z91119991111111119991111111119991111111119991111111B11k9)s91B9111999111111111999111111111999111111111999111111111999111111111999111111111999)c9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1B1119991119991119991119991119991119991119991119991119991119991119991119991Z91J1J1J)J1J1J1J)J1J1J1J)J1J1J1B1J99991119991119991111sB)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)c99991119991119991119991119991119991119991111J9)k9)B)9)B)91Z9111999111999111999111999111999111999111999111999111999111999111999111999111999)s9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1B19991111111119991111111119991111111119991111111119991111111119991111111sB1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1{B1c91kB1k91J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B1911111119991111111119991111111119991B1)s9!9)B!9)B!9)B!9)c91919991111111119991111111119991111111119991111111119991111111119991111111111B9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J1sB9991119991119991119991119991119991119991119991119991119991119991119991B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)91k91119991119991119991119991111R9)s9)B)9)B)9)B)9)B)9)B)9){B1B99991119991119991119991119991119991119991119991119991119991119991119991111c9)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1B91111111119991111111119991111111119991111111119991111111119991111R9)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91c9111111111999111111)R1){B!9)B!9)B!9)B!9)B!9)B!9)B!9){91J1999111111111999111111111999111111111999111111111999111111111999111111111)s9!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1{B1119991119991119991119991119991119991119991119991119991119991111cB)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9){B)c91c91Z9)sB){9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B1Z99991119991119991119991119991119991119991119991119991119991119991119991J9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J1B11111119991111111119991111111119991111111119991111111119991911sB)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B)k9199111111111999111111111999111111111999111111111999111111111999111111)k9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1B9991119991119991119991119991119991119991119991119991119991J91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B){91B91119991119991119991119991119991119991119991119991119991119991119B9)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1sB1119991111111119991111111119991111111119991111111119991Z91J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B){91R9111111111999111111111999111111111999111111111999111111111999111)s9!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J1c99991119991119991119991119991119991119991119991119991kB1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)91k91119991119991119991119991119991119991119991119991119991119991R9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1Z91111111119991111111119991111111119991111111111B9)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)s9191111111999111111111999111111111999111111111999111111111199!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J99991119991119991119991119991119991119991119ZB1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B1J1999111999111999111999111999111999111999111999111999111)sB)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1kB1119991111111119991111111119991111111911sB)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9JZRc{!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B)Z9111111999111111111999111111111999111111111999111111)Z9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J1kB9991119991119991119991119991119991J91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9BRRcsƭƽ)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)k99991119991119991119991119991119991119991119991111c9)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J1111111119991111111119991111991k91J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91JRcs{Rc)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!{91J9111999111111111999111111111999111111111999)Z9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J9R91119991119991119991111ZB)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)91JRck{{cs)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)91c9191999111999111999111999111999111999JJJ9cB)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J1{B9991111111119991R91B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)BRcZk{{)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)s91B1999111111111999111111111999111RRR1sB)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1{B1Z91R91sB1B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)BJZRc{Δ)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B1Z9999111999111999111999111999JRR)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B)B!9)B!9)B!9)B!9)B!9)B!9)B9JRc{ν֥)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B)s91R9111111111999111111999BcJ!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)9)B)9)B)9)B9RRcs{Ƶ)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)sB1J19991119991119B9){B)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J9JRccs{1J!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B)s91c91J11R9)k9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1JZkcsƵRc)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)BRcRkƵks!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1JBZRkƵƽ{)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)BBZRks{ƵƵΜ!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J9RRks{ƭƭ֥)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JRkcs{!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1JJcZkƭBR)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JBRZk{νRc)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1JBZZksƭνs)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1JZkk{ƭ{)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)JZkcsƵέ)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B֭)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J9RƵ)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1JƵ9R!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1JBZνRc)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JJZ{!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1JJcք)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1Jk{Υ!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1Jk{ֽƽ)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1Js!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1JJZ)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J޽Rc)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J֭΄)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1Jkccc999111111111999111111111999JJJsss֌)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1Jk{999111999111999111999111999111999111999111BBBέ)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B111111111999111111111999111111111999111111111999111RRR)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J999111999111999111999111999111999111999111999111999111999RRR)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B111999111111111999111111111999111111111999111111111999111111111kkkRc!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J޽RRR111999111999111999111999111999111999111999111999111999111999111999Zk)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B֭sss111111999111111111999111111111999111111111999111111111999111111111999{!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1Jcs111999111999111999111999111999111999111999111999111999111999111999111999ZZZ֔)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)BZkBBB111111111999111111111999111111111999111111111999111111111999111111111999ZZZΥ!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)JƥkkkBBB999111ֵZZZ999111999111999111999111999111999111999111999111999kkk)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JΜkkkJJJ111111999111111111999111111ZZZ1111119991111111119991111111119991111111119991B)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1JέkkkZZZ999111999111999111999111999111999111999111999111RRRkkk111999111999111999111999111999111999111999Rc)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J֭ε{{{ZZZ111111999111111111999111111111999111111111999111111111999111111111999111111999111111111999111111111999111111111BBBcs)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J֭Ɯ{{{kkk999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999BBB999111999111999111999111999111999111kkk΄)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1Jcs111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111ZZZ999111111111999111111111999111111111֜)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1JJcBBB111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999BBB999111999111999111999111999111999RRRέ)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)BBBB111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111999111111111999111111111999111111)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1JBBB111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111RRR9R)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)BBBB111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999ccckkk111999111111111999111111111999111Rc!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1JΥBBB111999111999111999111999111999111999111999111999111999111999111999kkk{{{Υkkkkkkkkkkkk999111999111999111999111999111999ZZZs{)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)BΜBBB111999111111111999111111111999111111111999BBBkkk΄BBB999111111111999111111111999BBB111111999111111111999111111111999{!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1JcsBBB111999111999111999111999111999111999111999kkk999111999111999111999111999111999111999111BBB111999111999111999111999111999111֥)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)BJcZZZ111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111kkk111111111999111111111999111111JJJεƵ!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)Jccc111999111999111999111999111999111999111999ccc111999111999111999111999111999111999111999111999111999111999BBB999111999111999111999111999111999)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JZZZ111999111111111999111111111999111111111999ZZZ1111111119991111111119991111111119991111111119991111111119991111111119991111111119991111111119991119J)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1Jccc111999111999111999111999111999111999111999ccc111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999kkkRc)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JΥZZZ111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999s{)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)JƔccc111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999ZZZkkkkkkkkk111999111999111999111999111999111999111999111999111Ό)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JcsZZZ111999111111111999111111111999111111111999111111999111111111999111111111999111111cccZZZ111111111999111111111999111111111999111111֥)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1JBZccc111999111999111999111999111999111999111999999111999111999111999111999111999111999111999111999111999111999111999111999111ν)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)BZZZ111999111111111999111111111999111111111999111999111111111999111111111999111111111111111999111111111999111111111999ccc)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1Jkkk111999111999111999111999111999111999111999sss999111999111999111999111999111999RRR111999111999111999111999111999111ZZZJZ)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B޽111999111111111999111111111999111111111BBBBBB111111111999111111111999111111111999111111111999111111111999111111111Rc!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1JΥ111999111999111999111999111999111999111BBB111999111999111999111999111999111kkk111999111999111999111999111999111999{)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)Bs111999111111111999111111111999111111111ZZZ111111999111111111999111111111999kkk111999111111111999111111111999111Ό!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1Jcs111999111999111999111999111999111999111{{{111999111999111999111999111999111999111999111999111999111999111999֥)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J111999111111111999111111111999111111111999111111111999111111111999111111111111111999111111111999111111111!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J111999111999111999111999111999111999111111999111999111999111999111999111999111999111999111999111999111999)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J111999111111111999111111111999111111ccc111111999111111111999111111111999ccc111999111111111999111111111999111Rc)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1Jccc111999111999111999111999111999111999111999111999111999111999111999111ZZZ999111999111999111999111999111999ck)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JΥBBB111999111111111999111111111999111RRR999111111111999111111111999111111111111111111999111111111999111111111{)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)Jk{999111999111999111999111999111999111kkk999111999111999111999111999111999999111999111999111999111999111kkkΔ)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JRkccc111111999111111111999111111111999sss111999111111111999111111111999111kkkBBB111999111111111999111111111999֥)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J111999111999111999111999111999111999999111999111999111999111999111999111111999111999111999111999111999111)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)BRRR111111111999111111111999111111111BBB111111999111111111999111111111999JJJBBB9991111111119991111111119991111111J!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J999111999111999111999111999111999111999111999111999111999111999111999ZZZBBB999111999111999111999111999111999Rc)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)Bֵ111999111111111999111111111999111999111111111999111111111999111111111999BBBBBB999111111111999111111111999111111111ks!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1JΥ999111999111999111999111999111999kkk999111999111999111999111999111999111999111BBBssskkk999111999111999111999111999111999111999111kkk{)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)Bc{111111111999111111111999111111111kkkBBB999111111111999111111111999111111111999111111111999111111111999111111111999111111111999111111111BBBΜ!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1JJc999111999111999111999111999111999kkk111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999111999֥)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J111111999111111111999111111111999111sss111999111111111999111111111999111111111999111111111999111111111999111111111999111111111999!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)JZZZ1119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991119991J)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JZZZ111999111111111999111111111999111111111111999111111111999111111111999111111111999111111111999111111111999111111111BBBRc)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J֭BBB111999111999111999111999111999111999111BBBZZZ999111999111999111999111999111999111999111999111999111999111999111kkks)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JƜ999111kkkΜZZZ111111111999111111111999111111111999111111111999BBB111111111999111111111999111111111999111111111999111111ccc{)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)Jk{111999111999111999111999111999111999111999111999111999111999111999111999111999111999BBBsss999111999111999111999111999111999111999ZZZέƭ)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JBZ111111999111111111999111111111999111111111999111111111999111111111999111111111999111Ɯccckkkccckkkccc֭)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1JZZZ111999111999111999111999111999111999111999111999111999111999111999111999111999111)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B111999111111111999111111111999111111111999111111111999111111111999111111111999111BR!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!91J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J999111999111999111999111999111999111999111999111999111999111999111999111999111Rc)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)BΥ111111111999111111111999111111111999111111111999111111111999111111111999JJJֽB{!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B)9)B)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J{999111999111999111999111999111999111999111999111999111999111999111RRRֵ){k)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)9)B)B1B)B1J)B1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)Bc{111999111111111999111111111999111111111999111111111999111111sss֥kck!9)B!9)B!9)B!9)B!9)B!9)B!9)B!9)B)9)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J9RZZZ111999111999111999111999111999111999111kkkքcccc)B)9)B)9)B)9)B)9)B)B1B)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JƜZcccZc!9)B)9)B)B)B)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)JBcccccc)c1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J޽ν!scccZccc!c1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J֭kcccccccc)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JssZcccZcccZc{1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)Jk{sB!{{sccccccccccs1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)BB1{{{{{{{{{{{ccZcccZcccc1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1JRB{{{{{{{{{{{{{{ccccccccccc)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)BcB{{{{{{{{{{{{{{{{{{{{{{{{{ccccZcccZcc!k)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J޽cB{{{{{{{{{{{{{{{{{{{{{{{kcccccccccc!s1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)BΥsB!{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{kcZcccZcccZ{)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1JcsB1{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{sccccccccccs1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)BZkR1{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{scccZcccZccs)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1JRB{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ccccccccccc1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JcB{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{B!{{{{{{{{{{{{{{cZcccZcccZc)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)JsB!{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{kcccccccccc)k1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J֭B1{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{R{{{{c{{{{{{{{{{{{{{{kccZcccZcccs1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J֭R1{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{1Rc{B{{{1{{{{{{{{{{{kcccccccccc)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1JcsRB{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{!{{1{{{1{{{{{{{{{{{{{{{{sZcccZcccZcs1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)JJccB{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{BBBB{{{{{{{{{s{{{{{{{{{{{{sccccccccccs1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)BsB!{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{R!{{{cc{{{{{{{{{{{{{{{{{{{{{{ccZcccZcccZ1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1JB1{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{1{{BRB{{{{{{Bc{{{{{{{{{{{{{{kcccccccccc)R1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)BR1{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{cR{{{{{{c{{{{{{{{{{{{c{B{{{{{{{{{{{{{{{{{{ccccZcccZcc!k)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1JΥRB{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{1{{{B!{!{{{{{{{{{s!{{{{{{{{{{{{{kcccccccccc1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B{ƜcB{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{1Bc{{{{{{{{{1{{{{{{{{B{{1{{{{{{{{{BR1{{{{{{{{{{{{{{{{kcZcccZcccZ{)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J!s{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{B{B{{!B{{{!c{{{{{{{{{{{{{cccccccccck1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B)c{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{!R1{{{{{{B{{{{{{s{{{{c{{{1{{{{1{{1{{{{{{{{{{{{{{{{{{{{{{scccZcccZcck)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J{{{{{{{{{{{{{{{{{{{{{{{{{{{c{{{{c{{{{{s{{{{{{{B{{B{{Rc{{{!{{c{{{{{{{{{{{{ccccccccccc1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{!{{{{{{{{{{{{c{{{{{{!B{{B1{{{B{{{{B{{{B{{{{{{{{{{{{{{{{cZcccZcccZc)R1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J{{{{{{{{{{{{{B1{{{{{{c{{{{{B{{{{B{{{{{{R!{{{{sB!{{{{s{{{B{{{{{{{{{{{{kcccccccccc)k1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J{{{{{{{{{{{{{{B{{{{{{{1{{{{{{{{{{{1{{{{{{B{{{{{{{{{B{{{{{{{{{{{{{{{s{{{{{{{{{{{{{{{{{{{kccZcccZccc{{1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J!{{{{{{{{{{c{{{{Bc{{{{{{{{{{{{{{{B{{{{{{c{{{{{{B{{{{{{{B{B{{{{{{{{{{{{kccccccccck)c)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J!s{{{{{{{{{{{{{B{{{{{{{{{{{{{{{{{{{!{{{{{R{{{{{{{B{{{{{{{{{R{{{{{{{{{{{{{{{{{{{{{{{{{{{ZcccZccck)R)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1Z{{{{{{{{{cR{{1{{{R{{{{{{{{{{{{B{{{{{{{{{B{{1{{R{{Bc{{{{{{{{{{{{{{sccccccck1R)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B{{{{{{{{{{{{c{{{{{BR{{{{{{{{{{{{{{{{{{s{{{{{{{{{{{{B{{{R{{{R{{{R{{{!{{{{{{{{{{{{{{{{{{{{ccZcccs1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J{{{{{{{!{{{{{{1{{{{{{{{{{{{s{{{{R{{{{{R{{{{{{R{{{1{{cBB{{{{{{{{{{{{{{{{{{kccccs1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B{{{{{{{{{{B{{{{{{{c{{!{{{{{{{{{{{{{{{B{{{{{{{{{{{{{{{BBc{{{{sB{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{cccc{1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J{{{{{{{{{{{{{{1{{B{{{{{{{{{{{{!{{{{{1{{{B1{{1R{{{{B!{{{{{{{{{{{{{{{{{{{{{{{{{{{{scc{1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B!{{{{{{{{{{{{{{{{{{R{{{{{{{{{{{{{{{{{{{{{{{{Bc{{{{{!{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{kcs1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J!s{{{{{{{c{{{{{{{{{{{{{{{{{{{1{B{B{{{c{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{)c1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J{{{{{{{{{{B{{{{{{{{{{RB{{{{{{{{{{{{{{{B{{R{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{!{)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J{{{{{{{1{{{{{{{{{{{{{{!{{B{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{){)R1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J{{{{{{{{{{s{{{{{{{B{{{Bc{{{B{B{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{!{)Z1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J{{{{{{{{{{{{!{{{{BsB!{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{){)c1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J{{{{{{{{{{!{{{{{{{{{{{{{B1{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{!{!k1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J!{{{{{{{{!{BR{{{{{{B!{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{!!s1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J!k{{{{{{{{{{{{{{{{{{{{{!cR1{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{!!s)R)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J{{{{{{{{{1{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{!!s1Z)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B{{{{{{{{{{{{B{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{!s)c)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J{{{{{{{{{{{BBBB{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{!s)k)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{!!{)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{){)R1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B!{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{!{)R1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J!k{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{){)Z1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{!{!k1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J{{{{{{{{{{{{{{{{{{{{!!s1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J{{{{{{{{{{{{{{{{{{{{{!!s)R)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J{{{{{{{{{{{!s1Z1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J{{{{{{{{!s)c)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J){{!s)s1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J1J1J)J1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B1J)B'}\par}}}{\rtlch\fcs1 \af1\afs33 \ltrch\fcs0 \f1\fs33\cf19\insrsid8454727\charrsid8454727 Zentyal 4.0, the next major Community Zentyal Edition -\par }\pard\plain \ltrpar\ql \li0\ri0\sl360\slmult1\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap2\pararsid14634989 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe2052\loch\af0\hich\af0\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf20\insrsid8454727\charrsid8454727 In 2 weeks Zentyal 4.0 will be released! It will be a }{\rtlch\fcs1 \ab\af1\afs21 \ltrch\fcs0 \cs21\b\f1\fs21\cf20\insrsid8454727\charrsid8454727 greatly improved Small Business Server}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf20\insrsid8454727\charrsid8454727 with native Microsoft Exchange compatibility.\line \line }{\rtlch\fcs1 \ab\af1\afs21 \ltrch\fcs0 \cs21\b\f1\fs21\cf20\insrsid8454727\charrsid8454727 Instead of waiting, you can give Zentyal 4.0 a try}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \cs22\f1\fs21\cf20\insrsid8454727\charrsid8454727 with our Daily Builds. }{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf20\insrsid8454727\charrsid8454727 Daily Builds are for testing and non-production environments only.\line \line }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \ab\af1\afs21 \ltrch\fcs0 \cs21\b\f1\fs21\cf20\insrsid8454727\charrsid8454727 HYPERLINK "http://go.zentyal.com/e/24292/index-php-Daily-Builds/f1b69/413547931" }}{\fldrslt {\rtlch\fcs1 \ab\af1\afs21 \ltrch\fcs0 \cs15\b\f1\fs21\ul\cf19\insrsid8454727\charrsid8454727 Download and try the Daily Builds}}}\sectd \ltrsect\linex0\sectdefaultcl\sectrsid8454727\sftnbj {\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \cs22\f1\fs21\cf20\insrsid8454727\charrsid8454727 and }{\rtlch\fcs1 \ab\af1\afs21 \ltrch\fcs0 \cs21\b\f1\fs21\cf20\insrsid8454727\charrsid8454727 help us with testing}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \cs22\f1\fs21\cf20\insrsid8454727\charrsid8454727 . Reporting found bugs in the }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \cs22\f1\fs21\cf20\insrsid8454727\charrsid8454727 HYPERLINK "http://go.zentyal.com/e/24292/2014-10-15/f1mx3/413547931" }}{\fldrslt {\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \cs15\f1\fs21\ul\cf19\insrsid8454727\charrsid8454727 tracker}}}\sectd \ltrsect\linex0\sectdefaultcl\sectrsid8454727\sftnbj {\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \cs22\f1\fs21\cf20\insrsid8454727\charrsid8454727 are highly appreciated and will help to make the }{\rtlch\fcs1 \ab\af1\afs21 \ltrch\fcs0 \cs21\b\f1\fs21\cf20\insrsid8454727\charrsid8454727 final release}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \cs22\f1\fs21\cf20\insrsid8454727\charrsid8454727 a }{\rtlch\fcs1 \ab\af1\afs21 \ltrch\fcs0 \cs21\b\f1\fs21\cf20\insrsid8454727\charrsid8454727 rock solid}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \cs22\f1\fs21\cf20\insrsid8454727\charrsid8454727 }{\rtlch\fcs1 \ab\af1\afs21 \ltrch\fcs0 \cs21\b\f1\fs21\cf20\insrsid8454727\charrsid8454727 Microsoft Exchange drop-in replacement}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \cs22\f1\fs21\cf20\insrsid8454727\charrsid8454727 !}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf20\insrsid8454727\charrsid8454727 \nestcell{\nonesttables -\par }}\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap2 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \fs20\cf0\dbch\af0\insrsid8454727\charrsid8454727 {\*\nesttableprops\trowd \irow0\irowband0\ltrrow\ts11\trgaph300\trleft0\trftsWidth2\trwWidth5000\trautofit1\trpaddl300\trpaddt300\trpaddb300\trpaddr300\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid14634989\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw120\brdrcf21 \clbrdrl\brdrtbl \clbrdrb\brdrs\brdrw120\brdrcf21 \clbrdrr\brdrtbl \clcbpat22\cltxlrtb\clftsWidth1\clcbpatraw22\clhidemark \cellx9000\nestrow}{\nonesttables -\par }}\pard\plain \ltrpar\s4\ql \li0\ri0\sa150\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\outlinelevel3\adjustright\rin0\lin0\itap2\pararsid14634989 \rtlch\fcs1 \ab\af0\afs24\alang1025 \ltrch\fcs0 \b\fs24\lang1033\langfe2052\loch\af0\hich\af0\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af1\afs33 \ltrch\fcs0 \f1\fs33\cf19\insrsid8454727\charrsid8454727 TechRepublic features Zentyal -\par }\pard\plain \ltrpar\ql \li0\ri0\sl360\slmult1\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap2\pararsid14634989 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe2052\loch\af0\hich\af0\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \ab\af1\afs21 \ltrch\fcs0 \cs21\b\f1\fs21\cf20\insrsid8454727\charrsid8454727 TechRepublic.com}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf20\insrsid8454727\charrsid8454727 , a }{\rtlch\fcs1 \ab\af1\afs21 \ltrch\fcs0 \cs21\b\f1\fs21\cf20\insrsid8454727\charrsid8454727 leading website}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf20\insrsid8454727\charrsid8454727 that helps IT decision-makers identify technologies and strategies to empower workers and streamline business processes, }{\rtlch\fcs1 \ab\af1\afs21 \ltrch\fcs0 \cs21\b\f1\fs21\cf20\insrsid8454727\charrsid8454727 has featured Zentyal}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf20\insrsid8454727\charrsid8454727 on their website:\line \line }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \cs21\b\f1\cf20\insrsid8454727\charrsid8454727 "If your small business is looking for a drop-in replacement for Windows Small Business Server, Jack Wallen might just have the perfect solution"}{\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf20\insrsid8454727\charrsid8454727 \line }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf20\insrsid8454727\charrsid8454727 HYPERLINK "http://go.zentyal.com/e/24292/ith-this-open-source-solution-/f1mx1/413547931" }}{\fldrslt {\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \cs15\f1\fs21\ul\cf19\insrsid8454727\charrsid8454727 Read the complete artice.}}}\sectd \ltrsect\linex0\sectdefaultcl\sectrsid8454727\sftnbj {\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf20\insrsid8454727\charrsid8454727 \line \~ -\par }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap3\pararsid14634989 {\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid5784989 \hich\af0\dbch\af31505\loch\f0 \hich\af0\dbch\af31505\loch\f0 INCLUDE\hich\af0\dbch\af31505\loch\f0 PICTURE \hich\af0\dbch\af31505\loch\f0 "http://go.zentyal.com/l/24292/2014-05-08/6w1p7/24292/38272/quote_png.png" \\* MERGEFORMAT \\d\hich\af0\dbch\af31505\loch\f0 }}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0 \cf0\lang1024\langfe1024\dbch\af0\noproof\insrsid5784989\charrsid5784989 }}}\sectd \ltrsect\linex0\sectdefaultcl\sectrsid8454727\sftnbj {\rtlch\fcs1 \af0 \ltrch\fcs0 \cf0\dbch\af0\insrsid8454727\charrsid8454727 \nestcell{\nonesttables -\par }}{\rtlch\fcs1 \ai\af0\afs21 \ltrch\fcs0 \cs23\i\fs21\cf20\dbch\af0\insrsid8454727\charrsid8454727 }{\rtlch\fcs1 \af0\afs21 \ltrch\fcs0 \fs21\cf20\dbch\af0\insrsid8454727\charrsid8454727 If you're looking for a drop-in replacement for Windows Small Business Server, look no further than Zentyal}{\rtlch\fcs1 \ai\af0\afs21 \ltrch\fcs0 \cs23\i\fs21\cf20\dbch\af0\insrsid8454727\charrsid8454727 }{\rtlch\fcs1 \af0\afs21 \ltrch\fcs0 \fs21\cf20\dbch\af0\insrsid8454727\charrsid8454727 \line \line }{\rtlch\fcs1 \ab\af0\afs21 \ltrch\fcs0 \cs21\b\fs21\cf20\dbch\af0\insrsid8454727\charrsid8454727 Jack Wallen, award-winning writer for TechRepublic and Linux.com}{\rtlch\fcs1 \af0\afs21 \ltrch\fcs0 \fs21\cf20\dbch\af0\insrsid8454727\charrsid8454727 \nestcell{\nonesttables -\par }}\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap3 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \fs20\cf0\dbch\af0\insrsid8454727\charrsid8454727 {\*\nesttableprops\trowd \irow0\irowband0\lastrow \ltrrow\ts11\trgaph15\trleft0\trftsWidth2\trwWidth5000\trautofit1\trspdl7\trspdt7\trspdb7\trspdr7\trspdfl3\trspdft3\trspdfb3\trspdfr3\trpaddl15\trpaddt15\trpaddb15\trpaddr15\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid14634989\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth1\clshdrawnil\clhidemark \cellx785\clvertalc\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth1\clshdrawnil\clhidemark \cellx8400\nestrow}{\nonesttables -\par }}\pard \ltrpar\ql \li0\ri0\sl360\slmult1\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap2\pararsid14634989 {\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf20\insrsid8454727\charrsid8454727 \line }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid5784989 \hich\af0\dbch\af31505\loch\f0 \hich\af0\dbch\af31505\loch\f0 INCLUDEPICTURE \hich\af0\dbch\af31505\loch\f0 "http://go.zentyal.com/l/24292/2014-10-08/dmpvk/24292/55818/TechRepublic_logo.png" \\* MERGEFORMAT \\d\hich\af0\dbch\af31505\loch\f0 }}{\fldrslt {\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf20\lang1024\langfe1024\noproof\insrsid5784989\charrsid5784989 }}}\sectd \ltrsect\linex0\sectdefaultcl\sectrsid8454727\sftnbj {\rtlch\fcs1 \af1\afs21 \ltrch\fcs0 \f1\fs21\cf20\insrsid8454727\charrsid8454727 \nestcell{\nonesttables -\par }}\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap2 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \fs20\cf0\dbch\af0\insrsid8454727\charrsid8454727 {\*\nesttableprops\trowd \irow1\irowband1\lastrow \ltrrow\ts11\trgaph300\trleft0\trftsWidth2\trwWidth5000\trautofit1\trpaddl300\trpaddt300\trpaddb300\trpaddr300\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid14634989\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw120\brdrcf21 \clbrdrl\brdrtbl \clbrdrb\brdrs\brdrw120\brdrcf21 \clbrdrr\brdrtbl \clcbpat22\cltxlrtb\clftsWidth1\clcbpatraw22\clhidemark \cellx9000\nestrow}{\nonesttables -\par }\ltrrow}\trowd \irow0\irowband0\lastrow \ltrrow\ts11\trqc\trleft0\trftsWidth3\trwWidth12000\trautofit1\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid14634989\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \clcbpat8\cltxlrtb\clftsWidth3\clwWidth9000\clcbpatraw8\clhidemark \cellx9000\clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \clcbpat21\cltxlrtb\clftsWidth3\clwWidth3000\clcbpatraw21\clhidemark \cellx12000\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\pararsid14634989 {\rtlch\fcs1 \af0 \ltrch\fcs0 \cf0\dbch\af0\insrsid8454727\charrsid8454727 \cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap2\pararsid14634989 {\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \cf0\dbch\af0\insrsid8454727\charrsid8454727 HYPERLINK "http://go.zentyal.com/e/24292/zentyal/f1b6h/413547931" \\o "go to Zentyal Facebook" }}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0 \cs15\ul\cf17\dbch\af0\insrsid8454727\charrsid8454727 Facebook}}}\sectd \ltrsect\linex0\sectdefaultcl\sectrsid8454727\sftnbj {\rtlch\fcs1 \af0 \ltrch\fcs0 \cf0\dbch\af0\insrsid8454727\charrsid8454727 }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \cf0\dbch\af0\insrsid8454727\charrsid8454727 HYPERLINK "http://go.zentyal.com/e/24292/--zentyal/f1b6k/413547931" \\o "go to Zentyal Twitter" }}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0 \cs15\ul\cf17\dbch\af0\insrsid8454727\charrsid8454727 Twitter}}}\sectd \ltrsect\linex0\sectdefaultcl\sectrsid8454727\sftnbj {\rtlch\fcs1 \af0 \ltrch\fcs0 \cf0\dbch\af0\insrsid8454727\charrsid8454727 }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \cf0\dbch\af0\insrsid8454727\charrsid8454727 HYPERLINK "http://go.zentyal.com/e/24292/zentyal/f1b6m/413547931" \\o "go toZentyal Flick" }}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0 \cs15\ul\cf17\dbch\af0\insrsid8454727\charrsid8454727 Flick}}}\sectd \ltrsect\linex0\sectdefaultcl\sectrsid8454727\sftnbj {\rtlch\fcs1 \af0 \ltrch\fcs0 \cf0\dbch\af0\insrsid8454727\charrsid8454727 }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \cf0\dbch\af0\insrsid8454727\charrsid8454727 HYPERLINK "http://go.zentyal.com/e/24292/zentyal/f1b6p/413547931" \\o "go to Zentyal Youtube channel" }}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0 \cs15\ul\cf17\dbch\af0\insrsid8454727\charrsid8454727 Youtube}}}\sectd \ltrsect\linex0\sectdefaultcl\sectrsid8454727\sftnbj {\rtlch\fcs1 \af0 \ltrch\fcs0 \cf0\dbch\af0\insrsid8454727\charrsid8454727 \nestcell{\nonesttables -\par }}\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap2 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \fs20\cf0\dbch\af0\insrsid8454727\charrsid8454727 {\*\nesttableprops\trowd \irow0\irowband0\lastrow \ltrrow\ts11\trleft0\trftsWidth2\trwWidth5000\trautofit1\trspdl150\trspdt150\trspdb150\trspdr150\trspdfl3\trspdft3\trspdfb3\trspdfr3\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid14634989\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalc\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth1\clshdrawnil\clhidemark \cellx3000\nestrow}{\nonesttables -\par }\ltrrow}\trowd \irow0\irowband0\lastrow \ltrrow\ts11\trqc\trleft0\trftsWidth3\trwWidth12000\trautofit1\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid14634989\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \clcbpat8\cltxlrtb\clftsWidth3\clwWidth9000\clcbpatraw8\clhidemark \cellx9000\clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \clcbpat21\cltxlrtb\clftsWidth3\clwWidth3000\clcbpatraw21\clhidemark \cellx12000\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\pararsid14634989 {\rtlch\fcs1 \af0 \ltrch\fcs0 \cf0\dbch\af0\insrsid8454727\charrsid8454727 -\par }\pard\plain \ltrpar\s4\ql \li0\ri0\sa150\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\outlinelevel3\adjustright\rin0\lin0\itap2\pararsid14634989 \rtlch\fcs1 \ab\af0\afs24\alang1025 \ltrch\fcs0 \b\fs24\lang1033\langfe2052\loch\af0\hich\af0\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af1\afs27 \ltrch\fcs0 \f1\fs27\cf23\insrsid8454727\charrsid8454727 Download Zentyal 4.0 -\par }\pard\plain \ltrpar\ql \li0\ri0\sl360\slmult1\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap2\pararsid14634989 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe2052\loch\af0\hich\af0\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\cf20\insrsid8454727\charrsid8454727 Download }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\cf20\insrsid8454727\charrsid8454727 HYPERLINK "http://go.zentyal.com/e/24292/index-php-Daily-Builds/f1b69/413547931" }}{\fldrslt {\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \cs15\f1\fs18\ul\cf19\insrsid8454727\charrsid8454727 Zentyal 4.0 Daily Builds }}}\sectd \ltrsect\linex0\sectdefaultcl\sectrsid8454727\sftnbj {\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\cf20\insrsid8454727\charrsid8454727 and join the testing effort! We are looking forward to receiving your feedback and comments!\nestcell{\nonesttables -\par }}\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap2 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \fs20\cf0\dbch\af0\insrsid8454727\charrsid8454727 {\*\nesttableprops\trowd \irow0\irowband0\ltrrow\ts11\trgaph300\trleft0\trftsWidth2\trwWidth5000\trautofit1\trpaddl300\trpaddt300\trpaddb300\trpaddr300\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid14634989\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth1\clshdrawnil\clhidemark \cellx3000\nestrow}{\nonesttables -\par }}\pard\plain \ltrpar\s4\ql \li0\ri0\sa150\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\outlinelevel3\adjustright\rin0\lin0\itap2\pararsid14634989 \rtlch\fcs1 \ab\af0\afs24\alang1025 \ltrch\fcs0 \b\fs24\lang1033\langfe2052\loch\af0\hich\af0\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af1\afs27 \ltrch\fcs0 \f1\fs27\cf23\insrsid8454727\charrsid8454727 Evaluating the Commercial Zentyal Server Edition? -\par }\pard\plain \ltrpar\ql \li0\ri0\sl360\slmult1\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap2\pararsid14634989 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe2052\loch\af0\hich\af0\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\cf20\insrsid8454727\charrsid8454727 Are you thinking about deploying a }{\rtlch\fcs1 \ab\af1\afs18 \ltrch\fcs0 \cs21\b\f1\fs18\cf20\insrsid8454727\charrsid8454727 commercially supported}{\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\cf20\insrsid8454727\charrsid8454727 Zentyal Server in your organization? Get a }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\cf20\insrsid8454727\charrsid8454727 HYPERLINK "http://go.zentyal.com/e/24292/trial-zentyal-premium-edition-/f1b6r/413547931" }}{\fldrslt {\rtlch\fcs1 \ab\af1\afs18 \ltrch\fcs0 \cs21\b\f1\fs18\ul\cf19\insrsid8454727\charrsid8454727 Free 30-Day Trial}}}\sectd \ltrsect\linex0\sectdefaultcl\sectrsid8454727\sftnbj {\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\cf20\insrsid8454727\charrsid8454727 or }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \ab\af1\afs18 \ltrch\fcs0 \cs21\b\f1\fs18\cf20\insrsid8454727\charrsid8454727 HYPERLINK "http://go.zentyal.com/e/24292/contact-sales-/f1b6t/413547931" }}{\fldrslt {\rtlch\fcs1 \ab\af1\afs18 \ltrch\fcs0 \cs15\b\f1\fs18\ul\cf19\insrsid8454727\charrsid8454727 Contact Sales}}}\sectd \ltrsect\linex0\sectdefaultcl\sectrsid8454727\sftnbj {\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\cf20\insrsid8454727\charrsid8454727 for a quote.\nestcell{\nonesttables -\par }}\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap2 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \fs20\cf0\dbch\af0\insrsid8454727\charrsid8454727 {\*\nesttableprops\trowd \irow1\irowband1\ltrrow\ts11\trgaph300\trleft0\trftsWidth2\trwWidth5000\trautofit1\trpaddl300\trpaddt300\trpaddb300\trpaddr300\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid14634989\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth1\clshdrawnil\clhidemark \cellx3000\nestrow}{\nonesttables -\par }}\pard\plain \ltrpar\s4\ql \li0\ri0\sa150\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\outlinelevel3\adjustright\rin0\lin0\itap2\pararsid14634989 \rtlch\fcs1 \ab\af0\afs24\alang1025 \ltrch\fcs0 \b\fs24\lang1033\langfe2052\loch\af0\hich\af0\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af1\afs27 \ltrch\fcs0 \f1\fs27\cf23\insrsid8454727\charrsid8454727 On-line Zentyal Training -\par }\pard\plain \ltrpar\ql \li0\ri0\sl360\slmult1\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap2\pararsid14634989 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe2052\loch\af0\hich\af0\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\cf20\insrsid8454727\charrsid8454727 Are you interested in deploying Zentyal Server professionally? Zentyal offers }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\cf20\insrsid8454727\charrsid8454727 HYPERLINK "http://go.zentyal.com/e/24292/ing-online-courses-bundle-html/f1b6w/413547931" }}{\fldrslt {\rtlch\fcs1 \ab\af1\afs18 \ltrch\fcs0 \cs21\b\f1\fs18\ul\cf19\insrsid8454727\charrsid8454727 on-line training courses}}}\sectd \ltrsect\linex0\sectdefaultcl\sectrsid8454727\sftnbj {\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\cf20\insrsid8454727\charrsid8454727 and a }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\cf20\insrsid8454727\charrsid8454727 HYPERLINK "http://go.zentyal.com/e/24292/training-zeca-voucher-html/f1b6y/413547931" }}{\fldrslt {\rtlch\fcs1 \ab\af1\afs18 \ltrch\fcs0 \cs21\b\f1\fs18\ul\cf19\insrsid8454727\charrsid8454727 certification exam}}}\sectd \ltrsect\linex0\sectdefaultcl\sectrsid8454727\sftnbj {\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\cf20\insrsid8454727\charrsid8454727 , that give you full understanding and skills to carry out Zentyal deployments correctly.\nestcell{\nonesttables -\par }}\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap2 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \fs20\cf0\dbch\af0\insrsid8454727\charrsid8454727 {\*\nesttableprops\trowd \irow2\irowband2\ltrrow\ts11\trgaph300\trleft0\trftsWidth2\trwWidth5000\trautofit1\trpaddl300\trpaddt300\trpaddb300\trpaddr300\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid14634989\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth1\clshdrawnil\clhidemark \cellx3000\nestrow}{\nonesttables -\par }}\pard\plain \ltrpar\s4\ql \li0\ri0\sa150\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\outlinelevel3\adjustright\rin0\lin0\itap2\pararsid14634989 \rtlch\fcs1 \ab\af0\afs24\alang1025 \ltrch\fcs0 \b\fs24\lang1033\langfe2052\loch\af0\hich\af0\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af1\afs27 \ltrch\fcs0 \f1\fs27\cf23\insrsid8454727\charrsid8454727 Zentyal On-line Certification Exams -\par }\pard\plain \ltrpar\ql \li0\ri0\sl360\slmult1\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap2\pararsid14634989 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe2052\loch\af0\hich\af0\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\cf20\insrsid8454727\charrsid8454727 Next Zentyal Certification Exams will take place (on-line): }{\rtlch\fcs1 \ab\af1\afs18 \ltrch\fcs0 \cs21\b\f1\fs18\cf20\insrsid8454727\charrsid8454727 November 27 }{\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\cf20\insrsid8454727\charrsid8454727 and }{\rtlch\fcs1 \ab\af1\afs18 \ltrch\fcs0 \cs21\b\f1\fs18\cf20\insrsid8454727\charrsid8454727 December 18}{\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\cf20\insrsid8454727\charrsid8454727 . Book you seat by purchasing the }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\cf20\insrsid8454727\charrsid8454727 HYPERLINK "http://go.zentyal.com/e/24292/training-zeca-voucher-html/f1b6y/413547931" }}{\fldrslt {\rtlch\fcs1 \ab\af1\afs18 \ltrch\fcs0 \cs21\b\f1\fs18\ul\cf19\insrsid8454727\charrsid8454727 ZeCA Exam Voucher}}}\sectd \ltrsect\linex0\sectdefaultcl\sectrsid8454727\sftnbj {\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\cf20\insrsid8454727\charrsid8454727 !\nestcell{\nonesttables -\par }}\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap2 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \fs20\cf0\dbch\af0\insrsid8454727\charrsid8454727 {\*\nesttableprops\trowd \irow3\irowband3\lastrow \ltrrow\ts11\trgaph300\trleft0\trftsWidth2\trwWidth5000\trautofit1\trpaddl300\trpaddt300\trpaddb300\trpaddr300\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid14634989\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth1\clshdrawnil\clhidemark \cellx3000\nestrow}{\nonesttables -\par }\ltrrow}\trowd \irow0\irowband0\lastrow \ltrrow\ts11\trqc\trleft0\trftsWidth3\trwWidth12000\trautofit1\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid14634989\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \clcbpat8\cltxlrtb\clftsWidth3\clwWidth9000\clcbpatraw8\clhidemark \cellx9000\clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \clcbpat21\cltxlrtb\clftsWidth3\clwWidth3000\clcbpatraw21\clhidemark \cellx12000\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\pararsid14634989 {\rtlch\fcs1 \af0 \ltrch\fcs0 \cf0\dbch\af0\insrsid8454727\charrsid8454727 \cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \fs20\cf0\dbch\af0\insrsid8454727\charrsid8454727 \trowd \irow0\irowband0\lastrow \ltrrow\ts11\trqc\trleft0\trftsWidth3\trwWidth12000\trautofit1\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid14634989\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \clcbpat8\cltxlrtb\clftsWidth3\clwWidth9000\clcbpatraw8\clhidemark \cellx9000\clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \clcbpat21\cltxlrtb\clftsWidth3\clwWidth3000\clcbpatraw21\clhidemark \cellx12000\row }\pard \ltrpar\qc \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid8454727 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f1\cf0\insrsid8454727\charrsid8454727 -\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid8454727 {\rtlch\fcs1 \af37 \ltrch\fcs0 \f37\cf0\insrsid8454727\charrsid8454727 -\par }} \ No newline at end of file diff --git a/Attic/Fixtures/zentyal_crash_8346.rtf b/Attic/Fixtures/zentyal_crash_8346.rtf deleted file mode 100644 index de7fd5f12..000000000 --- a/Attic/Fixtures/zentyal_crash_8346.rtf +++ /dev/null @@ -1,378 +0,0 @@ -{\rtf1\ansi\ansicpg1252\uc1\deff0\stshfdbch0\stshfloch0\stshfhich0\stshfbi0\deflang3082\deflangfe3082{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;}{\f35\fswiss\fcharset0\fprq2{\*\panose 020b0604030504040204}Tahoma;}{\f36\fswiss\fcharset0\fprq2{\*\panose 020b0506020202030204}Arial Narrow;}{\f37\fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\f44\fswiss\fcharset0\fprq2{\*\panose 020b0604030504040204}Verdana;}{\f45\fswiss\fcharset0\fprq2{\*\panose 020b0a04020102020204}Arial Black;}{\f91\froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}{\f98\froman\fcharset238\fprq2 Times New Roman CE;}{\f99\froman\fcharset204\fprq2 Times New Roman Cyr;}{\f101\froman\fcharset161\fprq2 Times New Roman Greek;}{\f102\froman\fcharset162\fprq2 Times New Roman Tur;}{\f103\froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f104\froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f105\froman\fcharset186\fprq2 Times New Roman Baltic;}{\f106\froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f108\fswiss\fcharset238\fprq2 Arial CE;}{\f109\fswiss\fcharset204\fprq2 Arial Cyr;}{\f111\fswiss\fcharset161\fprq2 Arial Greek;}{\f112\fswiss\fcharset162\fprq2 Arial Tur;}{\f113\fswiss\fcharset177\fprq2 Arial (Hebrew);}{\f114\fswiss\fcharset178\fprq2 Arial (Arabic);}{\f115\fswiss\fcharset186\fprq2 Arial Baltic;}{\f116\fswiss\fcharset163\fprq2 Arial (Vietnamese);}{\f448\fswiss\fcharset238\fprq2 Tahoma CE;}{\f449\fswiss\fcharset204\fprq2 Tahoma Cyr;}{\f451\fswiss\fcharset161\fprq2 Tahoma Greek;}{\f452\fswiss\fcharset162\fprq2 Tahoma Tur;}{\f453\fswiss\fcharset177\fprq2 Tahoma (Hebrew);}{\f454\fswiss\fcharset178\fprq2 Tahoma (Arabic);}{\f455\fswiss\fcharset186\fprq2 Tahoma Baltic;}{\f456\fswiss\fcharset163\fprq2 Tahoma (Vietnamese);}{\f457\fswiss\fcharset222\fprq2 Tahoma (Thai);}{\f458\fswiss\fcharset238\fprq2 Arial Narrow CE;}{\f459\fswiss\fcharset204\fprq2 Arial Narrow Cyr;}{\f461\fswiss\fcharset161\fprq2 Arial Narrow Greek;}{\f462\fswiss\fcharset162\fprq2 Arial Narrow Tur;}{\f465\fswiss\fcharset186\fprq2 Arial Narrow Baltic;}{\f468\fswiss\fcharset238\fprq2 Calibri CE;}{\f469\fswiss\fcharset204\fprq2 Calibri Cyr;}{\f471\fswiss\fcharset161\fprq2 Calibri Greek;}{\f472\fswiss\fcharset162\fprq2 Calibri Tur;}{\f475\fswiss\fcharset186\fprq2 Calibri Baltic;}{\f538\fswiss\fcharset238\fprq2 Verdana CE;}{\f539\fswiss\fcharset204\fprq2 Verdana Cyr;}{\f541\fswiss\fcharset161\fprq2 Verdana Greek;}{\f542\fswiss\fcharset162\fprq2 Verdana Tur;}{\f545\fswiss\fcharset186\fprq2 Verdana Baltic;}{\f546\fswiss\fcharset163\fprq2 Verdana (Vietnamese);}{\f548\fswiss\fcharset238\fprq2 Arial Black CE;}{\f549\fswiss\fcharset204\fprq2 Arial Black Cyr;}{\f551\fswiss\fcharset161\fprq2 Arial Black Greek;}{\f552\fswiss\fcharset162\fprq2 Arial Black Tur;}{\f555\fswiss\fcharset186\fprq2 Arial Black Baltic;}{\f1008\froman\fcharset238\fprq2 Cambria CE;}{\f1009\froman\fcharset204\fprq2 Cambria Cyr;}{\f1011\froman\fcharset161\fprq2 Cambria Greek;}{\f1012\froman\fcharset162\fprq2 Cambria Tur;}{\f1015\froman\fcharset186\fprq2 Cambria Baltic;}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;\red255\green102\blue0;\red51\green204\blue204;\red31\green73\blue125;\red192\green80\blue77;\red153\green153\blue153;\red181\green196\blue223;}{\stylesheet{\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \fs24\lang3082\langfe3082\cgrid\langnp3082\langfenp3082 \snext0 Normal;}{\*\cs10 \additive \ssemihidden Default Paragraph Font;}{\*\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tscellwidthfts0\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \fs20\lang1024\langfe1024\cgrid\langnp1024\langfenp1024 \snext11 \ssemihidden Normal Table;}{\*\cs15 \additive \ul\cf2 \sbasedon10 Hyperlink;}{\*\cs16 \additive \ul\cf12 \sbasedon10 FollowedHyperlink;}{\s17\ql \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \fs24\lang3082\langfe3082\cgrid\langnp3082\langfenp3082 \sbasedon0 \snext17 Normal (Web);}{\*\cs18 \additive \f35 \sbasedon10 \slink19 \slocked Texto de globo Car;}{\s19\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f35\fs16\lang3082\langfe3082\cgrid\langnp3082\langfenp3082 \sbasedon0 \snext19 \slink18 Balloon Text;}{\*\cs20 \additive \f35 \sbasedon10 textodeglobocar;}{\*\cs21 \additive \b0\i0\strike0\f36\ulnone\cf0\animtext0\striked0 \sbasedon10 \ssemihidden \spersonal EstiloCorreo21;}{\*\cs22 \additive \b0\i0\strike0\f36\ulnone\cf0\animtext0\striked0 \sbasedon10 \ssemihidden \spersonal EstiloCorreo22;}{\*\cs23 \additive \f37\cf19 \sbasedon10 \ssemihidden \spersonal EstiloCorreo23;}{\*\cs24 \additive \f37\cf19 \sbasedon10 \ssemihidden \spersonal EstiloCorreo24;}{\*\cs25 \additive \b0\i0\strike0\f36\ulnone\cf0\animtext0\striked0 \sbasedon10 \ssemihidden \spersonal EstiloCorreo25;}{\*\cs26 \additive \f37\cf19 \sbasedon10 \ssemihidden \spersonal EstiloCorreo26;}{\*\cs27 \additive \b0\i0\strike0\f36\fs22\ulnone\cf0 \sbasedon10 \ssemihidden \spersonal \sreply \styrsid11731365 EstiloCorreo27;}}{\*\latentstyles\lsdstimax156\lsdlockeddef0}{\*\revtbl {Unknown;}}{\*\pgptbl {\pgp\ipgp5\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp13\itap0\li0\ri0\sb0\sa0\brdrt\brdrs\brdrw20\brsp60\brdrcf22 }{\pgp\ipgp8\itap0\li0\ri0\sb0\sa0\brdrt\brdrs\brdrw20\brsp60\brdrcf22 }{\pgp\ipgp5\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp5\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp5\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp5\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp5\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp5\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp4\itap0\li0\ri0\sb0\sa0\brdrt\brdrs\brdrw20\brsp60\brdrcf22 }{\pgp\ipgp5\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp5\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid1847230\rsid2557630\rsid6257269\rsid11731365\rsid13053405}\paperw11906\paperh16838\margl1701\margr1701\margt1417\margb1417 \deftab708\widowctrl\ftnbj\aenddoc\hyphhotz425\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1701\dgvorigin1984\dghshow1\dgvshow1\jexpand\doctype2\viewkind5\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\allowfieldendsel\nojkernpunct\rsidroot11731365\newtblstyruls \fet0\sectd \linex0\headery708\footery708\colsx708\endnhere\pgbrdropt32\sectlinegrid360\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\ipgp5\pararsid11731365 \fs24\lang3082\langfe3082\cgrid\langnp3082\langfenp3082 {\f36\fs22\cf0\insrsid11731365 Buen da, -\par -\par Gracias por enviar la proforma}{\f36\fs22\cf0\insrsid11731365 NRO 2013 000436.-}{\f36\fs22\cf0\insrsid11731365 -\par }{\f36\fs22\cf0\insrsid11731365 -\par }{\b\f36\fs22\ul\cf0\insrsid11731365\charrsid11731365 Comentarios -\par }{\b\f36\fs28\cf0\insrsid11731365\charrsid11731365 1)}{\f36\fs22\cf17\insrsid11731365\charrsid11731365 }{\b\f36\fs22\ul\cf17\insrsid11731365\charrsid11731365 Forma de pago}{\f36\fs22\cf0\insrsid11731365\charrsid11731365 :}{\f36\fs22\cf0\insrsid11731365\charrsid11731365 En primer lugar por supuesto agradecemos el plazo para pago que se nos otorga pero}{\b\f36\fs22\cf18\insrsid11731365 }{\b\f36\fs22\cf18\insrsid11731365 }{\b\f36\fs22\cf0\insrsid11731365 pagaremos contra copia de Bill of Lading . En ese sentido agradecer modifiquen la forma de PAGO en la factura.}{\b\f36\fs22\cf0\insrsid11731365 -\par }{\b\f36\fs22\cf0\insrsid11731365 -\par }{\b\f36\fs28\cf0\insrsid11731365\charrsid11731365 2)}{\b\f36\fs22\cf18\insrsid11731365 }{\f36\fs22\cf0\insrsid11731365\charrsid11731365 Necesitamos una}{\b\f36\fs22\cf18\insrsid11731365 }{\b\f36\fs22\ul\cf17\insrsid11731365\charrsid11731365 proforma solamente por los }{\b\f36\fs22\ul\cf17\insrsid11731365\charrsid11731365 tems}{\b\f36\fs22\ul\cf17\insrsid11731365\charrsid11731365 en stock}{\b\f36\fs22\cf18\insrsid11731365 .}{\f36\fs22\cf0\insrsid11731365 Las autorizaciones de pre embarque dan tiempo para embarque hasta 5 meses mximo una vez emitidas. Dado que hay }{\f36\fs22\cf0\insrsid11731365 tems}{\f36\fs22\cf0\insrsid11731365 }{\f36\fs22\cf0\insrsid11731365 que figuran con entrega SEPT 2013.- DIC 2013.- no puedo pedir autor}{\f36\fs22\cf0\insrsid11731365 i}{\f36\fs22\cf0\insrsid11731365 zacin por ellos. -\par }{\f36\fs22\cf0\insrsid11731365 -\par }{\b\f36\fs28\cf0\insrsid11731365\charrsid11731365 3)}{\f36\fs22\cf0\insrsid11731365 Han includo en la proforma las pos}{\f36\fs22\cf0\insrsid11731365 i}{\f36\fs22\cf0\insrsid11731365 ciones arancelarias de los cigeales. En caso de no poder exclurlas, pido por favor enuncien el nro 8483.10}{\f36\fs22\cf0\insrsid11731365 -\par -\par }{\b\f36\cf0\insrsid11731365\charrsid11731365 4)}{\f36\fs22\cf0\insrsid11731365 }{\f36\cf0\insrsid11731365\charrsid11731365 1\~\~\~\~\~\~\~\~\~ \~\~\~\~\~\~\~\~\~\~\~ 509 000\~ }{\b\f36\cf6\insrsid11731365\charrsid11731365 QSC 8.3700 euros/unit.julio 2013}{\f36\cf0\insrsid11731365\charrsid11731365 -\par }{\b\f36\fs22\cf0\insrsid11731365\charrsid11731365 Figura en la factura como 509002 . }{\b\f36\fs22\ul\cf0\insrsid11731365\charrsid11731365 Es el mismo?}{\b\f36\fs22\cf0\insrsid11731365\charrsid11731365 -\par }{\f36\cf0\insrsid11731365 }{\f36\cf0\insrsid11731365\charrsid11731365 2\~\~\~\~\~\~\~\~\~ \~\~\~\~\~\~\~\~\~\~\~ 508 003\~ QSB 5.9500 euros/unit..septiembre 2013 -\par }{\b\f36\fs22\cf0\insrsid11731365\charrsid11731365 Figura en la factura como 508}{\b\f36\fs22\cf0\insrsid11731365\charrsid11731365 005. }{\b\f36\fs22\ul\cf0\insrsid11731365\charrsid11731365 Es el mismo?}{\b\f36\fs22\cf0\insrsid11731365\charrsid11731365 -\par }{\b\f36\fs22\cf0\insrsid11731365\charrsid11731365 -\par }{\f36\fs22\cf0\insrsid11731365 Una vez que reciba la proforma por los }{\f36\fs22\cf0\insrsid11731365 tems}{\f36\fs22\cf0\insrsid11731365 en stock, listos para despacho}{\f36\fs22\cf0\insrsid11731365 - solicitar la autorizacin de embarque. -\par Gracias otra vez por su asistencia. -\par -\par }{\f36\fs22\cf0\insrsid11731365\charrsid11731365 Saludos cordiales,}{\f36\fs22\cf0\insrsid11731365 -\par -\par }{\f36\fs22\cf0\insrsid11731365\charrsid11731365 -\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\ipgp5 {\f36\fs22\cf0\insrsid11731365\charrsid11731365 -\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\ipgp6\pararsid11731365 {\cf0\insrsid11731365 {\pict{\*\picprop\shplid1034{\sp{\sn shapeType}{\sv 1}}{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fillColor}{\sv 10070188}}{\sp{\sn fFilled}{\sv 1}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn alignHR}{\sv 1}}{\sp{\sn dxHeightHR}{\sv 30}}{\sp{\sn fStandardHR}{\sv 1}}{\sp{\sn fHorizRule}{\sv 1}}{\sp{\sn fLayoutInCell}{\sv 1}}}\picscalex1378\picscaley6\piccropl0\piccropr0\piccropt0\piccropb0\picw1764\pich882\picwgoal1000\pichgoal500\wmetafile8\bliptag988111005\blipupi39{\*\blipuid 3ae5609d4efb7ed6fe9eb53a53c2108c}\bin374    X."System u9P$ -@Times New Roman-  2 -ZX ---$WoWo--'-}}{\cf0\insrsid11731365 -\par }\sectd \linex0\headery708\footery708\colsx708\endnhere\pgbrdropt32\sectlinegrid360\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\ipgp6\pararsid11731365 \fs24\lang3082\langfe3082\cgrid\langnp3082\langfenp3082 {\b\f35\fs20\cf0\insrsid11731365\charrsid11731365 De:}{\f35\fs20\cf0\insrsid11731365\charrsid11731365 Santiago Guzman [mailto:santi@csanz.com] \line }{\b\f35\fs20\cf0\insrsid11731365\charrsid11731365 Enviado el:}{\f35\fs20\cf0\insrsid11731365\charrsid11731365 Mircoles, 22 de Mayo de 2013 07:07\line }{\b\f35\fs20\cf0\insrsid11731365\charrsid11731365 Para:}{\f35\fs20\cf0\insrsid11731365\charrsid11731365 'Mara Monti'\line }{\b\f35\fs20\cf0\insrsid11731365\charrsid11731365 CC:}{\f35\fs20\cf0\insrsid11731365\charrsid11731365 export@csanz.com\line }{\b\f35\fs20\cf0\insrsid11731365\charrsid11731365 Asunto:}{\f35\fs20\cf0\insrsid11731365\charrsid11731365 RE: CONFIRMACIN DE COMPRA- ENVO MARTIMO}{\cf0\insrsid11731365 -\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\ipgp5 {\insrsid11731365 -\par }{\f37\fs22\cf19\insrsid11731365\charrsid11731365 Buenos das Maria\~ , }{\f37\fs22\cf19\insrsid13053405\charrsid11731365 -\par }{\f37\fs22\cf19\insrsid11731365\charrsid11731365 -\par Te envi la proforma\~ por lo items abajo mencionados\~ , por favor infrmanos de cuando tenis la autorizacin para realiza el despacho y si preparamos lo modelos que estn en stock para su envi. -\par -\par -\par A la espera de tus comentarios -\par Un cordial saludo -\par Santi -\par -\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\ipgp7 {\caps\f91\fs20\cf19\insrsid11731365\charrsid11731365 -\par }{\caps\f91\fs20\cf19\insrsid11731365\charrsid11731365 {\*\shppict{\pict{\*\picprop\shplid1030{\sp{\sn shapeType}{\sv 75}}{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn pibFlags}{\sv 66}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn wzName}{\sv Imagen_x0020_1}}{\sp{\sn wzDescription}{\sv LOGOTIPO1}}{\sp{\sn fLayoutInCell}{\sv 1}}}\picscalex100\picscaley100\piccropl0\piccropr0\piccropt0\piccropb0\picw6376\pich3201\picwgoal3615\pichgoal1815\jpegblip\bliptag1176076447{\*\blipuid 4619809fe1974716db3325361af31989}\bin3829 JFIF``C - - - -  #%$""!&+7/&)4)!"0A149;>>>%.DIC;C -  ;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;y" - }!1AQa"q2#BR$3br -%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz - w!1AQaq"2B #3Rbr -$4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?j( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -)+/S./5S! ظBu,ߑEp7lXK1Ark :m -){rfDbW ֖3Cu?xWho:4? -o;HQ'/XJo7|?nq&k_wR|A/LbEq곷ƭj?~+$K{Bj#C@#?(al?‘$q-(Ie,(?.zU>4K:{y֯4S.G׃]Z}i1HTi`|+Tn5zUoL2 Ǔ@Z K{W1JYW!Cj_zi4KMdz.WSgY lx5jǓ[ ^"b(sQ@Q@Q@:w2!{)6֕M]H!y*(f8WIoħ¹'>(P~%!ut8,b5/Ƴ放*\UmS>1rUDˌ}[Zg²q&n?E4"*Q)*kU3zra-N~`D?夣{~T@)V%ԫ:o(faEPEPEPIKE&*ޏ_.-w(*2]r7 k7??#9k ny 3ubGZѪUt["CK1n[-URN;]QL()(ƞ)wC%ćd\pSS)(8l459#}/za ˂v<7m>}ꯆrP 9.w}&AnϨ0忆/eUGyu~-ᶅa$4TA? -+Sn(7Z׬4 As)UcFYϠ˿m0OaJYN;<#?ұ57#qA3o8 1]k MYK˰ #)7zPuTZѼ{k7Ij-$ˀk2|4Jo#+#H͍l%\&i_tʖ *rn]ZO`{\on2 -ڼ{ƶm|ْZN\r먿jΨ|T lk<),LC+[YޏXr~1T~#ᦿ j!7{H1}Wt(B - 8+>7vW_7so^ ٮ3YX8:q D*Jٷ{|axIbY!1.\bWMnLWVaǯ"4 ·ݖ[sc/#;M?T: d89sU8Vv986W>m^4xN P/y kc+D칄Hϧo5ki+ޏ/psӜ[rb~_+"˭rtb~%U[A^AXn#]Ouϭn{iV[W=2}άv'IJ^t>>%.DIC;C -  ;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;y" - }!1AQa"q2#BR$3br -%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz - w!1AQaq"2B #3Rbr -$4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?j( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -( -)+/S./5S! ظBu,ߑEp7lXK1Ark :m -){rfDbW ֖3Cu?xWho:4? -o;HQ'/XJo7|?nq&k_wR|A/LbEq곷ƭj?~+$K{Bj#C@#?(al?‘$q-(Ie,(?.zU>4K:{y֯4S.G׃]Z}i1HTi`|+Tn5zUoL2 Ǔ@Z K{W1JYW!Cj_zi4KMdz.WSgY lx5jǓ[ ^"b(sQ@Q@Q@:w2!{)6֕M]H!y*(f8WIoħ¹'>(P~%!ut8,b5/Ƴ放*\UmS>1rUDˌ}[Zg²q&n?E4"*Q)*kU3zra-N~`D?夣{~T@)V%ԫ:o(faEPEPEPIKE&*ޏ_.-w(*2]r7 k7??#9k ny 3ubGZѪUt["CK1n[-URN;]QL()(ƞ)wC%ćd\pSS)(8l459#}/za ˂v<7m>}ꯆrP 9.w}&AnϨ0忆/eUGyu~-ᶅa$4TA? -+Sn(7Z׬4 As)UcFYϠ˿m0OaJYN;<#?ұ57#qA3o8 1]k MYK˰ #)7zPuTZѼ{k7Ij-$ˀk2|4Jo#+#H͍l%\&i_tʖ *rn]ZO`{\on2 -ڼ{ƶm|ْZN\r먿jΨ|T lk<),LC+[YޏXr~1T~#ᦿ j!7{H1}Wt(B - 8+>7vW_7so^ ٮ3YX8:q D*Jٷ{|axIbY!1.\bWMnLWVaǯ"4 ·ݖ[sc/#;M?T: d89sU8Vv986W>m^4xN P/y kc+D칄Hϧo5ki+ޏ/psӜ[rb~_+"˭rtb~%U[A^AXn#]Ouϭn{iV[W=2}άv'IJ^t>>%.DIC;C -  ;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;NM" - }!1AQa"q2#BR$3br -%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz - w!1AQaq"2B #3Rbr -$4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?j( -( -( -( -( -)*)tw -?Zz"j+~ȓU2_V\|?|ً"+ & 7KbgsTHAjiTr|l+[⾤~j>Ƙ~*Ɨʾzi⮮:Yh7Wm@}2$aV#|O"%/="u[+F []k -l2?4$PST{s8;M5:JZdQ@Q@RPI;.VTiu{ 4m!xI:pC)7C~ʧ\tV^: y:ٷMmeܷEPSWX J\Rͩ۲,pʆp3G$k Z-QH##-IAEPEPE^O7gl -nȱMwHԳUN>־(hk4<_zƹŞ3syDOs¿Z#zM% dn7?ZunJ|q3?[Ҿ¡_UiGyNƋM>al4~ex:_ɞk76I'm{<)OY-udty/<< uǸ iR]^=IQr/f/#VN=⹭)DZxG?FX`bhʻso II?UῆGk${G%W۸[Vl 6%kqt7!&$wn&K@?FX~c54T1v L~8:0Ўj{kۻ6ku4VJԭݔ?s [7= O:-lz4<ժ%EenG΁Q]6VZ{6k7Q]AGEqW)ho즃_=)^w7T2okh?#ڴhڸ's,o֦s_:E{;;f9'Zөͣ<,+*pv3r(O +OVVP FeO}3B񎡭r+aF&ڿr'{hA&7S@׮rx8 8]t $ O ~䚴)wl/tƂ8XIg+"E߇οMRoO!$SMt[eDN:}gK7=#P[)gc-$?җه<;hT4G)/YN6_d:d^6H.Y2Ͱ+JQ ˥#Ϙ#j~$%^.չvN̬{K.#MhZ6lG[|3 hڮjTl/ntoCmy g$gxd#׌VjIIF"7WW#]U23P >@ߒ?J^ }G H!q(2&Ejɶfc2T%0@01OZ9u[>[i=Hn-†h$9Tz=:fHsǘǖnc9ϽQnb{M[g٠G_zN*wJ.# ->xԺS_Z_U}^ h+][Dѝ 4 JƞkQpяfTmcqJz]\[w~-ǔ棩C` 95vJSԕ$,8lҟ\ssr!Β-Nvo.y n`HH+Ѕ+ϭOof?n處IMIcG T=Z,3rF: t-ԑj#? p3k{qϿJ~ٻ۫J1DG?:ppvf -((qq <ϙgctjm{Ü8WyEuSĸC/9AJ\͜ ÌX\IGhxAjvh{ȮތU_J-5ccyl,m!tgҷ.<PRIx;9e=Mu,u$W4>f00**c{X5k d[XSAbH8Pև23[ ~sd#>y+ '2 zjG`ĪZbo4F(_ol[]&T>Z;CczTh. Ȧ.U~p9XoݡFv,]B}8iw)=,9KI[OVv2s5ӄZDWk_(6^ZYy6qe*6`Ƭ+{k{x'tLd(+מӯK;~ȆH0X\s]R/M>Wd g;5/`jM4^yv!74ov?w1W쵹%O6,Sۘs0SЌu9ZgDs$ip$e'o[kGy460 F]6t~Y@I*`}(AHH$n-mU(Y -xQ5fnhD=:MDj{#/[M8pdS:I'#ǟ|]OlZ<Ñnȟ_һD"U -KL$yOr#J-}sQ?ba6a4Q§=ε5uN_s:+hw[0]ʒ*{TV"ת-V^=+BhQ4(K҆:傻5(z^+Pc` =9" U(ԤR-z E%sxqJ UP[:5jŻvW:J+N񎅪-yQ8ȭOaTRYz ]Ff[8{Ӵ}NRWӧ3,$; -h*{NW}MA4|Ub<ڙ ??—4{,%gML4 -Hz \,/ @ߧ -0D_)I(q<&*T>hg#c18>}קt4Km>Im.rkFRwDVMSKQEG8>E/_jU-;BIxu?xwf -|PN{ⷠ9?g8^ټܷ64|~3],𤩐2 3G:=w źJ -\g8ȧϮxƚ}ŕwmn\r9Np-faAiu4QVn!'y>u5i}:C? !I?δXjo?˷{ +\:Kt8OdB]:KK4[X`Gz/&hzlEupT 9㨬"ȯh)Z#[0{nLێkΏ,5R~x(?Lb_HסZH͐lG~Y_I>;nl_?A9T >VkUn<=)iV%< 2aۊگKbshjDYjwcr6rj~2@ik>Ƿ - Tݵ_ų-Mc+WzaڄtD/-\C̤HgS7RP}'qy{C'^HSlЮ#{bh@UO̪}Iv#Tm=%ca;Y2f4sFH%p}Ӯ'5k=:h65ly^3;{d{4PV{i-`*}T{I^ϷM/LQQ~ff"%/`檚ťZURGVa@:U%c -Nv=G&(q2L輸񂫌coJFH@I8\`AD$ k#wNJRɢҤUx0i,69jyZ#geiM/KZʱ$?*)cN`VO#YP؇2CrqR[]!p4Mٌps&>Κ×d#i !y -} -e "ջZGYьCaYrnzmMƪq QNWZ*p((Oafo[ ->sWkDEJQ|qVo]ӵLF".T^~ .v>~ -^m#⢴<"h%>X\olҨO wmLEcx0rj%VSqH:L8#@'뎕{T<;ؾ<5M$A/M6G#&B?,sML~Dܥ`ϙ3;ZHu9O3H<8zCk lC>c9/V=ۍ&mX_  wSY:\"(&,dc>1NM*pdd;~JhdkJ뿟n?E6W)#]RA9=Q\SMh_qWVps}vY -WqJCxj>\!Squ4VquOt/$V F *mSVnivNFiVcjh* ,-$GK185^ /ðJRGN }CQ5o:ȳ3C¨Wxo>?y;:g-`uw?zF5S[WьH ͅQZXQEW2H|/DӪ>;N?J+6~5{v)d`qS=bμ L%%h KM2fe7\sp"WN4'ɸ)ĩm"?εe Ehw%C,od)RGvCMMմmYmfV99ҼS5 [$ v .t۹e3U sc=N{]}4{w6;'a\7 f+Qex#]۟}Zuewga]28ݽhov\E#z5hq zѿk񟉴?YDmKgTAףG"=fP=\v mR?_=gЍ}`9]gЍ]n|u>_57Su zO[ oxaǦ]#F֩X/,䄻Zn'Ϸ2sV\kH2giu&~9vk5j+X1FlEi$gz&bR?,[/C7P ^<֏`c3Һ_x[Q-uRE@0deַ<- {*/T*znߪ(U0 -!K+0b|EWAEP:\H=%$E{xGVop_9 -9Uk}-ȓǹ? t??k -S,4{^tX)~02k Ī_]$/傴߆3^3!\ݽہO]'6Sw7CuF ˕YOor~R(J_u}/-?Q-uO?è͔]]Ȭp$\< -ma_A>k#[?Ý>٥A{2ѱC8Jݔ]h#|)yqoa.R?mү,ﴫ{ XFzcx&j:hIi_lbm^$3a$. I;Г]͋b_N=1NfTRT N-IG/ak&Y`ɥ <cP m?fyr/=FvmsF<Ѫ66`ϡ+fH%ث-k-{(XqrA v,$grÁҝ>Up -(,(_i$@$|æk.2\1j6[B H#ڴ9I]yn]Ep@Oa8c{dMi s" TV[U -Μ*JIš{iqjq*Oy20o̸Vo%)o~ MG`ޛ%>K2ΚH6H 9 -]ƣoқ/"(۷*OͰ7\lj5[ 'S6:B2[`YS=hM]HiӮlVIcU@ɗ̫T܂}(Io5{ m;vI\tM¥`GeF+3=X|ʡA])]wTO6X;{hq( Cd} -o{2;0+97gj|Vk0ASjɬT1<1@AT:uEc@1ӫGz֑h~ZP;/UC?Oδ-<;$ -\>y?ޟAڵ5.:1Qԕ<' - *P((cǺηO2x$*waOIIP*#R;-wVk~="Z½TJ[3ܞuJA7yZC}$Qaϯi:A$+8ʝ$߀+vbSTَ#7})omNjip\I;p+WhלPy -tI-|\v8oUZG~kx4!$u{u&)ʔZМ>s>ieٜ5agx%Ş.nO1xWbQ*wI\0٪֩R. 01UBS2rzUJ*Jba*>{%пe9l*o "Hֻ1Q\=gKGI[/Z!L͔SޘGT^F)7oJQkG!hB(>e,tp<{D:sEW6fZ!=ri#ӬaYᵶD#ҬN,UM}Y[TӁKe &+8#,6(:t4Qv+"u,wn}qzZ[E 8#HTTOSQEc:OåY.s`PGZP{$yiFJO".vsRQHcs[U:z\9Q~ onἿY#3M81j{ ֩6YpsyIv qk5ɀE"IĞMkECo~M5ŽW$NSZ4Ru$adQE@}}{\nonshppict{\pict\picscalex100\picscaley100\piccropl0\piccropr0\piccropt0\piccropb0\picw15584\pich2064\picwgoal8835\pichgoal1170\wmetafile8\bliptag-711381721\blipupi96{\*\blipuid d5992d2759c6907e7150c04256e8e528}\bin138044   y   ONy A NMNM(MNεƥkZ9R){cs{k{csZ{csRsRcJcJZBZBRBZJZJkZkRkRkRcsﵭsƔkc֌{{kޜ{ƽΌ{{sޔ{csk{cν{cތskkss罽kssskkkss{k筜{kksksk{k{sss{k{ksssss{sss{{ks{ssބ{Z19Z1ƭB)9!9!11)11911111119!11)1)11RBccB11!))))19!kZkc1!11!199kRs)9)1))1sJ)911)))11119sZZB)1111)))))!119911111111)1119!1J9νk91kBƽsB)1911)111)1)1111991)911)1))RJsk)9!))9)9Z9ƵJ1)BB9919!9!9111)9!911111)111!111{cRB))1)1)111191))))1)1)1)1)9!11)9)R19BsZ{J111)))199999B999B99199911)111ZJ91!!)B!9)sZνRB)9)119)kR)1!))))J919)!))1))!9!11sccR1111999))119)1199999999B9)9B))9!νB19cJ1B)))99)!1)1)111)11911)111!B1!s))99191B!εƵƽννƽƽƽƽƽ{11J!1)9!9!ƥ11)1919!ƵZJ)1111)1!1))1)1){ZR9))1)1!)91)))))11919191919!991B!ֵֽcJ9BB!εR9B1111))!9!J9R9J1R9R9Z9Z1Z9R1Z9Z1R9B!1)1111R1Δ{J91111B1!9!B19)J1B1B)B1B1B1B1B)J1B)B1B)B)B!)!9))19!{c19)1111ƽsk1!)19))))!)1B!9BބcZJ)19BB91911199!1!)99919991199B11R9Ƶ{έ{{ƽZRZRZRZRcZ޵޽sk罥sBBJ!BsRRcZRsssZZέcZJ!!k99{RRsJJcZƽZ1)sBBsscc{RRZB9ƭ֥ccRRsJJsJJƵR91kRJcJBcBBcB9ΥR11kBBsRJZB9J))kc凜{R99)cBƽƵJ)B1)91)B1΄sƵsB1)91199kR9)11119B1!)))!1)1111111)9B!1)1!)B199111)1Ƶ{1!!1)))119!1)!9))1΄Z{J11))9)1!19J1kR֥֜{skJB9{{Z99ތkcsB9֔{sk11B絵J)!΄kccRJZZk))ƌ֥R)!{sƜ{cZJ)!޽Z91kB9ƔƌZZZ)!ƌRJR)!絭kcRΔƔc1)1筥kcR!罵)c!!{19kkZR9kkB!R!!Ɣc11J!{{֭έR91{k9J9cJƵ1B!1111)kcƵR9)99B19scZBB!J!1111)1)))1)11919191B)9))1!))!sk1B19199ƵR911!!)19J1R9J!111B!19ބZcJ9!9B919111kR絥{s{ƽν{sュ{k{{{kޥ{{ν{ƵֽsZ{R9kJ1cB)sRBkZƥεν{{kRJkBBZ91ZJ֔k))Z1)kcsZRRޔsksJJcZcB9ZZJ!{91kcRJcZ{sk))ﭭBBΌ֔ZJk!!֌{BBskƜkB9JJJJ֭k99ccέB)!kRJ)B{cZZ)!B99!9)1!JBZ9)919B9cR999!9!1!911B91B)BB1B1B)B!)1!19){11)1919εƵcB1B)!!)BBsƭ111))91{RkB9911))9)9!΄kkB!k9k1s9Z)֭樓sZ{1!R!s絥{Z)s1k)c1sZBscc!s1k1s9Z)֭εs9c!k9c9Z1!cJZ)k9c)ﵥkRZ)s1R!kJ)sZεc9k1{)1{1BBs1k!RB֜ZRB{k{scJ{cRkZ{cRνkcƵ{kc甄{B9){k{kZscZ{ュ{{{cRRkc{{cR{ތsc{cRƥs{ZJkZkZcB1޽sRBƵ{kcތ{kcRBsckcRZJ9{cZ{kc{cZZJBƵ{skƵcJB{cRkRBﵜkZsRJcZ{{{BJ֌RRƽs91s1!B1s1)c!ﵭk1)֥skcZRƽB)!cRk9)Υs)!ZRB9ZR{99Jk)!B9Z֌c!Z)Ɣ{ss1)ZZ{sΔ{B9Ƶk))kk{JJZ)!BƵR1BB1{ƽƽƽƽƵkB19B1B1sk{Z911)1)))9)!1111!19B!J!99191)1!{k)9)9119νsZB1111919cֽ911)119sRJ))9B!!)1!9!cRބJ)9B9{1絔眄Z)1s)Z絥s{999{9kJsc19BBs1筜εB1Bk9s9)ތZ1{B91樓kR{199s9kΥcB{19B!)1{1BJ!9{!ZJオkZJ{c{cJֽ޵ZB֥sB1εskZB9ε{kƵZBB޽sZBƭε{ZBֽkB1νεsJ1ƭ{R9cR9֥s{k΄sZ{cﵔscƭscRskZƽcZcB1ε{ZBֵkZ{s11kc{kc{{kc99JJƽ絥ﵥﵥcRs1!c)!ޥ{skkRRJƽcB9kRJkcc)ν{B9BBJJBƽB9cZֽ{ƌ֔{sBB眔ޔc!ƽZ!Ɣ֥c!!ƽJJkc眜RkRJRB1{91cccΜccR)!﵄{c91J)91B)΄ck{c{ZsRkRcJkJZBZ9J1J)1!!91199εB!11))))!J)sZZJ{kcJZJkRcJcRcJ!119!J!1!RB{11)1119ε11111111Z9ֽ19!1)11{ZƽsZ1)99911))R1έJ)B9B{1|֌kB1B!s)kBƭ{{999BcBsc1BBJs1絜ֽB9Bs9k9!ƄR){BB1֔{kR999k)sﭜs){1Z)B9k9Z1c)BJ)9k){scR祌{{kkZsZ޵ƵcR֭֔kZƵscZƽsc{kޭsccJcR{έƭsZ޵ֽ{ZBsZJ֌kc޽{sֽRB1{kZƵkJ9s{kZ9)ƽckZ!!ss{kksZRZZ{1)JJ甄sZ1!Υνkcc)!ƽk11֥sscZk)!91ZZ!sJJ{kZ!sJJR!sB9{{֜s1)sB1ƜJ!֥kcJ{JRR{ZZR)!Υ{B9ZRsZ!!{s֔c)!ΔkkJJƄRRsZRR)!k)R)11!kZRBB11!1)11111))!!!))))))1111B!9k19)))9!ZBƭJ)911999){)9)1199ƽB)11919)1B!ƽB)1!9119sR9!11)111119scބR)BBB9|sJ)9!9!9R1ƭ{999{9kBsZ99JB{9ޭεB9Jk1sB)έsBJ{9BsZkJB9Js1{Ƅss!9Bs1R1֥Js1J!{1{9!kZkRBƵ֥s{sskB1޵sB9ε{kcΌsc{{ε{cRsRB΄cRƵsc{kZB)ֵ֔sc{cRƔscƵƥ{ZJֵ֭έscscR֌kZޥsƥ΄cR޵|{kƄJRƄJBޥ{kB9c9)ZRΥオR)!sskcƽZ!樂ƽオέ޽{RJsB9RJB罽ƌΜsR!Z1!kc絜cB9cB9sJB{ΜsJBsJJkJBsRJssޭsJJZRBcZRR!!{s筭{JBk11ƽޔ{ssR91{skJBkR)9B9!ƭB)11)9991911))!)!)!)!!!)!!919Z1ֽƵJ11))91)9!Μsc1)1191)ZB{11)1919εJ1!1))91)B)֔{1!1!1)11sRcR))))!9911sR罭{J!B9B{1kB191J)έ{{191{9cBsZ1BBBs1絜ε9BBk1s9)ޭk9{BB9cBޥkR999BscR9)B9sBsJ΄c)k9B{9s1ZBR1){k{ZR{ZJkZcB1kZ罜ƵZJ֥΄ZJƵ{kk{cR{ƵsZZkRJcJB{{cRενބkZƵνR1)νƵkRB祄s{{cRskJ9kccZcZkRBkcֽΌkZscB1sRBkJ9ƭs{sJJ{{{JBΥsRJ֌sskZZ{BBcZkJBkkR119c1)ƭJ))֭{1罵kJ9kJB{RR{sZ))ΔBƽJ91kcsJBkJJZ91{{R91J1R9ƜZJ1)19B91)1))!!))1!)))1))!J)Μ{{kB!)911B!!B99)11)1119)9)9119νcZ11!1911΄k119!!111sRsB)))111JB)R)ΥR)BBB9Υk9919{B!֭Υ{999{9kJsc9BJB{9޵εBBBs9J1֜{s9JBBR1֭sR999{9kRJ{1!1{9k9kJdc)sBJJ!s1R9sRJƵޭ・kZsc{skcƽZRνskνscRƽ{sscc޽R91sk֔{s{cR{s{kZcRJZJBsc{sscRskƽcZ{s{s{cZ{kskskƥޭsZRƽkJB{kƔscֽﭔ{{kJJ{RRεJ11祌{{k1)k99BcJJֽsRJZ1)ss1B)!ZB9J1)kcskkZRkk{{֭J!!JBBB91cBBZ1)R91Z91Z91R1){{J)!c11sBBB!!)J1)R!)RBΔ{199911)11111))!)!)))!!!!91ZRƌ{νkJ1111B!)){{kZ))))1)9!kZ{11)1119εsc11)!191sRƽ)91))11{ZRBB)1!1)1B11sZJ!B9B{9֥{s9991B޵֭{{9999cB{c{1BBJk1絜ֽ9BB{9{B)ƽZs9BJ9B)޽sR1B9{9kJBc!k)k)R!sRޭZ!J{9Bs1kJkJJskƵ޽Z91޽kcZ{kcュcRJ樂{skB91RBBƽޔ{sƭZBBνֽ֥Μ{ֽ{{{sﵥkZRRB9ބkcε{cZν{cRƽνscRֵƥνƭƽεƭֽƭεƥֵ޽Ƶ{B9BB1ƥ{k!9)19!111911191919!9!J!J!R9RBRBRJccksΌ999B)B!1!B99!19)1199{)9)1199ν))B!!)!1)R1νB)1))111sZƽcR11119119J!J1ƵބR)9B9{9Δk{9B!919ޭ֭{9999cJsc99BBs1ޭεBBBs9B)εsJs9BJ99έsJ1B9s9{﵌{scksR{cΥεcc1BBB{1sRcJJ{skRJ絭skkcRR{kc{cRBννskckZZscZssޔ{{cJBsksskZRƽƽRB9ƵƽZBB{sscZsksscZskscR{191)B)Δ{RB191111)Z9֌sƵcJ1J!B9)1cRZJ911))11{c{11)1119֭J))11!B!!199)1)1)sZB9!)199119B!ƌ{֌R)999{1{Rs1B99B!{Rޭ{{9B99cBsc{1B9Bk1絜εJ!19J!s1ֵJ!BBB91祌{Z1BJZ1kֽsJk9s9J9B{1֥ƽƽ޽オ{sssƵƭƵƽƵƽ{c1B)J)֜{RB9))))1cJ絥ƽ便ﵵ樂ﭭJ!9B1)1B9ֵB!119)9)J1ֽ{19)1111ƭƭsJ)1)1)9!1{sƽ911)111sZZZ)!)B99999sZν֌Z1{9B99בֿsBs1B19BsJ֥sBBB9cJsc99BBs1޵εJ!1BB9!ƭJ!BJ9B!1ޜ{R9BBkB{祌B)k)BJ{1B9{9!ޭZB9)919΄ccJ11)1))ZJνkJB191))J)ƵsR)J1!99)cJνR1119)19)Ƅs{11))119ޔssR1191))9!cZν19)1)11sZB1))))1111R1֜քR)9999祄Z){99919c9Δk{9B99cBsc{1BBBk1޵ε999{99!9BB19!1Ƅc{R1B{9kBsέ{R{1B){1{9J!J!s){1֜ZB)9J)B!sccR11)19)J1ΜZ19B999JR)ƭB!9B9)1)B)ZJ)1B1)99B){)9)1191R19)9B!111)RBֽν9911111sZJ119B19B9)B!{s֌R19B9B!ΌkJ!{99B99Z1R{BBB9cJsc{99BBk1޵ε9BB{9J)ޔs9BJ9B!1kRsJ9BJZ1sεkBR)s!B!9s1J!c){9֔cJ1)B9)cRƵkc!1!111)R1{ZkksksssssZZsJR))191999R1s!BB)!91!1191!91{11)111999111919B)ƭν99)1)1)sZcBR1ZBR1Z9J)R1J1J1J1R9R9R9J1R9B1RJR91!))!))1B91{{ބJ!B9BBsR{BB9c919J!sJ{9B99ZBsc{1BBBk1޵ε9JB{9J){Z1BJR)91R9kJ9BBc1sν{R9R){J!J)B!B!{Bc1Z9ﵜZJ!19)1RBΜ{))1!11)!))99999991B91)19B)9)1cJR1191))1!J)!)91)cR{)9)1191119)9919ƜνB911111sZ9111)!))!))99911)1191111))9B!)kkބR)BBBB!Z1J{BJތZB9J!c1{BBB9cJsc{9BBBk1޵εBBB{9J)Z9BBc1{Z9!{1J1Z9BBB{1{Ɣ{k1k)J!9{1s9kBccZ)!91!9!ΜB1)!!1!1911)1)1)))))!!)!)!!1)B)Δ{9)9)!!1!!91J1s)1))111!)1)991{c99)1)1)sc1!)1!1!)!)))1999B1!))!!1)9))19!skބJ!B9B{9B!{B{BR!J!9BJs9B99ZB{c{1BBBc1޵ν99B99B!BBk9בֿ{1{1!{B!J)9B99kޥcR9!{)19{9Z9޽cZ)))999{ksc19))1)))9)))))))))1)1!1)!11!1sZJ1191!!!))119kZ{)919191911)B9ZBνB!911111sZ1!9!1!1!!!1!)199111B1119)!)199)sZބR)BB9Bs1{Bk9Z)֥Z)9B{9{B{BB9cJscs99B{Bk1޵εB!1B{991J9{Rέ{9)s1!{B){9!99B9ƌk֔J119B{9Z1Υƥcƥ{sc)B1191RJƥ{s1!)!)191111)1)1)))1191119!B1{9!919)19)J)ƭ{B!9111))191cBƭB!19919){Z1)1!9)!)))1111111)1)1)1)9)1))kR֌J)91J!9B{JZ1sBƜZ1J9B9J!k1c1ZBsZJ!c)k9Z)Z)ޭνs1{1k)s1s)s1s)k){ck9)Z!c)!s9)k){9!B!s1{ZΜJ)919{B!sRƥZ!k)s1k1c)֭ﭭƽ筭kkﵥƵƽƽ)B9)91!B9Ƅ{kcJB1B)9!9!91111999!9R)J!J)B!R1cJ΄kޔ{ννscRBZBB!J)R)B!B!ZBZBsR9J)Z1R1J)R9J)J!9J)R1ZJƜcJR1R1BR)R)R1ƌsB1R9R9J1R9J1J)J)J)J)B)J)J)J)B)J)J)J)B)J)J)J)B)J)J1J1J1RBJ9{kޜZBB!999BsBZ1k֭sJk)k)Bk){B!{J1sJ1kέΥέޭ֭ޭ֥֥ΜƔ{sޜsccRcRsJ1k9)c9!c9!sB)Μ{罌R)s)9B!sB){cέB!9B{1s9・ޜ֭s{scZ{scZ{kZsc{ƽscsZsc{{ƜΌ{νބ{֔眔kkΜ{{Μs{{ΥcZ猄ֵkk{Ɣ֌Υ֥ƽ{scƌ{kc{{֜{Υ{ƜΥƽ{ք{ƔΔ{9!)J!1)1)kZνƽk1s)9B{1k1JR1s֭{ck޵έֽƭƔ{ZsR1k9c1J!ZBƭ֔{s19{1{9c1εRR1)JJBBZBR9΄ssZJcZskscJkRB9kk{{{{オRBcJΌ{֌{RB1)J9ƽJJ9!絭罵ޥ֭{{kc眔ֵ甌ƔƽޥΌ΄{ƽcZ{{νskオZRƽޔ֌ք{ֵ{kބ{オ{c֜ƵﭥscZƵRB)B!B191ZBέRBs9!B)k)sB!{R1{Ɯֽֽֽƭs{R9R1Z!k)R1J){B)kB)JJ{k1!911)19)s9)ƭcR99{{B1ƭkZB1ZRR9R9ﭜ91cJkc{{{ƥ{Μ猄{kν{ZZskƥ{kƵﵭޭ{scZƔ֭猄{sΥΥsքsֽcZ{sΥֽ֥cZΔބ{Μ絭筥{ޭsޔ{s甌ބεs֥ޜν{skcƽZJ119B9!1kcB1R!{J9sZֽƽ{skRcBZ9R1{B!R9{J)J){B!{B!{B!J)J)Z1Z1sBƥ{έֽΜR9c)9Z1sJBƵ91΄{cckk絭111!ƽBB{sk9)RBֽBBs{RRZRB1BBƄ{cR{{JJRJsk{s{sskkccc{{sskk{ZRޭƽ֥{sscZ{sΜƽ{s֭skΥ{k{skcƽ{kƭ{{ν{֥kckZ{kkc{k֌{ε{k֥skν{{ƵR1ƥ{޵ZRΜsZ9B)191!Z9֭Μ{sZ9BZ))s1{9s1k){1{1{1{19999919{1sBc9c1Bc9cB)罭{k{kZRބs1)ƽ99B9ƽs1)ƽ19ε991!kc筥BBs{RRRR1!)1skcRcZccBBkkskƔkcsksskkޭ{sέΥƽ{s{sε{{s{s甌甌眔JBνք{ΥΔބsֵ{Ƅ{sscΔ眔猔ƌs{cν{kք{cRss{cZƽB!J!1119!1sRƵkkB))Z1)k1{1{1{1{1B9B{199B999Bc)k9c1c1c1kB)J9ZJZRJJcRB9ֽ1)11焌)ZRJBB9{k1!)1B191cZs{ν{sk{{{{{sssέkksk{ν{s{֔{skƥ{s֭sskskcccޭ眔ƵZB1)199)9B!֥޽skRcBR1{B!s9{9s1{9{9{9{9{9{9B!B!R9cBsRsֵ)9){{1!)JJJBZR919)91kZ޽ޥ祥JBkcƽZBcRֵccks1!1){RJss{{ssk{{sk焄ޜƽkkB1!191)B1kRޭƽƽ罵Ƶ罵ƵƵƵZJ{skZRssBJBBkcsJ9JJkZB)cRcZJBJ9{k{skތ{{s猄ss焌{RB)9BB1B)1kZƽνƌs9)1B1119BkRﵥ֭{ZRƽkkZƵ猌kRB!)9BJ9))ZBք{ֽƽZB9޵ΌkcR1)έsR9){樂RJ9{R91))9BB!11J1cZBBR1)RJƌ{εB)B)޽kcR!cRֽֽcJ1R9)νޥƽ{県{ƽ筥ƽ{ƥ֥絵ƭ{s{c{քs{kƵs֌{ƵkZsckcƄ{kRJ)1!111191J1s{R99)1!)!{sB9Z{1!ZJ{c{cΜ{Z9Z1J!Z1!{﵄{BJ!kB!kJsRc{ZZ9c)c9!sRBsk{skZޥscJB{s{{skccތ{kcskZR甔{kR9sޭsc֔{kքsZJZJsZR9))1)1199BB)sZνcJB!19111!{sc{1!){)c!s1k!s1{9!c1ޭssBs9s)1{){){1B!k1{ss焄ksss{{RJ{{֌֔ZZZZ{{֥ޜs{kksk{ֽRB)1B!B11991RBscνεR991191199Ƅs֭s9){)19!B!B!s1{B)֭罔kRs1BJ!919!k1!罭Ƶέ޵Ɣ֭ƜƥƽΔֽέ޽޽έεƵεƔνƽs{s{ZcccJR{ΜJBJBkk{{kkέ{{ޜ֌k{ccckcscJ)1)!1)))11!cRΜνkJB))))1)119)Ƅs޽k1)k!s)!k){kνν֜ƌ{{csZcJZBZBZBRBZJcJkRsZ{c{ƥֽ֥kBk9k)s1k)c1!ƥέcֵ{޵kRƵΥkskc޵ZkƵkRkR֭ss޵֭k֥{ννƜΜƽޔsֵƥޭ{罵{ƜֽkֵֵƭƵֽ{εkεƭεkƔƔεƭRBsZcJcZRRJRBBZckc΄{{s猌ckέcR{cR{kkccskƵkk{sﭜJ11)1B!91!B!)1J9{ƵƽscJ1119B111)1)119΄s޵{{{{Ƅ{ƽsksJJZ1!c1c)c)Z)k1k1k9k1s9!k9s9k1k1c1k1c)Z1J!J!J!c9){ZJsεƜ{{cƔ罵ﵔ{֭{BƜ{ΜZ{֔Rsޥc޵sR֌ƌJ|s޵ֽcֵ{޵εƔƽνε{޽έ罔Ɯ֥ƭ{޵ƭֵcΥs޽޵޵ΜέΌ{ֽBBskΜsskkkk{RJkcccRRskƽ{֥RcRRs{֭{ZRΔJ9kckc{sֵkcνkkskƵJ9)!1191991B1sk֭Ƶ{{ZJ)B11)11)11)1)119){sΜޥsZRZB9ZB1sZJsc{ƭֽ޽εεֽεֽֽֽεεƭƭֵֵƥ{kkZkRBcJ9ZB9kZR{{ֵέBZkΌ9޽sΌBkRޜRk֜c֜ZޜޔRεΜsƔc޽{έƜkƜΥ罔޵Ɯ޽ƭsƭkƥ{έΥƥsޭ֭޽έ֭֭{֭{έƜklƔֵεƌνcZスs{RRƵ޵ZcssƌkZƭscZRJ)){{cZcJ111B9999111!ZJ{sֵ{sZR1B19199B9911)1)11999΄s޽J)){ֵ޽νkcZB9ss֜J޽΄֔J{JRs{ޜcޥޔZ罥ޥޥ{Ɯ{Μs経lƔk罔ƥƵ{ƥ֭ΥΥk޽ƜέֵƭΥ{޵{c޽֥Ɣƥֽ{Zc{s{{ss{skk祭Zc{{kc{scZ{skckkssscZkJB!)))99111)9!cJsƵsRcBB!1)1191911)119)))119111ΌsR)!{ZRZJ9ZB9޽֜ք9޽kƔJ{֔BޥΌ9kΜƔΌZ経޵k֌Zƌk޽ƔktƜֵ֥֭֭Ɯƭk޽έƭεέ֭cƜֵֽsƜk޽ƭֽֽﭽޭ祵ֵ޵絵kR9)!991!B1))B)sZ{ƽ{cJB)))!11999)))999)))11111119)csBBcB1ֽνR9){ZRƜZR֥c֥sΜƜcޥ֥c罌BƔZs޽ޭks֔k絜絜ֽεέƥƥֵ޽֭ƥ{Υ޵ֵƭ罵sƜεƭƥֽƭƭƥεֵƭֵֵƜsƭνƭνkZ1!)B!)1B11))BcBsƵsZkJJ19!11199911)))111))!)19)111)19JJ!Ɣ{kZR1!sZεk9sֵ֭ν{ƭֽ޽νε޽εֵsֽ{kR9)1111119B))19!ZB{s֭νskJR1991111191!!)))!))1)11911)119111J)Z9Μ{Ƶ・Z9)B)ƜB!cB)εƭƭεƽ޵{ZJR99119999911)119!cJքs筥νZBR9B!9199B9911)1))!)!!!))1)1)11111)1)9)ZBƌ{罭ƵsZJR)k1ZBޜƭƵƽε֜{Z1s9c1sR9ννεεֵֵ֥ƜֵֽֽcJJ)9911)119)))119!B1cR΄{޵ƭskJR9B!1)B99991911)111111))1)1)1)1199B!11)B!ZBބsk9)k)9){!J1c)ֽ筥罥R1k)119c)έ筭ֽƔ{{ZsRk絔祄c・ƌZ{Z{ΥΜsΜs֭֭ޭsRs罄cc{ZZޜ{ƵƵέεƵ֥ƥΥ֭sƥƜ޽ֵƭΥƽs{絜ΥƥεƭƥƥֽƜƽ{޽ƜƵkZJ1J)B!1)!))11911)119!RBscޔƵkcJR19!911199B)1199911111111)111))!)19B9)))J1cR΄s絥ΔcRs))!B11s1k凜{ֽ{Zk)9B19sZƭ{{νֽssޭsRcΜ組ޥssJΌcƭ޽ƌk{JΌZƜ֥{JƄJΜ{筄֔RƌR{ν֥ƔRƔRƥsƜޔc֌csֵk罔{޵Ƶ{筌ƔkƥΌƭƜ{cεƽƜ֥Υ{ƵƜֽ֥εﵔcs﵌s޵|{罜ε{・sƭs޽޽s޵֭罌R{cZBB!1)1)919111BB1)11B1ZRƄ{眔ƵεƥkcBR1J)9!B!991B999991)919111911)1)1)1)!)99B99119Z9sZޔﵥƥcZ{!){)R1{J1޽֌sޜ޽{R)s1B1s!cJֽֽkc{Ƶ{kcR{ƭƭƵֵֽֽ{{ƥƭ{ckεޥsJΜkޥΜZkֵ޵{RZ{ֽޔZքJޥ{֜kޔJZƜc֔Rk֥Z{Z޵ƭ֥֥Μ{ֵޔkν޽Ɯνޭ絔֥νΜޥƌƭƜ{ƭ֥ƥέ絜޵Μ{ƥsΜνcƌֵ{ֽsZJ11)11999))19991)!!1J!Z1kJcνkRkJR1J!B9))991))))1)1)))11111)))))1)111199BBJ99199!J1k֜ƽ޵{s{91s9!Z)Z1s{ssZc9c1k9R1֜ƭュk{kνscεskΜ{kƥνέƭsƵΥssƽֽ|ֵ֔{{{{ֽΔcƔZssZZcƄR֌JZތR֔k{ތ9ޜRΔZ֌JkޥR{RֵΥޥ{ΜƔc{JƔޥ޵Ƶ֭Ɯk֥֭{絔ޭƭƵƌ{Υ{罄ք޽ksƥsƥΔΥ֥ƽcέ֭֭ƔΥks罔Μ֭{εεskRJ11))9B911)99BB99911)11B1J9ZRkkƌޔޭﭵ甌ތ{kZZJZJJ9B)1)!91119BJB))91919999911))!))))111)911)))))11BR1{Z祌νƽcJsZJsZJƽ{kc{Υsc{RB{R9sZνƽscssƵ{kRJƭεsέƥƭεsέsZƥskƵ֭{|ƥƥεƭƽ޽֥ΔsZZR޵{޵֔ZތJcRޜsBJ֜cޔRsZƌZέƜޥs֥ﵜƜc{Bkƥkkތ{Υ{֭޵ޥ﵌ﵔν罥έ{ֵcƥRεֽkƥ֜ﵜޭΜޭcsޭ֥޵޵経cνscJ19)11999)!)119991111)1))))9!B)J1ZBZBkRsZ{cs{k{kscsccRcJZBZB9!B!9911)))))1)1)1)1))))))!)))!!!!!!1)1))!))1)1)))))119)B1RB΄sޥƵ޽cB9ZRƽεƭkRJZB1ƽƭk{νk{֭scZƵƥƭsεƵ{sƽƵsƵ{c{ƵkRƭνƜεޥƌZJ罄Ɣޔc֌BތRތJΌcƭk9R֭νsքRkֵΔZRֵƔ֜cΜ{ޭ޵cޜkޥ眔έ֭s筄筄ﵔֽ罌ƥkέΥk֔Ɯ֥{ΔΥsƵƔ֥֭εƵkcJB!9191911)1)11111)1)111)1)1)1)))1)1)119!99!99!99!9999!99!1911)1)))))1)1111111)1)1)1)1)911)111))!))11111)))911)))))1)19!R9kRތ{޽{JBc9)Z1!Z1!sRBsRkkƜΥέֵ֭޵ֵ޵֭֭έ֭Υƭ{{sc{cZkRJRB1J1)1scZƭν{νƄk{Rc֭sΔck{R֥έZƌR﵌Δc֔ZƔsΔs{RZcsZ{֭֔k{Zs֭քZ{JΜsֽƔc޵޵εssֽֽ{Z֥{Μsƌ֜kƵνΥ{sl{R޽޽{ZƔƵ{sƜﭔccֵֽcֵ֭ﵽkƽsֵΥkνƽsεεs{cR9J)1111))11)1))!))1)1)1)111)))))))1)11111)1)111)1)1)1)1)1)1)1)1)11111)1))11)1)1)1)1)))1)111)1)111)))1!B)ZJscތ絥Ƶ{kcJ9J1J1B1J1Z!k!c!k!k!k)k!k)k)k)k!k)k!k)k!c)R!R!J!J!J!J)J1!R91cJB{ννƥssk{ƭƥ{νƵ{ֽ絔{R֌ZޜkΜ{ֵέ֭sk{罥޽ƥֵ{{ֵֵ{sƵ޽s{ε{s޵޽Ɯsޭεscέֽsscƥƥε{ksƥέ޽޽kֽ޽{ksƥνssZZJJ19)11)11111)1)1111111199991111111)11119191911191119191111191919191111191911)))1)111191B!B)J1J1{csֽνΜΔ{ƌ{{k{ckRcRZJcRcJcRcJkRkRkZkZssƔƜֵ罵ޭ{RZ޽έֵƭ{{kcZRJ9B1191111))1111111111111119111111191919191911111111191919191111))))11199B)J)J9kRsc΄s֜筥޽Ɣsk絜ƥνν{εscsRcBZ9R1R1J)J!BB9911)1)1)11111)1)1)111)111)1111911111999999B)J)Z9ZBkJkR{c{c{ενֽƵƽν罵νƽ{{ss{k{kkZkZkRkZcRcRcJcRZJZJZBZJZJZJZBZJcRcRcRkRkRkZkRsc΄s΄΄Δ֔ޜ眜祥罵ƽ'}}}{\caps\f91\fs20\cf19\insrsid11731365\charrsid11731365 -\par }{\caps\f45\cf19\insrsid11731365\charrsid11731365 vicente irache asin -\par }{\f45\fs20\cf19\insrsid11731365\charrsid11731365 General Manager -\par }{\field\fldedit{\*\fldinst {\f1\fs20\cf19\insrsid11731365\charrsid11731365 HYPERLINK "mailto:santi@csanz.com" }}{\fldrslt {\cs15\f1\fs20\ul\cf19\lang1033\langfe3082\langnp1033\insrsid11731365\charrsid11731365 Direct e-mail\'3b virache@csanz.com}}}{\f1\fs20\cf19\lang1033\langfe3082\langnp1033\insrsid11731365\charrsid11731365 -\par }{\f1\fs20\cf19\insrsid11731365\charrsid11731365 Poligono Malpica -Santa Isabel . C/ F Oeste n44 -45 A. 50016 Zaragoza / Espaa /Spain. -\par tel: +34 976 571 009 , fax: +34 976 571 645 -\par }{\field\fldedit{\*\fldinst {\f1\fs20\cf19\insrsid11731365\charrsid11731365 HYPERLINK "mailto:esport@csanz.com" }}{\fldrslt {\cs15\f1\fs20\ul\cf19\insrsid11731365\charrsid11731365 mailto:export@csanz.com}}}{\f1\fs20\cf19\insrsid11731365\charrsid11731365 \~ ,\~ }{\field\fldedit{\*\fldinst {\f1\fs20\cf19\insrsid11731365\charrsid11731365 HYPERLINK "www.csanz.com" }}{\fldrslt {\cs15\f1\fs20\ul\cf19\insrsid11731365\charrsid11731365 www.csanz.com}}}{\f1\fs20\cf19\insrsid11731365\charrsid11731365 -\par }{\f91\fs20\cf19\insrsid11731365\charrsid11731365 -\par }\pard \ql \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\ipgp1 {\b\f44\fs15\cf19\insrsid11731365\charrsid11731365 DISCLAIMER:}{\f44\fs15\cf19\insrsid11731365\charrsid11731365 \line Este mensaje se dirige exclusivamente a su destinatario y puede contener informacin privilegiada o confidencial. Si no es vd. el destinatario indicado, queda notificado de que la utilizacin, divulgacin y/o copia sin autorizacin esta prohibida en virtud de la legislacin vigente. Si ha recibido este mensaje por error, le rogamos que nos lo comunique inmediatamente por esta misma va y proceda a su destruccin. -\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\ipgp1 {\f44\fs15\cf19\lang1033\langfe3082\langnp1033\insrsid11731365\charrsid11731365 This message is intended exclusively for its addressee and may contain information that is CONFIDENTIAL and protected by professional privilege. If you are not the intended recipient you are hereby notified that any dissemination, copy or disclosure of this communication is strictly prohibited by law. If this message has been received in error, please immediately notify us via e-mail and delete it. -\par -\par }{\i\f37\fs12\cf19\insrsid11731365\charrsid11731365 Este mensaje y los archivos adjuntos estn dirigidos nica y exclusivamente a sus destinatarios y pueden contener informacin confidencial. Cualquier uso, modificacin, difusin y/o reproduccin de cualquier persona distinta del destinatario esta prohibida en virtud a la legislacin vigente. Si usted ha recibido este mensaje por error, le rogamos que lo comunique inmediatamente al remitente y proceda a su destruccin. -\par Segn lo dispuesto en la Ley Orgnica 15/1999 Proteccin de Datos de Carcter Personal y la Ley 34/2002 de Servicios de la Sociedad de la Informacin y de Comercio Electrnico, le informamos sobre la posibilidad de que sus datos formen parte de un fichero de carcter personal, cuyo Responsable es }{\b\i\f37\fs12\cf19\insrsid11731365\charrsid11731365 Cigeales Sanz, S.L. }{\i\f37\fs12\cf19\insrsid11731365\charrsid11731365 ,y cuya finalidad es la de mantener relaciones profesionales y/o comerciales. En virtud de las Leyes antes mencionadas, usted posee los derechos de, acceso, rectificacin, cancelacin y oposicin de sus datos, dirigindose al telfono 976 571009, o al e-mail }{\field\fldedit{\*\fldinst {\i\f37\fs12\cf19\insrsid11731365\charrsid11731365 HYPERLINK "mailto:export@csanz.com" }}{\fldrslt {\cs15\i\f37\fs12\ul\cf2\insrsid11731365\charrsid11731365 export@csanz.com}}}{\i\f37\fs12\cf19\insrsid11731365\charrsid11731365 -\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\ipgp5 {\f37\fs22\cf19\insrsid11731365\charrsid11731365 -\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\ipgp11 {\b\f35\fs20\cf0\insrsid11731365\charrsid11731365 De:}{\f35\fs20\cf0\insrsid11731365\charrsid11731365 Mara Monti [}{\field\fldedit{\*\fldinst {\f35\fs20\cf0\insrsid11731365\charrsid11731365 HYPERLINK "mailto:mariamonti@fdez-insua.com.ar" }}{\fldrslt {\cs15\f35\fs20\ul\cf2\insrsid11731365\charrsid11731365 mailto:mariamonti@fdez-insua.com.ar}}}{\f35\fs20\cf0\insrsid11731365\charrsid11731365 ] \line }{\b\f35\fs20\cf0\insrsid11731365\charrsid11731365 Enviado el:}{\f35\fs20\cf0\insrsid11731365\charrsid11731365 viernes, 10 de mayo de 2013 16:32\line }{\b\f35\fs20\cf0\insrsid11731365\charrsid11731365 Para:}{\f35\fs20\cf0\insrsid11731365\charrsid11731365 CIGENALES SANZ- Vicente Irache Asn\line }{\b\f35\fs20\cf0\insrsid11731365\charrsid11731365 Asunto:}{\f35\fs20\cf0\insrsid11731365\charrsid11731365 RV: Solicitud de cotizacin -\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\ipgp5 {\cf0\insrsid11731365\charrsid11731365 -\par }{\f36\fs22\cf0\insrsid11731365\charrsid11731365 Buenos das, -\par Espero se encuentren bien. -\par Estamos a la espera de su cotizacin. -\par Saludos cordiales, -\par -\par -\par -\par }\pard \qc \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\ipgp12 {\cf0\insrsid11731365\charrsid11731365 {\pict{\*\picprop\shplid1033{\sp{\sn shapeType}{\sv 1}}{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fillColor}{\sv 10070188}}{\sp{\sn fFilled}{\sv 1}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn alignHR}{\sv 1}}{\sp{\sn dxHeightHR}{\sv 30}}{\sp{\sn dxWidthHR}{\sv 13785}}{\sp{\sn fStandardHR}{\sv 1}}{\sp{\sn fHorizRule}{\sv 1}}{\sp{\sn fLayoutInCell}{\sv 1}}}\picscalex1378\picscaley6\piccropl0\piccropr0\piccropt0\piccropb0\picw1764\pich882\picwgoal1000\pichgoal500\wmetafile8\bliptag-144105531\blipupi45{\*\blipuid f7691fc5c97d4172e946f05fa900779c}\bin374    X."System u9P$ -@Times New Roman-  2 -ZbX ---$WbWb--'-}}{\cf0\insrsid11731365\charrsid11731365 -\par }\sectd \linex0\headery708\footery708\colsx708\endnhere\pgbrdropt32\sectlinegrid360\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\ipgp12 \fs24\lang3082\langfe3082\cgrid\langnp3082\langfenp3082 {\b\f35\fs20\cf0\insrsid11731365\charrsid11731365 De:}{\f35\fs20\cf0\insrsid11731365\charrsid11731365 Mara Monti [}{\field\fldedit{\*\fldinst {\f35\fs20\cf0\insrsid11731365\charrsid11731365 HYPERLINK "mailto:mariamonti@fdez-insua.com.ar" }}{\fldrslt {\cs15\f35\fs20\ul\cf2\insrsid11731365\charrsid11731365 mailto:mariamonti@fdez-insua.com.ar}}}{\f35\fs20\cf0\insrsid11731365\charrsid11731365 ] \line }{\b\f35\fs20\cf0\insrsid11731365\charrsid11731365 Enviado el:}{\f35\fs20\cf0\insrsid11731365\charrsid11731365 Mircoles, 08 de Mayo de 2013 16:30\line }{\b\f35\fs20\cf0\insrsid11731365\charrsid11731365 Para:}{\f35\fs20\cf0\insrsid11731365\charrsid11731365 CIGENALES SANZ- Vicente Irache Asn\line }{\b\f35\fs20\cf0\insrsid11731365\charrsid11731365 Asunto:}{\f35\fs20\cf0\insrsid11731365\charrsid11731365 Solicitud de cotizacin}{\cf0\insrsid11731365\charrsid11731365 -\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\ipgp5 {\cf0\insrsid11731365\charrsid11731365 -\par }{\f36\cf0\insrsid11731365\charrsid11731365 Buenas tardes, -\par -\par Mucho agradeceremos su cotizacin y plazo de entrega por los tems que detallo debajo -\par -\par -\par }{\b\f36\ul\cf2\insrsid11731365\charrsid11731365 CANT\~\~\~\~\~\~\~\~\~\~\~\~\~\~ ITEM NR\~\~\~\~\~\~\~\~\~ -\par }{\f36\cf0\insrsid11731365\charrsid11731365 1\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~ 422 000\~ M11 -\par 1\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~ 423 000\~ N14 -\par 1\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~ 500 002\~ ISBE 150 -\par 1\~\~\~\~\~\~\~\~\~ \~\~\~\~\~\~\~\~\~\~\~ 501 002\~ ISBe\~ 180 -\par 2\~\~\~\~\~\~\~\~\~ \~\~\~\~\~\~\~\~\~\~\~ 507 000\~ ISX -\par 2\~\~\~\~\~\~\~\~\~ \~\~\~\~\~\~\~\~\~\~\~ 508 003\~ QSB 5.9 -\par 1\~\~\~\~\~\~\~\~\~ \~\~\~\~\~\~\~\~\~\~\~ 509 000\~ ISL\~ 8.3 -\par 1\~\~\~\~\~\~\~\~\~ \~\~\~\~\~\~\~\~\~\~\~ 262 003\~ 3408\~ 1W5009 -\par 1\~\~\~\~\~\~\~\~\~ \~\~\~\~\~\~\~\~\~\~\~ 307003 1601799\~ C15 -\par 1\~\~\~\~\~\~\~\~\~ \~\~\~\~\~\~\~\~\~\~\~ 309001 \~ 3133996 -\par 1\~\~\~\~\~\~\~\~\~ \~\~\~\~\~\~\~\~\~\~\~ 310001 \~\~3133997 -\par 1\~\~\~\~\~\~\~\~\~ \~\~\~\~\~\~\~\~\~\~\~ 311003\~\~ 1556632 -\par 1\~\~\~\~\~\~\~\~\~ \~\~\~\~\~\~\~\~\~\~\~ 312000\~\~\~ 1894918 -\par 1\~\~\~\~\~\~\~\~\~ \~\~\~\~\~\~\~\~\~\~\~ 313002\~\~\~\~\~\~\~\~\~\~\~\~ 3849907 -\par 1\~\~\~\~\~\~\~\~\~ \~\~\~\~\~\~\~\~\~\~\~ 314002\~\~\~\~\~\~\~\~\~\~\~\~ 3849908 -\par 1\~\~\~\~\~\~\~\~\~ \~\~\~\~\~\~\~\~\~\~\~ 315002\~\~\~\~\~\~\~\~\~\~\~\~ 2827958 -\par 1\~\~\~\~\~\~\~\~\~ \~\~\~\~\~\~\~\~\~\~\~ 316002\~\~\~\~\~\~\~\~\~\~\~\~ 2827956 -\par 1\~\~\~\~\~\~\~\~\~ \~\~\~\~\~\~\~\~\~\~\~ 318001\~\~\~\~\~\~\~\~\~\~\~\~ 1323211 -\par 1\~\~\~\~\~\~\~\~\~ \~\~\~\~\~\~\~\~\~\~\~ 318002\~\~\~\~\~\~\~\~\~\~\~\~ 3264278 -\par -\par Quedamos a la espera de su respuesta. -\par Saludos cordiales, -\par -\par -\par }{\f36\cf9\lang11274\langfe3082\langnp11274\insrsid11731365\charrsid11731365 Mara Monti de Prados }{\cf0\insrsid11731365\charrsid11731365 -\par }{\cf9\insrsid11731365\charrsid11731365 Compras/ Purch Dep\line }{\f36\cf9\lang11274\langfe3082\langnp11274\insrsid11731365\charrsid11731365 FERNANDEZ INSUA SA}{\f36\cf0\insrsid11731365\charrsid11731365 \line }{\f36\cf9\lang11274\langfe3082\langnp11274\insrsid11731365\charrsid11731365 Avda Pavn 1402 (B1870EDQ) Avellaneda}{\f36\cf9\insrsid11731365\charrsid11731365 \line }{\f36\cf9\lang11274\langfe3082\langnp11274\insrsid11731365\charrsid11731365 Pcia de Buenos Aires- Argentina}{\f36\cf9\insrsid11731365\charrsid11731365 \line }{\f36\cf9\lang11274\langfe3082\langnp11274\insrsid11731365\charrsid11731365 Te: 54-11-4208-6224/\~\~ 4209-6676}{\f36\cf9\insrsid11731365\charrsid11731365 \line }{\f36\cf9\lang11274\langfe3082\langnp11274\insrsid11731365\charrsid11731365 Fax:54-11-4209-4927\~ }{\cf0\insrsid11731365\charrsid11731365 -\par }\pard\plain \s17\ql \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\ipgp5 \fs24\lang3082\langfe3082\cgrid\langnp3082\langfenp3082 {\cf0\insrsid11731365\charrsid11731365 {\*\shppict{\pict{\*\picprop\shplid1029{\sp{\sn shapeType}{\sv 75}}{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn pibFlags}{\sv 66}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn wzDescription}{\sv }}{\sp{\sn fLayoutInCell}{\sv 1}}}\picscalex100\picscaley100\piccropl0\piccropr0\piccropt0\piccropb0\picw1958\pich1958\picwgoal1110\pichgoal1110\pngblip\bliptag66810105{\*\blipuid 03fb70f930df6061941de99daa5105a7}\bin186 PNG - - IHDRJJ&P2tEXtSoftwareMicrosoft Office5qPLTEtRNS@f pHYs@@bCc[ cmPPJCmp0712OmIDAT8c``.YIENDB`}}{\nonshppict{\pict\picscalex100\picscaley100\piccropl0\piccropr0\piccropt0\piccropb0\picw1958\pich1958\picwgoal1110\pichgoal1110\wmetafile8\bliptag66810105{\*\blipuid 03fb70f930df6061941de99daa5105a7}\bin66  !  KK'}}}{\cf0\insrsid11731365\charrsid11731365 -\par }{\field\fldedit{\*\fldinst {\f36\cf0\insrsid11731365\charrsid11731365 HYPERLINK "http://www.fernandezinsua.com" }}{\fldrslt {\cs15\f36\ul\cf2\insrsid11731365\charrsid11731365 www.fernandezinsua.com}}}{\cf0\insrsid11731365\charrsid11731365 \~ -\par \~ -\par }\pard\plain \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\ipgp5 \fs24\lang3082\langfe3082\cgrid\langnp3082\langfenp3082 {\cf0\insrsid11731365 -\par }} \ No newline at end of file diff --git a/Attic/OpenChange/COPYING b/Attic/OpenChange/COPYING deleted file mode 100644 index 94a9ed024..000000000 --- a/Attic/OpenChange/COPYING +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program 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 of the License, or - (at your option) any later version. - - This program 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. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/Attic/OpenChange/Codepages.h b/Attic/OpenChange/Codepages.h deleted file mode 100644 index 60d8223d8..000000000 --- a/Attic/OpenChange/Codepages.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Codepages.h - this file is part of SOGo - * - * Copyright (C) 2014 Jesús García Sáez - * - * 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. - */ - -#import -#import -#import - - -@interface Codepages - -+ (NSDictionary *) getCodepagesTable; -+ (NSDictionary *) getReverseCodepagesTable; - -+ (NSNumber *) getCodepageFromName: (NSString *) name; -+ (NSString *) getNameFromCodepage: (NSNumber *) codepage; - -@end diff --git a/Attic/OpenChange/Codepages.m b/Attic/OpenChange/Codepages.m deleted file mode 100644 index 8776ffe22..000000000 --- a/Attic/OpenChange/Codepages.m +++ /dev/null @@ -1,214 +0,0 @@ -/* Codepages.m - this file is part of SOGo - * - * Copyright (C) 2014 Jesús García Sáez - * - * 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. - */ - -#import "Codepages.h" -#import - -@implementation Codepages - -+ (NSDictionary *) getCodepagesTable -{ - static NSDictionary *table = nil; - - if (table == nil) - { - /* http://msdn.microsoft.com/en-us/library/dd317756%28v=vs.85%29.aspx */ - table = [[NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithInt: 37], @"ibm037", - [NSNumber numberWithInt: 437], @"ibm437", - [NSNumber numberWithInt: 500], @"ibm500", - [NSNumber numberWithInt: 708], @"asmo-708", - [NSNumber numberWithInt: 720], @"dos-720", - [NSNumber numberWithInt: 737], @"ibm737", - [NSNumber numberWithInt: 775], @"ibm775", - [NSNumber numberWithInt: 850], @"ibm850", - [NSNumber numberWithInt: 852], @"ibm852", - [NSNumber numberWithInt: 855], @"ibm855", - [NSNumber numberWithInt: 857], @"ibm857", - [NSNumber numberWithInt: 858], @"ibm00858", - [NSNumber numberWithInt: 860], @"ibm860", - [NSNumber numberWithInt: 861], @"ibm861", - [NSNumber numberWithInt: 862], @"dos-862", - [NSNumber numberWithInt: 863], @"ibm863", - [NSNumber numberWithInt: 864], @"ibm864", - [NSNumber numberWithInt: 865], @"ibm865", - [NSNumber numberWithInt: 866], @"cp866", - [NSNumber numberWithInt: 869], @"ibm869", - [NSNumber numberWithInt: 870], @"ibm870", - [NSNumber numberWithInt: 874], @"windows-874", - [NSNumber numberWithInt: 875], @"cp875", - [NSNumber numberWithInt: 932], @"shift_jis", - [NSNumber numberWithInt: 936], @"gb2312", - [NSNumber numberWithInt: 949], @"ks_c_5601-1987", - [NSNumber numberWithInt: 950], @"big5", - [NSNumber numberWithInt: 1026], @"ibm1026", - [NSNumber numberWithInt: 1047], @"ibm01047", - [NSNumber numberWithInt: 1140], @"ibm01140", - [NSNumber numberWithInt: 1141], @"ibm01141", - [NSNumber numberWithInt: 1142], @"ibm01142", - [NSNumber numberWithInt: 1143], @"ibm01143", - [NSNumber numberWithInt: 1144], @"ibm01144", - [NSNumber numberWithInt: 1145], @"ibm01145", - [NSNumber numberWithInt: 1146], @"ibm01146", - [NSNumber numberWithInt: 1147], @"ibm01147", - [NSNumber numberWithInt: 1148], @"ibm01148", - [NSNumber numberWithInt: 1149], @"ibm01149", - [NSNumber numberWithInt: 1200], @"utf-16", - [NSNumber numberWithInt: 1201], @"unicodefffe", - [NSNumber numberWithInt: 1250], @"windows-1250", - [NSNumber numberWithInt: 1251], @"windows-1251", - [NSNumber numberWithInt: 1252], @"windows-1252", - [NSNumber numberWithInt: 1253], @"windows-1253", - [NSNumber numberWithInt: 1254], @"windows-1254", - [NSNumber numberWithInt: 1255], @"windows-1255", - [NSNumber numberWithInt: 1256], @"windows-1256", - [NSNumber numberWithInt: 1257], @"windows-1257", - [NSNumber numberWithInt: 1258], @"windows-1258", - [NSNumber numberWithInt: 1361], @"johab", - [NSNumber numberWithInt: 10000], @"macintosh", - [NSNumber numberWithInt: 10001], @"x-mac-japanese", - [NSNumber numberWithInt: 10002], @"x-mac-chinesetrad", - [NSNumber numberWithInt: 10003], @"x-mac-korean", - [NSNumber numberWithInt: 10004], @"x-mac-arabic", - [NSNumber numberWithInt: 10005], @"x-mac-hebrew", - [NSNumber numberWithInt: 10006], @"x-mac-greek", - [NSNumber numberWithInt: 10007], @"x-mac-cyrillic", - [NSNumber numberWithInt: 10008], @"x-mac-chinesesimp", - [NSNumber numberWithInt: 10010], @"x-mac-romanian", - [NSNumber numberWithInt: 10017], @"x-mac-ukrainian", - [NSNumber numberWithInt: 10021], @"x-mac-thai", - [NSNumber numberWithInt: 10029], @"x-mac-ce", - [NSNumber numberWithInt: 10079], @"x-mac-icelandic", - [NSNumber numberWithInt: 10081], @"x-mac-turkish", - [NSNumber numberWithInt: 10082], @"x-mac-croatian", - [NSNumber numberWithInt: 12000], @"utf-32", - [NSNumber numberWithInt: 12001], @"utf-32be", - [NSNumber numberWithInt: 20000], @"x-chinese-cns", - [NSNumber numberWithInt: 20001], @"x-cp20001", - [NSNumber numberWithInt: 20002], @"x-chinese-eten", - [NSNumber numberWithInt: 20003], @"x-cp20003", - [NSNumber numberWithInt: 20004], @"x-cp20004", - [NSNumber numberWithInt: 20005], @"x-cp20005", - [NSNumber numberWithInt: 20105], @"x-ia5", - [NSNumber numberWithInt: 20106], @"x-ia5-german", - [NSNumber numberWithInt: 20107], @"x-ia5-swedish", - [NSNumber numberWithInt: 20108], @"x-ia5-norwegian", - [NSNumber numberWithInt: 20127], @"us-ascii", - [NSNumber numberWithInt: 20261], @"x-cp20261", - [NSNumber numberWithInt: 20269], @"x-cp20269", - [NSNumber numberWithInt: 20273], @"ibm273", - [NSNumber numberWithInt: 20277], @"ibm277", - [NSNumber numberWithInt: 20278], @"ibm278", - [NSNumber numberWithInt: 20280], @"ibm280", - [NSNumber numberWithInt: 20284], @"ibm284", - [NSNumber numberWithInt: 20285], @"ibm285", - [NSNumber numberWithInt: 20290], @"ibm290", - [NSNumber numberWithInt: 20297], @"ibm297", - [NSNumber numberWithInt: 20420], @"ibm420", - [NSNumber numberWithInt: 20423], @"ibm423", - [NSNumber numberWithInt: 20424], @"ibm424", - [NSNumber numberWithInt: 20833], @"x-ebcdic-koreanextended", - [NSNumber numberWithInt: 20838], @"ibm-thai", - [NSNumber numberWithInt: 20866], @"koi8-r", - [NSNumber numberWithInt: 20871], @"ibm871", - [NSNumber numberWithInt: 20880], @"ibm880", - [NSNumber numberWithInt: 20905], @"ibm905", - [NSNumber numberWithInt: 20924], @"ibm00924", - [NSNumber numberWithInt: 20932], @"euc-jp", - [NSNumber numberWithInt: 20936], @"x-cp20936", - [NSNumber numberWithInt: 20949], @"x-cp20949", - [NSNumber numberWithInt: 21025], @"cp1025", - [NSNumber numberWithInt: 21866], @"koi8-u", - [NSNumber numberWithInt: 28591], @"iso-8859-1", - [NSNumber numberWithInt: 28592], @"iso-8859-2", - [NSNumber numberWithInt: 28593], @"iso-8859-3", - [NSNumber numberWithInt: 28594], @"iso-8859-4", - [NSNumber numberWithInt: 28595], @"iso-8859-5", - [NSNumber numberWithInt: 28596], @"iso-8859-6", - [NSNumber numberWithInt: 28597], @"iso-8859-7", - [NSNumber numberWithInt: 28598], @"iso-8859-8", - [NSNumber numberWithInt: 28599], @"iso-8859-9", - [NSNumber numberWithInt: 28603], @"iso-8859-13", - [NSNumber numberWithInt: 28605], @"iso-8859-15", - [NSNumber numberWithInt: 29001], @"x-europa", - [NSNumber numberWithInt: 38598], @"iso-8859-8-i", - [NSNumber numberWithInt: 50220], @"iso-2022-jp", - [NSNumber numberWithInt: 50221], @"csiso2022jp", - [NSNumber numberWithInt: 50222], @"iso-2022-jp", - [NSNumber numberWithInt: 50225], @"iso-2022-kr", - [NSNumber numberWithInt: 50227], @"x-cp50227", - [NSNumber numberWithInt: 51932], @"euc-jp", - [NSNumber numberWithInt: 51936], @"euc-cn", - [NSNumber numberWithInt: 51949], @"euc-kr", - [NSNumber numberWithInt: 52936], @"hz-gb-2312", - [NSNumber numberWithInt: 54936], @"gb18030", - [NSNumber numberWithInt: 57002], @"x-iscii-de", - [NSNumber numberWithInt: 57003], @"x-iscii-be", - [NSNumber numberWithInt: 57004], @"x-iscii-ta", - [NSNumber numberWithInt: 57005], @"x-iscii-te", - [NSNumber numberWithInt: 57006], @"x-iscii-as", - [NSNumber numberWithInt: 57007], @"x-iscii-or", - [NSNumber numberWithInt: 57008], @"x-iscii-ka", - [NSNumber numberWithInt: 57009], @"x-iscii-ma", - [NSNumber numberWithInt: 57010], @"x-iscii-gu", - [NSNumber numberWithInt: 57011], @"x-iscii-pa", - [NSNumber numberWithInt: 65000], @"utf-7", - [NSNumber numberWithInt: 65001], @"utf-8", - nil] retain]; - } - return table; -} - -+ (NSDictionary *) getReverseCodepagesTable -{ - static NSDictionary *table = nil; - - if (table == nil) - { - NSDictionary *codepages_table; - NSEnumerator *enumerator; - NSMutableArray *codepages, *names; - id key; - // Build reverse table: (NSNumber) codepage -> (NSString) encoding name - codepages_table = [self getCodepagesTable]; - codepages = [NSMutableArray arrayWithCapacity: [codepages_table count]]; - names = [NSMutableArray arrayWithCapacity: [codepages_table count]]; - enumerator = [codepages_table keyEnumerator]; - while ((key = [enumerator nextObject])) - { - [names addObject: key]; - [codepages addObject: [codepages_table objectForKey: key]]; - } - table = [[NSDictionary dictionaryWithObjects: names forKeys: codepages] retain]; - } - return table; -} - -+ (NSNumber *) getCodepageFromName: (NSString *) name -{ - return [[self getCodepagesTable] objectForKey: [name lowercaseString]]; -} - -+ (NSString *) getNameFromCodepage: (NSNumber *) codepage -{ - return [[self getReverseCodepagesTable] objectForKey: codepage]; -} - -@end diff --git a/Attic/OpenChange/GNUmakefile b/Attic/OpenChange/GNUmakefile deleted file mode 100644 index 739fbd95b..000000000 --- a/Attic/OpenChange/GNUmakefile +++ /dev/null @@ -1,200 +0,0 @@ - -# GNUstep makefile - -include ../config.make -include $(GNUSTEP_MAKEFILES)/common.make -include ../Version - -BACKEND_VERSION = 1.0.0 - -### bootstrap library -MAPISTORESOGO = MAPIStoreSOGo -LIBRARY_NAME = $(MAPISTORESOGO) - -$(MAPISTORESOGO)_VERSION = $(BACKEND_VERSION) - -$(MAPISTORESOGO)_OBJC_FILES += \ - MAPIStoreSOGo.m - -### backend bundle -SOGOBACKEND = SOGoBackend -BUNDLE_NAME = $(SOGOBACKEND) -BUNDLE_EXTENSION = .MAPIStore -BUNDLE_INSTALL_DIR = $(SOGO_LIBDIR) - -PYTHON = /usr/bin/python -PYTHON_IS_GOOD = $(shell $(PYTHON) -c 'from sys import version_info; a=version_info; print a[0] == 2 and a[1] >= 6') -ifeq (${PYTHON_IS_GOOD},False) -PYTHON = /usr/bin/python2.6 -endif - -all:: - @echo " Python executable: ${PYTHON}" - -SAMBA_PRIVATE_DIR = $(shell $(PYTHON) ./samba-get-config.py 'private dir' || echo /var/lib/samba/private) - -$(SOGOBACKEND)_PRINCIPAL_CLASS = MAPIApplication - -$(SOGOBACKEND)_OBJC_FILES += \ - MAPIApplication.m \ - MAPIStoreActiveTables.m \ - MAPIStoreAuthenticator.m \ - MAPIStoreMapping.m \ - MAPIStoreMIME.m \ - MAPIStoreTypes.m \ - MAPIStorePropertySelectors.m \ - MAPIStoreSamDBUtils.m \ - MAPIStoreUserContext.m \ - \ - SOGoMAPIDBMessage.m \ - SOGoCacheGCSObject+MAPIStore.m \ - \ - MAPIStoreAppointmentWrapper.m \ - MAPIStoreAttachment.m \ - MAPIStoreAttachmentTable.m \ - MAPIStoreContext.m \ - MAPIStoreEmbeddedMessage.m \ - MAPIStoreFolder.m \ - MAPIStoreMessage.m \ - MAPIStoreObject.m \ - MAPIStoreObjectProxy.m \ - MAPIStoreSOGoObject.m \ - MAPIStoreTable.m \ - MAPIStoreMessageTable.m \ - MAPIStoreFolderTable.m \ - MAPIStorePermissionsTable.m \ - \ - MAPIStoreDBBaseContext.m \ - MAPIStoreDBFolder.m \ - MAPIStoreDBFolderTable.m \ - MAPIStoreDBMessage.m \ - MAPIStoreDBMessageTable.m \ - \ - MAPIStoreFAIMessage.m \ - MAPIStoreFAIMessageTable.m \ - \ - MAPIStoreGCSBaseContext.m \ - MAPIStoreGCSFolder.m \ - MAPIStoreGCSMessage.m \ - MAPIStoreGCSMessageTable.m \ - \ - MAPIStoreCalTaskFolder.m \ - MAPIStoreCalTaskMessage.m \ - \ - MAPIStoreCalendarAttachment.m \ - MAPIStoreCalendarContext.m \ - MAPIStoreCalendarFolder.m \ - MAPIStoreCalendarMessage.m \ - MAPIStoreCalendarEmbeddedMessage.m \ - MAPIStoreCalendarMessageTable.m \ - MAPIStoreRecurrenceUtils.m \ - \ - MAPIStoreContactsAttachment.m \ - MAPIStoreContactsContext.m \ - MAPIStoreContactsFolder.m \ - MAPIStoreContactsMessage.m \ - MAPIStoreContactsMessageTable.m \ - \ - MAPIStoreTasksContext.m \ - MAPIStoreTasksFolder.m \ - MAPIStoreTasksMessage.m \ - MAPIStoreTasksMessageTable.m \ - \ - MAPIStoreMailAttachment.m \ - MAPIStoreMailContext.m \ - MAPIStoreMailFolder.m \ - MAPIStoreMailFolderTable.m \ - MAPIStoreMailMessage.m \ - MAPIStoreMailVolatileMessage.m \ - MAPIStoreMailMessageTable.m \ - \ - MAPIStoreNotesContext.m \ - MAPIStoreNotesFolder.m \ - MAPIStoreNotesMessage.m \ - \ - MAPIStoreFallbackContext.m \ - \ - MAPIStoreSharingMessage.m \ - \ - NSArray+MAPIStore.m \ - NSData+MAPIStore.m \ - NSDate+MAPIStore.m \ - NSObject+MAPIStore.m \ - NSString+MAPIStore.m \ - NSValue+MAPIStore.m \ - \ - iCalEvent+MAPIStore.m \ - iCalTimeZone+MAPIStore.m \ - \ - RTFHandler.m \ - \ - Codepages.m - - -$(SOGOBACKEND)_RESOURCE_FILES += \ - product.plist - -### pl reader -PLREADER_TOOL = plreader -$(PLREADER_TOOL)_OBJC_FILES += \ - plreader.m \ - -DBMSGREADER_TOOL = dbmsgreader -$(DBMSGREADER_TOOL)_OBJC_FILES += \ - dbmsgreader.m \ - NSObject+PropertyList.m - -$(DBMSGREADER_TOOL)_LIB_DIRS += \ - -L../SoObjects/SOGo/SOGo.framework/sogo -lSOGo \ - -L../SOPE/GDLContentStore/obj/ -lGDLContentStore \ - -L../SOPE/NGCards/obj/ -lNGCards \ - -lNGObjWeb \ - $(LIBMAPI_LIBS) - -TEST_TOOL_NAME += $(PLREADER_TOOL) $(DBMSGREADER_TOOL) - -### cflags and libs -LIBMAPI_CFLAGS = $(shell pkg-config libmapi --cflags) - -ifeq ($(LIBMAPI_CFLAGS),) -all install:: - @echo "Cannot build the OpenChange SOGo backend (empty CFLAGS for libmapistore)" -else - -SAMBA_LIB_DIR = $(shell pkg-config libmapistore --variable=libdir) - -LIBMAPI_LIBS = $(shell pkg-config libmapi --libs) - -LIBMAPISTORE_CFLAGS = $(shell pkg-config libmapistore --cflags) -DSAMBA_PREFIX="\"$(shell pkg-config libmapistore --variable=prefix)\"" -LIBMAPISTORE_LIBS = $(shell pkg-config libmapistore --libs) -lmapiproxy -lWEExtensions - -$(MAPISTORESOGO)_INSTALL_DIR = $(DESTDIR)/$(SAMBA_LIB_DIR)/mapistore_backends -$(MAPISTORESOGO)_LIB_DIRS += \ - -L../SoObjects/SOGo/SOGo.framework/sogo/ -lSOGo -lgnustep-base -lobjc -lNGObjWeb \ - $(LIBMAPI_LIBS) \ - $(LIBMAPISTORE_LIBS) - -$(SOGOBACKEND)_LIB_DIRS += \ - -L../SoObjects/SOGo/SOGo.framework/sogo/ -lSOGo \ - $(LIBMAPI_LIBS) \ - $(LIBMAPISTORE_LIBS) - -ADDITIONAL_INCLUDE_DIRS += \ - -Wall \ - -DSAMBA_PRIVATE_DIR=@"\"$(SAMBA_PRIVATE_DIR)\"" \ - $(LIBMAPI_CFLAGS) \ - $(LIBMAPISTORE_CFLAGS) \ - -I../SoObjects -I../SOPE \ - -DBACKEND_BUNDLE_NAME="@\"$(BUNDLE_NAME)$(BUNDLE_EXTENSION)\"" \ - -DSOGO_BUNDLES_DIR="@\"$(BUNDLE_INSTALL_DIR)\"" - -ADDITIONAL_LDFLAGS += -Wl,--rpath,$(SOGO_SYSLIBDIR)/sogo - --include GNUmakefile.preamble -include $(GNUSTEP_MAKEFILES)/bundle.make -include $(GNUSTEP_MAKEFILES)/library.make -include $(GNUSTEP_MAKEFILES)/test-tool.make -include $(GNUSTEP_MAKEFILES)/aggregate.make --include GNUmakefile.postamble - -endif diff --git a/Attic/OpenChange/GNUmakefile.preamble b/Attic/OpenChange/GNUmakefile.preamble deleted file mode 100644 index 7dba896b6..000000000 --- a/Attic/OpenChange/GNUmakefile.preamble +++ /dev/null @@ -1,8 +0,0 @@ -all:: MAPIStorePropertySelectors.m MAPIStorePropertySelectors.h - -MAPIStorePropertySelectors.m MAPIStorePropertySelectors.h: gen-property-selectors.py code-MAPIStorePropertySelectors.m code-MAPIStorePropertySelectors.h - @echo " Auto-generating MAPIStorePropertySelectors.[hm]..." - @$(PYTHON) ./gen-property-selectors.py -o MAPIStorePropertySelectors $(LIBMAPISTORE_CFLAGS) - -distclean clean:: - -rm -f MAPIStorePropertySelectors.m MAPIStorePropertySelectors.h diff --git a/Attic/OpenChange/MAPIApplication.h b/Attic/OpenChange/MAPIApplication.h deleted file mode 100644 index 44fdaa15a..000000000 --- a/Attic/OpenChange/MAPIApplication.h +++ /dev/null @@ -1,44 +0,0 @@ -/* MAPIApplication.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 MAPIAPPLICATION_H -#define MAPIAPPLICATION_H - -#import - -@class MAPIStoreUserContext; - -@interface MAPIApplication : SoApplication -{ - MAPIStoreUserContext *userContext; -} - -- (id) authenticatorInContext: (id) context; -- (MAPIStoreUserContext *) userContext; -- (void) setUserContext: (MAPIStoreUserContext *) newContext; -- (void) cleanup; - -@end - -extern MAPIApplication *MAPIApp; - -#endif /* MAPIAPPLICATION_H */ diff --git a/Attic/OpenChange/MAPIApplication.m b/Attic/OpenChange/MAPIApplication.m deleted file mode 100644 index 818ec1199..000000000 --- a/Attic/OpenChange/MAPIApplication.m +++ /dev/null @@ -1,101 +0,0 @@ -/* MAPIApplication.m - this file is part of SOGo - * - * Copyright (C) 2010 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. - */ - -#import -#import -#import - -#import -#import - -#import - -#import "MAPIStoreUserContext.h" -#import "MAPIStoreTypes.h" - -#import "MAPIApplication.h" - -MAPIApplication *MAPIApp = nil; - -@implementation MAPIApplication - -+ (BOOL) isCachingEnabled; -{ - return NO; -} - -- (NSString *) name -{ - return @"SOGo"; -} - -- (id) init -{ - if (!MAPIApp) - { - WEResourceManager *rm; - - // TODO publish - [iCalEntityObject initializeSOGoExtensions]; - - MAPIApp = [super init]; - [MAPIApp retain]; - - rm = [[WEResourceManager alloc] init]; - [self setResourceManager:rm]; - [rm release]; - - utcTZ = [NSTimeZone timeZoneWithName: @"UTC"]; - [utcTZ retain]; - } - - return MAPIApp; -} - -- (BOOL) shouldSetupSignalHandlers -{ - return NO; -} - -- (MAPIStoreUserContext *) userContext -{ - return userContext; -} - -- (void) setUserContext: (MAPIStoreUserContext *) newContext -{ - /* user contexts must not be retained here ad their holder (mapistore) - contexts must be active when any operation occurs. */ - userContext = newContext; -} - -- (id) authenticatorInContext: (id) context -{ - return [userContext authenticator]; -} - -- (void) cleanup -{ - [userContext deactivate]; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreActiveTables.h b/Attic/OpenChange/MAPIStoreActiveTables.h deleted file mode 100644 index 8459bd9c1..000000000 --- a/Attic/OpenChange/MAPIStoreActiveTables.h +++ /dev/null @@ -1,47 +0,0 @@ -/* MAPIStoreActiveTables.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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 MAPISTOREACTIVETABLES_H -#define MAPISTOREACTIVETABLES_H - -#import - -@class NSMutableArray; - -@class MAPIStoreTable; - -@interface MAPIStoreActiveTables : NSObject -{ - NSMutableArray *records; -} - -+ (id) activeTables; - -- (void) registerTable: (MAPIStoreTable *) table; -- (void) unregisterTable: (MAPIStoreTable *) table; - -- (NSArray *) activeTablesForFMID: (uint64_t) fmid - andType: (uint8_t) tableType; - -@end - -#endif /* MAPISTOREACTIVETABLES_H */ diff --git a/Attic/OpenChange/MAPIStoreActiveTables.m b/Attic/OpenChange/MAPIStoreActiveTables.m deleted file mode 100644 index a9cb0c254..000000000 --- a/Attic/OpenChange/MAPIStoreActiveTables.m +++ /dev/null @@ -1,198 +0,0 @@ -/* MAPIStoreActiveTables.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -/* MAPIStoreActiveTables provides an interface to keep accounting of all - instances of a given table, independently from its store and context. - Primary useful for notifications across different connections. */ - -#import -#import - -#import "MAPIStoreFolder.h" -#import "MAPIStoreTable.h" - -#import "MAPIStoreActiveTables.h" - -@interface MAPIStoreActiveTableRecord : NSObject -{ - uint64_t folderId; - uint8_t tableType; - MAPIStoreTable *table; -} - -+ (id) recordForTable: (MAPIStoreTable *) newTable; -- (id) initWithTable: (MAPIStoreTable *) newTable; - -- (MAPIStoreTable *) table; - -- (BOOL) exactlyMatchesTable: (MAPIStoreTable *) otherTable; -- (BOOL) matchesFMID: (uint64_t) otherFMid - andTableType: (uint8_t) otherTableType; -- (BOOL) matchesTable: (MAPIStoreTable *) otherTable; - -@end - -@implementation MAPIStoreActiveTableRecord : NSObject - -+ (id) recordForTable: (MAPIStoreTable *) newTable -{ - MAPIStoreActiveTableRecord *record; - - record = [[self alloc] initWithTable: newTable]; - [record autorelease]; - - return record; -} - -- (id) init -{ - if ((self = [super init])) - { - folderId = 0; - tableType = 0; - table = nil; - } - - return self; -} - -- (id) initWithTable: (MAPIStoreTable *) newTable -{ - if ((self = [self init])) - { - table = newTable; - folderId = [[table container] objectId]; - tableType = [table tableType]; - } - - return self; -} - -- (MAPIStoreTable *) table -{ - return table; -} - -- (BOOL) exactlyMatchesTable: (MAPIStoreTable *) otherTable -{ - return (table == otherTable); -} - -- (BOOL) matchesFMID: (uint64_t) otherFMid - andTableType: (uint8_t) otherTableType -{ - return (tableType == otherTableType - && folderId == otherFMid); -} - -- (BOOL) matchesTable: (MAPIStoreTable *) otherTable -{ - uint64_t otherFMid; - BOOL rc; - - rc = [self exactlyMatchesTable: otherTable]; - if (!rc) - { - otherFMid = [[otherTable container] objectId]; - rc = [self matchesFMID: otherFMid andTableType: [otherTable tableType]]; - } - - return rc; -} - -@end - -@implementation MAPIStoreActiveTables - -+ (id) activeTables -{ - static MAPIStoreActiveTables *activeTables = nil; - - if (!activeTables) - activeTables = [self new]; - - return activeTables; -} - -- (id) init -{ - if ((self = [super init])) - { - records = [NSMutableArray new]; - } - - return self; -} - -- (void) dealloc -{ - [records release]; - [super dealloc]; -} - -- (void) registerTable: (MAPIStoreTable *) table -{ - MAPIStoreActiveTableRecord *newRecord; - - newRecord = [MAPIStoreActiveTableRecord recordForTable: table]; - [records addObject: newRecord]; -} - -- (void) unregisterTable: (MAPIStoreTable *) table -{ - MAPIStoreActiveTableRecord *currentRecord; - NSUInteger count, max; - BOOL done = NO; - - max = [records count]; - for (count = 0; !done && count < max; count++) - { - currentRecord = [records objectAtIndex: count]; - if ([currentRecord exactlyMatchesTable: table]) - { - [records removeObject: currentRecord]; - done = YES; - } - } -} - -- (NSArray *) activeTablesForFMID: (uint64_t) fmid - andType: (uint8_t) tableType -{ - NSUInteger count, max; - NSMutableArray *tables; - MAPIStoreActiveTableRecord *currentRecord; - - tables = [NSMutableArray arrayWithCapacity: 5]; - - max = [records count]; - for (count = 0; count < max; count++) - { - currentRecord = [records objectAtIndex: count]; - if ([currentRecord matchesFMID: fmid andTableType: tableType]) - [tables addObject: [currentRecord table]]; - } - - return tables; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreAppointmentWrapper.h b/Attic/OpenChange/MAPIStoreAppointmentWrapper.h deleted file mode 100644 index 5ed4c83ff..000000000 --- a/Attic/OpenChange/MAPIStoreAppointmentWrapper.h +++ /dev/null @@ -1,177 +0,0 @@ -/* MAPIStoreAppointmentWrapper.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTORECALENDARWRAPPER_H -#define MAPISTORECALENDARWRAPPER_H - -#import -#import -#import - -#import "MAPIStoreObjectProxy.h" - -@class NSTimeZone; - -@class iCalAlarm; -@class iCalCalendar; -@class iCalEvent; - -@class SOGoUser; - -@interface MAPIStoreAppointmentWrapper : MAPIStoreObjectProxy -{ - struct mapistore_connection_info *connInfo; - iCalCalendar *calendar; - iCalEvent *firstEvent; - iCalEvent *event; - iCalTimeZone *timeZone; - SOGoUser *user; - NSString *senderEmail; - NSData *globalObjectId; - NSData *cleanGlobalObjectId; - BOOL alarmSet; - iCalAlarm *alarm; - BOOL itipSetup; - NSString *method; - iCalPersonPartStat partstat; -} - -+ (id) wrapperWithICalEvent: (iCalEvent *) newEvent - andUser: (SOGoUser *) newUser - andSenderEmail: (NSString *) newSenderEmail - withConnectionInfo: (struct mapistore_connection_info *) newConnInfo; -- (id) initWithICalEvent: (iCalEvent *) newEvent - andUser: (SOGoUser *) newUser - andSenderEmail: (NSString *) newSenderEmail - withConnectionInfo: (struct mapistore_connection_info *) newConnInfo; - -/* getters */ -- (void) fillMessageData: (struct mapistore_message *) dataPtr - inMemCtx: (TALLOC_CTX *) memCtx; - -- (NSString *) creator; -- (NSString *) owner; -- (NSUInteger) sensitivity; - -- (enum mapistore_error) getPidTagSenderEmailAddress: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagSenderAddressType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagSenderName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagSenderEntryId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; - -- (enum mapistore_error) getPidTagReceivedByAddressType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagReceivedByEmailAddress: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagReceivedByName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagReceivedByEntryId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; - -- (enum mapistore_error) getPidTagIconIndex: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagOwnerAppointmentId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidMeetingType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagMessageClass: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagStartDate: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidAppointmentSequence: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidAppointmentStateFlags: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidResponseStatus: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; - -- (enum mapistore_error) getPidLidAppointmentStartWhole: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidCommonStart: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagEndDate: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidAppointmentEndWhole: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidCommonEnd: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidAppointmentDuration: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidAppointmentSubType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidBusyStatus: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidIndentedBusyStatus: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagNormalizedSubject: (void **) data // SUMMARY - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidLocation: (void **) data // LOCATION - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidPrivate: (void **) data // private (bool), should depend on CLASS and permissions - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagSensitivity: (void **) data // not implemented, depends on CLASS - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagImportance: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagBody: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidIsRecurring: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidRecurring: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidAppointmentRecur: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidGlobalObjectId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidCleanGlobalObjectId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidServerProcessed: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidServerProcessingActions: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidAppointmentReplyTime: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; - -/* reminders */ -- (enum mapistore_error) getPidLidReminderSet: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidReminderDelta: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidReminderTime: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidReminderSignalTime: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidReminderOverride: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidReminderType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidReminderPlaySound: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidReminderFileParameter: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; - -@end - -#endif /* MAPISTORECALENDARWRAPPER_H */ diff --git a/Attic/OpenChange/MAPIStoreAppointmentWrapper.m b/Attic/OpenChange/MAPIStoreAppointmentWrapper.m deleted file mode 100644 index 1881a16a5..000000000 --- a/Attic/OpenChange/MAPIStoreAppointmentWrapper.m +++ /dev/null @@ -1,2115 +0,0 @@ -/* MAPIStoreAppointmentWrapper.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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 - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#import "iCalTimeZone+MAPIStore.h" -#import "MAPIStoreRecurrenceUtils.h" -#import "MAPIStoreSamDBUtils.h" -#import "MAPIStoreTypes.h" -#import "NSArray+MAPIStore.h" -#import "NSData+MAPIStore.h" -#import "NSDate+MAPIStore.h" -#import "NSObject+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreAppointmentWrapper.h" - -#undef DEBUG -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static NSCharacterSet *hexCharacterSet = nil; - -@implementation MAPIStoreAppointmentWrapper - -+ (void) initialize -{ - if (!hexCharacterSet) - { - hexCharacterSet = [NSCharacterSet characterSetWithCharactersInString: @"1234567890abcdefABCDEF"]; - [hexCharacterSet retain]; - } -} - -+ (id) wrapperWithICalEvent: (iCalEvent *) newEvent - andUser: (SOGoUser *) newUser - andSenderEmail: (NSString *) newSenderEmail - withConnectionInfo: (struct mapistore_connection_info *) newConnInfo -{ - MAPIStoreAppointmentWrapper *wrapper; - - wrapper = [[self alloc] initWithICalEvent: newEvent - andUser: newUser - andSenderEmail: newSenderEmail - withConnectionInfo: newConnInfo]; - [wrapper autorelease]; - - return wrapper; -} - -- (id) init -{ - if ((self = [super init])) - { - connInfo = NULL; - calendar = nil; - event = nil; - timeZone = nil; - senderEmail = nil; - globalObjectId = nil; - cleanGlobalObjectId = nil; - user = nil; - alarmSet = NO; - itipSetup = NO; - alarm = nil; - method = nil; - } - - return self; -} - -- (void) _setupITIPContextFromAttendees -{ - iCalPerson *attendee = nil; - NSArray *attendees; - - attendee = [event userAsAttendee: user]; - if (attendee) - method = @"REQUEST"; - else if ([event userIsOrganizer: user]) - { - if (senderEmail) - attendee = [event findAttendeeWithEmail: senderEmail]; - if (!attendee) - { - attendees = [event attendees]; - if ([attendees count] == 1) - attendee = [attendees objectAtIndex: 0]; - } - if (attendee) - { - method = @"REPLY"; - partstat = [attendee participationStatus]; - } - else - { - [self logWithFormat: @"no attendee matching sender found"]; - method = nil; - } - } - else - method = nil; - - [method retain]; -} - -- (void) _setupITIPContext -{ - NSArray *attendees; - NSUInteger max; - - /* Here we attempt to determine the type of message from the ITIP method - contained in the event. It it fails, we attempt to determine this by - checking the identity of the organizer and of the attendees. */ - itipSetup = YES; - method = [[event parent] method]; - if ([method length] > 0) - { - method = [method uppercaseString]; - [method retain]; - if ([method isEqualToString: @"REPLY"]) - { - attendees = [event attendees]; - max = [attendees count]; - if (max == 1) - partstat = [[attendees objectAtIndex: 0] participationStatus]; - else if (max > 1) - [self _setupITIPContextFromAttendees]; - } - } - else - [self _setupITIPContextFromAttendees]; -} - -- (id) initWithICalEvent: (iCalEvent *) newEvent - andUser: (SOGoUser *) newUser - andSenderEmail: (NSString *) newSenderEmail - withConnectionInfo: (struct mapistore_connection_info *) newConnInfo -{ - NSArray *events; - iCalTimeZone *tz; - - if ((self = [self init])) - { - connInfo = newConnInfo; - ASSIGN (calendar, [newEvent parent]); - event = newEvent; - events = [calendar events]; - firstEvent = [events objectAtIndex: 0]; - ASSIGN (user, newUser); - ASSIGN (senderEmail, newSenderEmail); - /* If newEvent comes from the client, we set its time zone in - updateFromMAPIProperties. If it is not present, we use the - time zone of the user */ - tz = (iCalTimeZone *) [calendar firstChildWithTag: @"vtimezone"]; - if (!tz) - { - tz = [iCalTimeZone timeZoneForName: [[[user userDefaults] timeZone] name]]; - if (!tz) - [self logWithFormat: @"no time zone could be set"]; - } - ASSIGN (timeZone, tz); - - [self _setupITIPContext]; - } - - return self; -} - -- (void) dealloc -{ - [calendar release]; - [timeZone release]; - [user release]; - [senderEmail release]; - [globalObjectId release]; - [cleanGlobalObjectId release]; - [alarm release]; - [method release]; - [super dealloc]; -} - -- (void) fillMessageData: (struct mapistore_message *) msgData - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *username, *cn, *email; - NSData *entryId; - NSArray *attendees; - iCalPerson *person; - iCalPersonPartStat partStat; - uint32_t partStatValue; - SOGoUserManager *mgr; - NSDictionary *contactInfos; - struct mapistore_message_recipient *recipient; - int count, max, p; - - msgData->columns = set_SPropTagArray (msgData, 9, - PR_OBJECT_TYPE, - PR_DISPLAY_TYPE, - PR_7BIT_DISPLAY_NAME_UNICODE, - PR_SMTP_ADDRESS_UNICODE, - PR_SEND_INTERNET_ENCODING, - PR_RECIPIENT_DISPLAY_NAME_UNICODE, - PR_RECIPIENT_FLAGS, - PR_RECIPIENT_ENTRYID, - PR_RECIPIENT_TRACKSTATUS); -// , -// PR_RECORD_KEY); - - attendees = [event attendees]; - max = [attendees count]; - - if (max > 0) - { - mgr = [SOGoUserManager sharedUserManager]; - msgData->recipients_count = max + 1; - msgData->recipients = talloc_array (msgData, struct mapistore_message_recipient, max + 1); - for (count = 0; count < max; count++) - { - recipient = msgData->recipients + count; - - person = [attendees objectAtIndex: count]; - cn = [person cn]; - email = [person rfc822Email]; - if ([cn length] == 0) - cn = email; - contactInfos = [mgr contactInfosForUserWithUIDorEmail: email]; - - if (contactInfos) - { - username = [contactInfos objectForKey: @"sAMAccountName"]; - recipient->username = [username asUnicodeInMemCtx: msgData]; - entryId = MAPIStoreInternalEntryId (connInfo, username); - } - else - { - recipient->username = NULL; - entryId = MAPIStoreExternalEntryId (cn, email); - } - recipient->type = [[person role] isEqualToString: @"OPT-PARTICIPANT"] ? MAPI_CC : MAPI_TO; - - /* properties */ - p = 0; - recipient->data = talloc_array (msgData, void *, msgData->columns->cValues); - memset (recipient->data, 0, msgData->columns->cValues * sizeof (void *)); - - // PR_OBJECT_TYPE = MAPI_MAILUSER (see MAPI_OBJTYPE) - recipient->data[p] = MAPILongValue (msgData, MAPI_MAILUSER); - p++; - - // PR_DISPLAY_TYPE = DT_MAILUSER (see MS-NSPI) - recipient->data[p] = MAPILongValue (msgData, 0); - p++; - - // PR_7BIT_DISPLAY_NAME_UNICODE - recipient->data[p] = [cn asUnicodeInMemCtx: msgData]; - p++; - - // PR_SMTP_ADDRESS_UNICODE - recipient->data[p] = [email asUnicodeInMemCtx: msgData]; - p++; - - // PR_SEND_INTERNET_ENCODING = 0x00060000 (plain text, see OXCMAIL) - recipient->data[p] = MAPILongValue (msgData, 0x00060000); - p++; - - // PR_RECIPIENT_DISPLAY_NAME_UNICODE - recipient->data[p] = [cn asUnicodeInMemCtx: msgData]; - p++; - - // PR_RECIPIENT_FLAGS - recipient->data[p] = MAPILongValue (msgData, 1); - p++; - - // PR_RECIPIENT_ENTRYID - recipient->data[p] = [entryId asBinaryInMemCtx: msgData]; - p++; - - // PR_RECIPIENT_TRACKSTATUS - /* - respNone 0x00000000 - No response is required for this object. This is the case for Appointment objects and Meeting Response objects. - respOrganized 0x00000001 - This Meeting object belongs to the organizer. - respTentative 0x00000002 - This value on the attendee's Meeting object indicates that the - attendee has tentatively accepted the Meeting Request object. - respAccepted 0x00000003 - This value on the attendee's Meeting object indicates that the - attendee has accepted the Meeting Request object. - respDeclined 0x00000004 - This value on the attendee's Meeting object indicates that the attendee has declined the Meeting Request - object. - respNotResponded 0x00000005 - This value on the attendee's Meeting object indicates that the attendee has - not yet responded. This value is on the Meet - */ - partStat = [person participationStatus]; - switch (partStat) - { - case iCalPersonPartStatAccepted: - partStatValue = 3; - break; - case iCalPersonPartStatDeclined: - partStatValue = 4; - break; - case iCalPersonPartStatTentative: - partStatValue = 2; - break; - default: - partStatValue = 5; - } - recipient->data[p] = MAPILongValue (msgData, partStatValue); - p++; - - // // PR_RECORD_KEY - // recipient->data[p] = [entryId asBinaryInMemCtx: msgData]; - // p++; - } - - /* On with the organizer: */ - { - recipient = msgData->recipients + max; - - person = [event organizer]; - cn = [person cn]; - email = [person rfc822Email]; - contactInfos = [mgr contactInfosForUserWithUIDorEmail: email]; - - if (contactInfos) - { - username = [contactInfos objectForKey: @"sAMAccountName"]; - recipient->username = [username asUnicodeInMemCtx: msgData]; - entryId = MAPIStoreInternalEntryId (connInfo, username); - } - else - { - recipient->username = NULL; - entryId = MAPIStoreExternalEntryId (cn, email); - } - recipient->type = MAPI_TO; - - p = 0; - recipient->data = talloc_array (msgData, void *, msgData->columns->cValues); - memset (recipient->data, 0, msgData->columns->cValues * sizeof (void *)); - - // PR_OBJECT_TYPE = MAPI_MAILUSER (see MAPI_OBJTYPE) - recipient->data[p] = MAPILongValue (msgData, MAPI_MAILUSER); - p++; - - // PR_DISPLAY_TYPE = DT_MAILUSER (see MS-NSPI) - recipient->data[p] = MAPILongValue (msgData, 0); - p++; - - // PR_7BIT_DISPLAY_NAME_UNICODE - recipient->data[p] = [cn asUnicodeInMemCtx: msgData]; - p++; - - // PR_SMTP_ADDRESS_UNICODE - recipient->data[p] = [email asUnicodeInMemCtx: msgData]; - p++; - - // PR_SEND_INTERNET_ENCODING = 0x00060000 (plain text, see OXCMAIL) - recipient->data[p] = MAPILongValue (msgData, 0x00060000); - p++; - - // PR_RECIPIENT_DISPLAY_NAME_UNICODE - recipient->data[p] = [cn asUnicodeInMemCtx: msgData]; - p++; - - // PR_RECIPIENT_FLAGS - recipient->data[p] = MAPILongValue (msgData, 3); - p++; - - // PR_RECIPIENT_ENTRYID = NULL - recipient->data[p] = [entryId asBinaryInMemCtx: msgData]; - p++; - - // PR_RECIPIENT_TRACKSTATUS - /* - respNone 0x00000000 - No response is required for this object. This is the case for Appointment objects and Meeting Response objects. - respOrganized 0x00000001 - This Meeting object belongs to the organizer. - respTentative 0x00000002 - This value on the attendee's Meeting object indicates that the - attendee has tentatively accepted the Meeting Request object. - respAccepted 0x00000003 - This value on the attendee's Meeting object indicates that the - attendee has accepted the Meeting Request object. - respDeclined 0x00000004 - This value on the attendee's Meeting object indicates that the attendee has declined the Meeting Request - object. - respNotResponded 0x00000005 - This value on the attendee's Meeting object indicates that the attendee has - not yet responded. This value is on the Meet - */ - recipient->data[p] = MAPILongValue (msgData, 1); - p++; - - // // PR_RECORD_KEY - // recipient->data[p] = [entryId asBinaryInMemCtx: msgData]; - // p++; - } - } -} - -- (enum mapistore_error) getPidTagIconIndex: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - uint32_t longValue; - - /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx: - Single instance appointment: 0x00000400 - Recurring appointment: 0x00000401 - Single instance meeting: 0x00000402 - Recurring meeting: 0x00000403 - Meeting request: 0x00000404 - Accept: 0x00000405 - Decline: 0x00000406 - Tentativly: 0x00000407 - Cancellation: 0x00000408 - Informational update: 0x00000409 */ - - // if ([headerMethod isEqualToString: @"REQUEST"]) - // longValue = 0x0404; - // else - // longValue = 0x0400; - - if (!itipSetup) - [self _setupITIPContext]; - - longValue = 0x0400; - - if (method) - { - if ([method isEqualToString: @"REQUEST"]) - longValue |= 0x0004; - else if ([method isEqualToString: @"REPLY"]) - { - longValue |= 0x0004; - switch (partstat) - { - case iCalPersonPartStatAccepted: - longValue |= 0x0001; - break; - case iCalPersonPartStatDeclined: - longValue |= 0x0002; - break; - case iCalPersonPartStatTentative: - longValue |= 0x0003; - break; - default: - longValue = 0x0400; - [self logWithFormat: @"unhandled part stat"]; - } - } - else if ([method isEqualToString: @"CANCEL"]) - longValue |= 0x0008; - } - else - { - if ([event isRecurrent]) - longValue |= 0x0001; - if ([[event attendees] count] > 0) - longValue |= 0x0002; - } - - *data = MAPILongValue (memCtx, longValue); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagOwnerAppointmentId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - const char *utf8UID; - union { - uint32_t longValue; - char charValue[4]; - } value; - NSUInteger max, length; - - if ([[event attendees] count] > 0) - { - utf8UID = [[event uid] UTF8String]; - length = strlen (utf8UID); - max = 2; - if (length < max) - max = length; - memcpy (value.charValue, utf8UID, max); - memcpy (value.charValue + 2, utf8UID + length - 2, max); - - *data = MAPILongValue (memCtx, value.longValue); - - rc = MAPISTORE_SUCCESS; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidLidMeetingType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - /* TODO - See 2.2.6.5 PidLidMeetingType (OXOCAL) */ - *data = MAPILongValue (memCtx, 0x00000001); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidOwnerCriticalChange: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND; - NSCalendarDate *lastModified; - - if ([[event attendees] count] > 0) - { - lastModified = [event lastModified]; - if (lastModified) - { - *data = [lastModified asFileTimeInMemCtx: memCtx]; - rc = MAPISTORE_SUCCESS; - } - } - - return rc; -} - -- (enum mapistore_error) getPidLidAttendeeCriticalChange: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND; - NSCalendarDate *lastModified; - - if ([[event attendees] count] > 0) - { - lastModified = [event lastModified]; - if (lastModified) - { - *data = [lastModified asFileTimeInMemCtx: memCtx]; - rc = MAPISTORE_SUCCESS; - } - } - - return rc; -} - -- (enum mapistore_error) getPidTagMessageClass: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - const char *className; - - if (!itipSetup) - [self _setupITIPContext]; - - if (method) - { - if ([method isEqualToString: @"REQUEST"]) - className = "IPM.Schedule.Meeting.Request"; - else if ([method isEqualToString: @"REPLY"]) - { - switch (partstat) - { - case iCalPersonPartStatAccepted: - className = "IPM.Schedule.Meeting.Resp.Pos"; - break; - case iCalPersonPartStatDeclined: - className = "IPM.Schedule.Meeting.Resp.Neg"; - break; - case iCalPersonPartStatTentative: - className = "IPM.Schedule.Meeting.Resp.Tent"; - break; - default: - className = "IPM.Appointment"; - [self logWithFormat: @"unhandled part stat"]; - } - } - else if ([method isEqualToString: @"COUNTER"]) - className = "IPM.Schedule.Meeting.Resp.Tent"; - else if ([method isEqualToString: @"CANCEL"]) - className = "IPM.Schedule.Meeting.Cancelled"; - else - { - className = "IPM.Appointment"; - [self logWithFormat: @"unhandled method: %@", method]; - } - } - else - className = "IPM.Appointment"; - *data = talloc_strdup(memCtx, className); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidAppointmentMessageClass: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = talloc_strdup (memCtx, "IPM.Appointment"); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidFInvited: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getYes: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidAppointmentSequence: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, [[event sequence] unsignedIntValue]); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidAppointmentStateFlags: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - uint32_t flags = 0x00; - - if ([[event attendees] count] > 0) - { - flags |= 0x01; /* asfMeeting */ - if ([event userAsAttendee: user]) - flags |= 0x02; /* asfReceived */ - /* TODO: asfCancelled */ - } - - *data = MAPILongValue (memCtx, flags); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidResponseStatus: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - uint32_t status = 0x00; - iCalPerson *person; - - if ([[event attendees] count] > 0) - { - if ([event userIsOrganizer: user]) - status = 1; - else - { - person = [event userAsAttendee: user]; - if (person) - { - switch ([person participationStatus]) - { - case iCalPersonPartStatTentative: - status = 2; - break; - case iCalPersonPartStatAccepted: - status = 3; - break; - case iCalPersonPartStatDeclined: - status = 4; - break; - default: - status = 5; - } - } - } - } - - *data = MAPILongValue (memCtx, status); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidAppointmentNotAllowPropose: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getYes: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidAppointmentStartWhole: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSCalendarDate *dateValue; - - // if ([event isRecurrent]) - // dateValue = [event firstRecurrenceStartDate]; - // else - dateValue = [event startDate]; - if ([event isAllDay]) - dateValue = [timeZone shiftedCalendarDateForDate: dateValue]; - *data = [dateValue asFileTimeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagStartDate: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - /* "The PidTagStartDate property ([MS-OXPROPS] section 2.1077) SHOULD be - set, and when set, it MUST be equal to the value of the - PidLidAppointmentStartWhole property (section 2.2.1.5).". Not true for - exceptions, where it is the normal start date for the day of the - exception. */ - NSCalendarDate *dateValue; - - dateValue = [event recurrenceId]; - if (!dateValue) - dateValue = [event startDate]; - if ([event isAllDay]) - dateValue = [timeZone shiftedCalendarDateForDate: dateValue]; - *data = [dateValue asFileTimeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidCommonStart: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSCalendarDate *dateValue; - - dateValue = [firstEvent startDate]; - if ([firstEvent isAllDay]) - dateValue = [timeZone shiftedCalendarDateForDate: dateValue]; - *data = [dateValue asFileTimeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidClipStart: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - NSCalendarDate *dateValue, *start; - - if ([event isRecurrent]) - { - /* [MS-OXOCAL] For a recurring series, this property specifies - midnight in the user's machine time zone, on the date of the - first instance, then is persisted in UTC. */ - start = [event startDate]; - dateValue = [NSCalendarDate dateWithYear: [start yearOfCommonEra] - month: [start monthOfYear] - day: [start dayOfMonth] - hour: 0 minute: 0 second: 0 - timeZone: utcTZ]; - dateValue = [timeZone shiftedCalendarDateForDate: dateValue]; - *data = [dateValue asFileTimeInMemCtx: memCtx]; - rc = MAPISTORE_SUCCESS; - } - else if ([event recurrenceId] != nil) - rc = MAPISTORE_ERR_NOT_FOUND; - else - rc = [self getPidLidAppointmentStartWhole: data inMemCtx: memCtx]; - - return rc; -} - -- (enum mapistore_error) getPidLidAppointmentEndWhole: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSCalendarDate *dateValue; - NSInteger offset; - - // if ([event isRecurrent]) - // dateValue = [event firstRecurrenceStartDate]; - // else - dateValue = [event startDate]; - offset = [event durationAsTimeInterval]; - if ([event isAllDay]) - offset -= [[timeZone periodForDate: dateValue] secondsOffsetFromGMT]; - dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: offset]; - *data = [dateValue asFileTimeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagEndDate: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSCalendarDate *dateValue; - NSInteger offset; - - dateValue = [event recurrenceId]; - if (!dateValue) - dateValue = [event startDate]; - offset = [firstEvent durationAsTimeInterval]; - if ([firstEvent isAllDay]) - offset -= [[timeZone periodForDate: dateValue] secondsOffsetFromGMT]; - dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: offset]; - *data = [dateValue asFileTimeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidCommonEnd: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSCalendarDate *dateValue; - NSInteger offset; - - // if ([event isRecurrent]) - // dateValue = [event firstRecurrenceStartDate]; - // else - dateValue = [firstEvent startDate]; - offset = [firstEvent durationAsTimeInterval]; - if ([event isAllDay]) - offset -= [[timeZone periodForDate: dateValue] secondsOffsetFromGMT]; - dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: offset]; - *data = [dateValue asFileTimeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidClipEnd: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - NSCalendarDate *dateValue; - iCalRecurrenceRule *rrule; - - if ([event isRecurrent]) - { - rrule = [[event recurrenceRules] objectAtIndex: 0]; - dateValue = [rrule untilDate]; - if (dateValue && [event isAllDay]) - dateValue = [timeZone shiftedCalendarDateForDate: dateValue]; - else - dateValue = [NSCalendarDate dateWithYear: 4500 month: 8 day: 31 - hour: 23 minute: 59 second: 00 - timeZone: utcTZ]; - *data = [dateValue asFileTimeInMemCtx: memCtx]; - rc = MAPISTORE_SUCCESS; - } - else if ([event recurrenceId] != nil) - rc = MAPISTORE_ERR_NOT_FOUND; - else - rc = [self getPidLidAppointmentEndWhole: data inMemCtx: memCtx]; - - return rc; -} - -- (enum mapistore_error) _getEntryIdFromCN: (NSString *) cn - andEmail: (NSString *) email - inData: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *username; - SOGoUserManager *mgr; - NSDictionary *contactInfos; - NSData *entryId; - - mgr = [SOGoUserManager sharedUserManager]; - contactInfos = [mgr contactInfosForUserWithUIDorEmail: email]; - if (contactInfos) - { - username = [contactInfos objectForKey: @"sAMAccountName"]; - entryId = MAPIStoreInternalEntryId (connInfo, username); - } - else - entryId = MAPIStoreExternalEntryId (cn, email); - - *data = [entryId asBinaryInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) _getEmailAddress: (void **) data - forICalPerson: (iCalPerson *) person - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - NSString *email; - - email = [person rfc822Email]; - if ([email length] > 0) - { - *data = [email asUnicodeInMemCtx: memCtx]; - rc = MAPISTORE_SUCCESS; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) _getAddrType: (void **) data - forICalPerson: (iCalPerson *) person - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [@"SMTP" asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) _getName: (void **) data - forICalPerson: (iCalPerson *) person - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - NSString *cn; - - cn = [person cn]; - if ([cn length] > 0) - { - *data = [cn asUnicodeInMemCtx: memCtx]; - rc = MAPISTORE_SUCCESS; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) _getEntryId: (void **) data - forICalPerson: (iCalPerson *) person - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND; - NSString *email, *cn; - - if (person) - { - email = [person rfc822Email]; - if ([email length] > 0) - { - cn = [person cn]; - rc = [self _getEntryIdFromCN: cn andEmail: email - inData: data - inMemCtx: memCtx]; - } - } - - return rc; -} - -/* sender (organizer) */ -- (enum mapistore_error) getPidTagSenderEmailAddress: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getEmailAddress: data - forICalPerson: [event organizer] - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagSenderAddressType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getAddrType: data - forICalPerson: [event organizer] - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagSenderName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getName: data - forICalPerson: [event organizer] - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagSenderEntryId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getEntryId: data - forICalPerson: [event organizer] - inMemCtx: memCtx]; -} - -/* creator (only if created from Outlook/SOGo or organizer as fallback */ -- (NSString *) creator -{ - iCalPerson *person; - NSDictionary *contactInfos; - NSString *creator = nil, *email; - SOGoUserManager *mgr; - - creator = [[event uniqueChildWithTag: @"x-sogo-component-created-by"] - flattenedValuesForKey: @""]; - if ([creator length] == 0) - { - person = [event organizer]; - if (person) - { - email = [person rfc822Email]; - if ([email length] > 0) - { - mgr = [SOGoUserManager sharedUserManager]; - contactInfos = [mgr contactInfosForUserWithUIDorEmail: email]; - if (contactInfos) - creator = [contactInfos objectForKey: @"sAMAccountName"]; - } - } - } - return creator; -} - -/* owner is the organizer of the event, if none, try with the creator - who has saved only from Outlook or SOGo */ -- (NSString *) owner -{ - iCalPerson *person; - NSDictionary *contactInfos; - NSString *email, *owner = nil; - SOGoUserManager *mgr; - - person = [event organizer]; - if (person) - { - email = [person rfc822Email]; - if ([email length] > 0) - { - mgr = [SOGoUserManager sharedUserManager]; - contactInfos = [mgr contactInfosForUserWithUIDorEmail: email]; - if (contactInfos) - owner = [contactInfos objectForKey: @"sAMAccountName"]; - } - } - - if (!owner) - owner = [[event uniqueChildWithTag: @"x-sogo-component-created-by"] - flattenedValuesForKey: @""]; - - return owner; -} - -- (NSUInteger) sensitivity -{ - NSString *accessClass = nil; - NSUInteger v; - - accessClass = [event accessClass]; - if (accessClass) - { - if ([accessClass isEqualToString: @"X-PERSONAL"]) - v = 0x1; - else if ([accessClass isEqualToString: @"PRIVATE"]) - v = 0x2; - else if ([accessClass isEqualToString: @"CONFIDENTIAL"]) - v = 0x3; - else - v = 0x0; /* PUBLIC */ - } - else - v = 0x0; /* PUBLIC */ - - return v; -} - -/* sender representing */ -- (enum mapistore_error) getPidTagSentRepresentingEmailAddress: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagSenderEmailAddress: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagSentRepresentingAddressType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getSMTPAddrType: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagSentRepresentingName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagSenderName: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagSentRepresentingEntryId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagSenderEntryId: data inMemCtx: memCtx]; -} - -/* attendee */ -- (enum mapistore_error) getPidTagReceivedByEmailAddress: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getEmailAddress: data - forICalPerson: [event userAsAttendee: user] - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagReceivedByAddressType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getAddrType: data - forICalPerson: [event userAsAttendee: user] - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagReceivedByName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getName: data - forICalPerson: [event userAsAttendee: user] - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagReceivedByEntryId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getEntryId: data - forICalPerson: [event userAsAttendee: user] - inMemCtx: memCtx]; -} -/* /attendee */ - -- (enum mapistore_error) getPidLidAppointmentDuration: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSTimeInterval timeValue; - - timeValue = [[event endDate] timeIntervalSinceDate: [event startDate]]; - *data = MAPILongValue (memCtx, (uint32_t) (timeValue / 60)); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidAppointmentSubType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPIBoolValue (memCtx, [event isAllDay]); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidBusyStatus: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - uint8_t value; - - value = 0x2; // olBusy - - if (![event isOpaque]) - value = 0x0; // olFree - - *data = MAPILongValue (memCtx, value); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidIndentedBusyStatus: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidLidBusyStatus: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagNormalizedSubject: (void **) data // SUMMARY - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [[event summary] asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidLocation: (void **) data // LOCATION - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_SUCCESS; - NSString *location; - - location = [event location]; - if (location) - *data = [location asUnicodeInMemCtx: memCtx]; - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidLidWhere: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidLidLocation: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidServerProcessed: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - /* TODO: we need to check whether the event has been processed internally by - SOGo or if it was received only by mail. We only assume the SOGo case - here. */ - return [self getYes: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidServerProcessingActions: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, - 0x00000010 /* cpsCreatedOnPrincipal */ - | 0x00000080 /* cpsUpdatedCalItem */ - | 0x00000100 /* cpsCopiedOldProperties */); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidPrivate: (void **) data // private (bool), should depend on CLASS and permissions - inMemCtx: (TALLOC_CTX *) memCtx -{ - if ([event symbolicAccessClass] == iCalAccessPublic) - return [self getNo: data inMemCtx: memCtx]; - - return [self getYes: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagSensitivity: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - /* See [MS-OXCICAL] Section 2.1.3.11.20.4 */ - uint32_t v; - - v = (uint32_t) [self sensitivity]; - *data = MAPILongValue (memCtx, v); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagImportance: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - 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; -} - -- (enum mapistore_error) getPidNameKeywords: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - /* See [MS-OXCICAL] Section 2.1.3.1.1.20.3 */ - NSArray *categories; - - categories = [event categories]; - if (categories) - { - *data = [categories asMVUnicodeInMemCtx: memCtx]; - return MAPISTORE_SUCCESS; - } - else - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidTagBody: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - NSRange range; - NSString *stringValue; - NSString *trimingString = @"\r\n\n"; - - /* FIXME: there is a confusion in NGCards around "comment" and "description" */ - stringValue = [event comment]; - if ([stringValue length] > 0 - && ![stringValue isEqualToString: @"\r\n"] - && ![stringValue isEqualToString: @"\n"]) - { - /* Avoiding those trail weird characters at event description */ - range = [stringValue rangeOfString: trimingString - options: NSBackwardsSearch]; - if (range.location != NSNotFound) - { - stringValue = [stringValue substringToIndex: (NSMaxRange(range) -1)]; - } - - rc = MAPISTORE_SUCCESS; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidTagInternetCodepage: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - /* 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; -} - -- (enum mapistore_error) getPidLidRecurring: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPIBoolValue (memCtx, [event isRecurrent]); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidIsRecurring: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPIBoolValue (memCtx, - [event isRecurrent] - || ([event recurrenceId] != nil)); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidIsException: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPIBoolValue (memCtx, [event recurrenceId] != nil); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidExceptionReplaceTime: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - NSCalendarDate *dateValue; - - dateValue = [event recurrenceId]; - if (dateValue) - { - rc = MAPISTORE_SUCCESS; - - if ([event isAllDay]) - dateValue = [timeZone shiftedCalendarDateForDate: dateValue]; - *data = [dateValue asFileTimeInMemCtx: memCtx]; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidLidRecurrencePattern: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [@"No description" asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (void) _fillExceptionInfo: (struct ExceptionInfo *) exceptionInfo - andExtendedException: (struct ExtendedException *) extendedException - withException: (iCalEvent *) exceptionEvent - inMemCtx: (TALLOC_CTX *) memCtx -{ - iCalEventChanges *changes; - NSArray *changedProperties; - NSCalendarDate *dateValue; - - changes = [iCalEventChanges changesFromEvent: event toEvent: exceptionEvent]; - - memset (exceptionInfo, 0, sizeof (struct ExceptionInfo)); - memset (extendedException, 0, sizeof (struct ExtendedException)); - extendedException->ChangeHighlight.Size = sizeof (uint32_t); - - dateValue = [timeZone computedDateForDate: [exceptionEvent startDate]]; - exceptionInfo->StartDateTime = [dateValue asMinutesSince1601]; - extendedException->ChangeHighlight.Value = BIT_CH_START; - extendedException->StartDateTime = exceptionInfo->StartDateTime; - - dateValue = [timeZone computedDateForDate: [exceptionEvent endDate]]; - exceptionInfo->EndDateTime = [dateValue asMinutesSince1601]; - extendedException->ChangeHighlight.Value |= BIT_CH_END; - extendedException->EndDateTime = exceptionInfo->EndDateTime; - - dateValue = [timeZone computedDateForDate: [exceptionEvent recurrenceId]]; - exceptionInfo->OriginalStartDate = [dateValue asMinutesSince1601]; - extendedException->OriginalStartDate = exceptionInfo->OriginalStartDate; - - changedProperties = [changes updatedProperties]; - if ([changedProperties containsObject: @"summary"]) - { - extendedException->ChangeHighlight.Value |= BIT_CH_SUBJECT; - extendedException->Subject - = [[exceptionEvent summary] asUnicodeInMemCtx: memCtx]; - - exceptionInfo->OverrideFlags |= ARO_SUBJECT; - exceptionInfo->Subject.subjectMsg.msg - = (uint8_t *) extendedException->Subject; - /* FIXME: this will fail with non ascii chars */ - exceptionInfo->Subject.subjectMsg.msgLength2 = [[exceptionEvent summary] length]; - exceptionInfo->Subject.subjectMsg.msgLength = exceptionInfo->Subject.subjectMsg.msgLength2 + 1; - } - if ([changedProperties containsObject: @"location"]) - { - extendedException->ChangeHighlight.Value |= BIT_CH_LOCATION; - extendedException->Location - = [[exceptionEvent location] asUnicodeInMemCtx: memCtx]; - exceptionInfo->OverrideFlags |= ARO_LOCATION; - exceptionInfo->Location.locationMsg.msg - = (uint8_t *) extendedException->Location; - /* FIXME: this will fail with non ascii chars */ - exceptionInfo->Location.locationMsg.msgLength2 = [[exceptionEvent location] length]; - exceptionInfo->Location.locationMsg.msgLength = exceptionInfo->Location.locationMsg.msgLength2 + 1; - } - if ([event isAllDay] != [exceptionEvent isAllDay]) - { - exceptionInfo->OverrideFlags |= ARO_SUBTYPE; - exceptionInfo->SubType.sType = [exceptionEvent isAllDay]; - } -} - -// - (struct SBinary_short *) _computeAppointmentRecurInMemCtx: (TALLOC_CTX *) memCtx -- (struct Binary_r *) _computeAppointmentRecurInMemCtx: (TALLOC_CTX *) memCtx -{ - struct AppointmentRecurrencePattern *arp; - struct Binary_r *bin; - // struct SBinary_short *sBin; - NSCalendarDate *firstStartDate; - iCalRecurrenceRule *rule; - NSUInteger startMinutes; - NSArray *events, *exceptions; - iCalEvent *exceptionEvent; - NSUInteger count, max; - - rule = [[event recurrenceRules] objectAtIndex: 0]; - - firstStartDate = [event firstRecurrenceStartDate]; - if (firstStartDate) - { - arp = talloc_zero (NULL, struct AppointmentRecurrencePattern); - [rule fillRecurrencePattern: &arp->RecurrencePattern - withEvent: event - inMemCtx: arp]; - arp->ReaderVersion2 = 0x00003006; - arp->WriterVersion2 = 0x00003008; /* 0x3008 for compatibility with - ol2003 */ - - /* All day events' dates are specified in floating time - ([MS-OXCICAL] 2.1.3.1.1.20.10). The StartTimeOffset and EndTimeOffset - fields are relative to midnight of those days ([MS-OXOCAL] 2.2.1.44.5), - so no time zone adjustment is needed */ - if (![event isAllDay]) - firstStartDate = [timeZone computedDateForDate: firstStartDate]; - startMinutes = ([firstStartDate hourOfDay] * 60 - + [firstStartDate minuteOfHour]); - arp->StartTimeOffset = startMinutes; - arp->EndTimeOffset = (startMinutes - + (NSUInteger) ([event durationAsTimeInterval] - / 60)); - - events = [[event parent] events]; - exceptions - = [events subarrayWithRange: NSMakeRange (1, [events count] - 1)]; - max = [exceptions count]; - arp->ExceptionCount = max; - arp->ExceptionInfo = talloc_array (memCtx, struct ExceptionInfo, max); - arp->ExtendedException = talloc_array (memCtx, struct ExtendedException, max); - for (count = 0; count < max; count++) - { - exceptionEvent = [exceptions objectAtIndex: count]; - [self _fillExceptionInfo: arp->ExceptionInfo + count - andExtendedException: arp->ExtendedException + count - withException: exceptionEvent - inMemCtx: arp]; - } - arp->ReservedBlock1Size = 0; - arp->ReservedBlock2Size = 0; - - /* Currently ignored in property.idl: arp->ReservedBlock2Size = 0; */ - - /* convert struct to blob */ - // sBin = talloc_zero (memCtx, struct SBinary_short); - bin = set_AppointmentRecurrencePattern (memCtx, arp); - // sBin->cb = bin->cb; - // sBin->lpb = bin->lpb; - talloc_free (arp); - - // DEBUG(5, ("To client:\n")); - // NDR_PRINT_DEBUG (AppointmentRecurrencePattern, arp); - } - else - { - [self errorWithFormat: @"no first occurrence found in rule: %@", rule]; - // bin = NULL; - bin = NULL; - } - - return bin; -} - -/* exception 12345 + 123456 (exchange): - 81ad0102 (PT_BINARY): - named prop - guid: {00062002-0000-0000-c000-000000000046} - dispid: 0x00008216 - (163 bytes) - 04 30 04 30 0a 20 00 00 | \x04 0 \x04 0 \x0a \x00 \x00 - 00 00 00 00 00 00 a0 05 | \x00 \x00 \x00 \x00 \x00 \x00 \xa0 \x05 - 00 00 00 00 00 00 23 20 | \x00 \x00 \x00 \x00 \x00 \x00 # - 00 00 0a 00 00 00 00 00 | \x00 \x00 \x0a \x00 \x00 \x00 \x00 \x00 - 00 00 01 00 00 00 a0 c6 | \x00 \x00 \x01 \x00 \x00 \x00 \xa0 \xc6 - e6 0c 01 00 00 00 a0 c6 | \xe6 \x0c \x01 \x00 \x00 \x00 \xa0 \xc6 - e6 0c 00 c1 e6 0c df 80 | \xe6 \x0c \x00 \xc1 \xe6 \x0c \xdf \x80 - e9 5a 06 30 00 00 08 30 | \xe9 Z \x06 0 \x00 \x00 \x08 0 - 00 00 66 03 00 00 84 03 | \x00 \x00 f \x03 \x00 \x00 \x84 \x03 - 00 00 01 00 e8 c9 e6 0c | \x00 \x00 \x01 \x00 \xe8 \xc9 \xe6 \x0c - f6 ca e6 0c 06 ca e6 0c | \xf6 \xca \xe6 \x0c \x06 \xca \xe6 \x0c - 11 00 06 00 05 00 31 32 | \x11 \x00 \x06 \x00 \x05 \x00 1 2 - 33 34 35 07 00 06 00 31 | 3 4 5 \x07 \x00 \x06 \x00 1 - 32 33 34 35 36 00 00 00 | 2 3 4 5 6 \x00 \x00 \x00 - 00 00 00 00 00 e8 c9 e6 | \x00 \x00 \x00 \x00 \x00 \xe8 \xc9 \xe6 - 0c f6 ca e6 0c 06 ca e6 | \x0c \xf6 \xca \xe6 \x0c \x06 \xca \xe6 - 0c 05 00 31 00 32 00 33 | \x0c \x05 \x00 1 \x00 2 \x00 3 - 00 34 00 35 00 06 00 31 | \x00 4 \x00 5 \x00 \x06 \x00 1 - 00 32 00 33 00 34 00 35 | \x00 2 \x00 3 \x00 4 \x00 5 - 00 36 00 00 00 00 00 00 | \x00 6 \x00 \x00 \x00 \x00 \x00 \x00 - 00 00 00 | \x00 \x00 \x00 - -openchange: - 918b0102 (PT_BINARY): - named prop - guid: {00062002-0000-0000-c000-000000000046} - dispid: 0x00008216 - (167 bytes) - - -recurrence pattern - readerversion: 04 30 - writerversion: 04 30 - recurfrequency: 0a 20 (daily) - patterntype: 00 00 - calendartype: 00 00 - firstdatetime: 00 00 00 00 - period: a0 05 00 00 (1440 minutes) - slidingflag: 00 00 00 00 - patterntypespecific: (0 bytes) - endtype: 23 20 00 00 - occurrencecount: *00->0a 00 00 00 (meaningless since no enddate) - firstdow: 00 00 00 00 - deletedicount: 01 00 00 00 - deletedinstancedates: (1) - a0 c6 e6 0c - modifiedicount: 01 00 00 00 - modifiedinstancedates: (1) - a0 c6 e6 0c - startdate: 00 c1 e6 0c - enddate: df 80 e9 5a -ReaderVersion2: 06 30 00 00 -WriterVersion2: 08 30 00 00 -StartTimeOffset: 66 03 00 00 -EndTimeOffset: 84 03 00 00 -ExceptionCount: 01 00 -ExceptionInfos: (1) - StartDateTime: *e7->e8 *ca->c9 e6 0c - EndDateTime: *e6->f6 *cb->ca e6 0c - OriginalStartDate: *a0->06 *c6->ca e6 0c - OverrideFlags: 11 00 - SubjectLength2: 06 00 - SubjectLength: 05 00 - Subject: 31 32 33 34 35 - LocationLength2: 07 00 - LocationLength: 06 00 - Location: 31 32 33 34 35 36 -ReservedBlock1Size: 00 00 00 00 -ExtendedException: (1) - ReservedBlockEE1Size: 00 00 00 00 - StartDateTime: *e7->e8 *ca->c9 e6 0c - EndDateTime: *e6->f6 *cb->ca e6 0c - OriginalStartDate: *a0->06 *c6->ca e6 0c - WideCharSubjectLength *06->05 - WideCharSubject: 00 31 00 32 00 33 00 34 00 35 00 [2bytes sup: 00 00] - LocationLength: *07->06 - Location 00 31 00 32 00 33 00 34 00 35 00 36 00 00 - ReservedBlockEE2Size: 00 00 00 00 -ReservedBlockEE2Size: 00 00 00 00 -*/ - -- (enum mapistore_error) getPidLidAppointmentRecur: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_SUCCESS; - - if ([event isRecurrent]) - *data = [self _computeAppointmentRecurInMemCtx: memCtx]; - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidLidRecurrenceType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - iCalRecurrenceFrequency freq; - iCalRecurrenceRule *rrule; - enum RecurrenceType rectype; - - if ([event isRecurrent]) - { - rrule = [[event recurrenceRules] objectAtIndex: 0]; - freq = [rrule frequency]; - if (freq == iCalRecurrenceFrequenceDaily) - rectype = rectypeDaily; - else if (freq == iCalRecurrenceFrequenceWeekly) - rectype = rectypeWeekly; - else if (freq == iCalRecurrenceFrequenceMonthly) - rectype = rectypeMonthly; - else if (freq == iCalRecurrenceFrequenceYearly) - rectype = rectypeYearly; - else - rectype = rectypeNone; /* or "unsupported" */ - - *data = MAPILongValue (memCtx, rectype); - rc = MAPISTORE_SUCCESS; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -// - (enum mapistore_error) getPidLidGlobalObjectId: (void **) data -// inMemCtx: (TALLOC_CTX *) memCtx -// { -// static char byteArrayId[] = {0x04, 0x00, 0x00, 0x00, 0x82, 0x00, 0xE0, -// 0x00, 0x74, 0xC5, 0xB7, 0x10, 0x1A, 0x82, -// 0xE0, 0x08}; -// static char X[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -// NSMutableData *nsData; -// NSData *uidData; -// NSCalendarDate *creationTime; -// struct FILETIME *creationFileTime; -// uint32_t uidDataLength; - -// nsData = [NSMutableData dataWithCapacity: 256]; -// [nsData appendBytes: byteArrayId length: 16]; - -// /* FIXME TODO */ -// [nsData appendBytes: X length: 4]; -// /* /FIXME */ - -// creationTime = [event created]; -// if (!creationTime) -// { -// [self logWithFormat: @"" __location__ ": event has no 'CREATED' tag -> inventing one"]; -// creationTime = [event lastModified]; -// if (!creationTime) -// creationTime = [NSCalendarDate date]; -// } -// creationFileTime = [creationTime asFileTimeInMemCtx: NULL]; -// [nsData appendBytes: &creationFileTime->dwLowDateTime length: 4]; -// [nsData appendBytes: &creationFileTime->dwHighDateTime length: 4]; -// talloc_free (creationFileTime); - -// uidData = [[event uid] dataUsingEncoding: NSUTF8StringEncoding]; -// uidDataLength = [uidData length]; -// [nsData appendBytes: &uidDataLength length: 4]; -// [nsData appendData: uidData]; -// *data = [nsData asBinaryInMemCtx: memCtx]; - -// return MAPISTORE_SUCCESS; -// } - -- (void) _setInstanceDate: (struct GlobalObjectId *) newGlobalId - fromDate: (NSCalendarDate *) instanceDate; -{ - uint16_t year; - NSCalendarDate *dateValue; - - if (instanceDate) - { - dateValue = [timeZone computedDateForDate: instanceDate]; - year = [dateValue yearOfCommonEra]; - newGlobalId->YH = year >> 8; - newGlobalId->YL = year & 0xff; - newGlobalId->Month = [dateValue monthOfYear]; - newGlobalId->D = [dateValue dayOfMonth]; - } -} - -/* note: returns a retained object */ -- (NSData *) _objectIdAsNSData: (const struct GlobalObjectId *) newGlobalId -{ - NSData *nsData; - TALLOC_CTX *localMemCtx; - struct ndr_push *ndr; - - localMemCtx = talloc_zero (NULL, TALLOC_CTX); - ndr = ndr_push_init_ctx (localMemCtx); - ndr_push_GlobalObjectId (ndr, NDR_SCALARS, newGlobalId); - nsData = [[NSData alloc] initWithBytes: ndr->data - length: ndr->offset]; - talloc_free (localMemCtx); - - return nsData; -} - -- (void) _computeGlobalObjectIds -{ - static NSString *prefix = @"040000008200e00074c5b7101a82e008"; - static uint8_t dataPrefix[] = { 0x76, 0x43, 0x61, 0x6c, 0x2d, 0x55, 0x69, - 0x64, 0x01, 0x00, 0x00, 0x00 }; - NSString *uid; - const char *uidAsUTF8; - NSUInteger uidLength; - NSData *encodedGlobalIdData; - struct Binary_r *encodedGlobalIdBinary; - struct GlobalObjectId *encodedGlobalId; - struct GlobalObjectId newGlobalId; - uint16_t year; - NSData *binPrefix; - TALLOC_CTX *localMemCtx; - - localMemCtx = talloc_zero (NULL, TALLOC_CTX); - - memset (&newGlobalId, 0, sizeof (struct GlobalObjectId)); - - uid = [event uid]; - uidLength = [uid length]; - if (uidLength >= 82 && (uidLength % 2) == 0 && [uid hasPrefix: prefix] - && [[uid stringByTrimmingCharactersInSet: hexCharacterSet] length] == 0) - { - encodedGlobalIdData = [uid convertHexStringToBytes]; - if (encodedGlobalIdData) - { - encodedGlobalIdBinary - = [encodedGlobalIdData asBinaryInMemCtx: localMemCtx]; - encodedGlobalId = get_GlobalObjectId (localMemCtx, - encodedGlobalIdBinary); - if (encodedGlobalId) - { - memcpy (newGlobalId.ByteArrayID, - encodedGlobalId->ByteArrayID, - 16); - year = ((uint16_t) encodedGlobalId->YH << 8) | encodedGlobalId->YL; - if (year >= 1601 && year <= 4500 - && encodedGlobalId->Month > 0 && encodedGlobalId->Month < 13 - && encodedGlobalId->D > 0 && encodedGlobalId->D < 31) - { - newGlobalId.YH = encodedGlobalId->YH; - newGlobalId.YL = encodedGlobalId->YL; - newGlobalId.Month = encodedGlobalId->Month; - newGlobalId.D = encodedGlobalId->D; - } - else - [self _setInstanceDate: &newGlobalId - fromDate: [event recurrenceId]]; - newGlobalId.CreationTime = encodedGlobalId->CreationTime; - memcpy (newGlobalId.X, encodedGlobalId->X, 8); - newGlobalId.Size = encodedGlobalId->Size; - newGlobalId.Data = encodedGlobalId->Data; - } - else - abort (); - } - else - abort (); - } - else - { - binPrefix = [prefix convertHexStringToBytes]; - [binPrefix getBytes: &newGlobalId.ByteArrayID]; - [self _setInstanceDate: &newGlobalId - fromDate: [event recurrenceId]]; - uidAsUTF8 = [uid UTF8String]; - newGlobalId.Size = 0x0c + strlen (uidAsUTF8); - newGlobalId.Data = talloc_array (localMemCtx, uint8_t, - newGlobalId.Size); - memcpy (newGlobalId.Data, dataPrefix, 0x0c); - memcpy (newGlobalId.Data + 0x0c, uidAsUTF8, newGlobalId.Size - 0x0c); - } - - globalObjectId = [self _objectIdAsNSData: &newGlobalId]; - - newGlobalId.YH = 0; - newGlobalId.YL = 0; - newGlobalId.Month = 0; - newGlobalId.D = 0; - cleanGlobalObjectId = [self _objectIdAsNSData: &newGlobalId]; - - talloc_free (localMemCtx); -} - -- (enum mapistore_error) getPidLidGlobalObjectId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_SUCCESS; - - if (!globalObjectId) - [self _computeGlobalObjectIds]; - - if (globalObjectId) - *data = [globalObjectId asBinaryInMemCtx: memCtx]; - else - abort (); - - return rc; -} - -- (enum mapistore_error) getPidLidCleanGlobalObjectId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_SUCCESS; - - if (!cleanGlobalObjectId) - [self _computeGlobalObjectIds]; - - if (cleanGlobalObjectId) - *data = [cleanGlobalObjectId asBinaryInMemCtx: memCtx]; - else - abort (); - - return rc; -} - -- (enum mapistore_error) getPidLidAppointmentReplyTime: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - /* We always return LAST-MODIFIED, which is a hack, but one that works - because: the user is either (NOT recipient OR (is recipient AND its - status is N/A), where this value should not be taken into account by the - client OR the user is recipient and its status is defined, where this - value is thus correct because the recipient status is the only property - that can be changed. */ - enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND; - NSCalendarDate *lastModified; - - lastModified = [event lastModified]; - if (lastModified) - { - *data = [lastModified asFileTimeInMemCtx: memCtx]; - rc = MAPISTORE_SUCCESS; - } - - return rc; -} - -/* reminders */ -- (void) _setupAlarm -{ - NSArray *alarms; - NSUInteger count, max; - iCalAlarm *currentAlarm; - NSString *action, *webstatus; - - alarms = [event alarms]; - max = [alarms count]; - for (count = 0; !alarm && count < max; count++) - { - currentAlarm = [alarms objectAtIndex: count]; - - // Only handle 'display' alarms - action = [currentAlarm action]; - if ([action caseInsensitiveCompare: @"display"] != NSOrderedSame) - continue; - - // Ignore alarms already triggered - webstatus = [[currentAlarm trigger] value: 0 ofAttribute: @"x-webstatus"]; - if ([webstatus caseInsensitiveCompare: @"triggered"] == NSOrderedSame) - continue; - - ASSIGN (alarm, currentAlarm); - } - - alarmSet = YES; -} - -- (enum mapistore_error) getPidLidReminderSet: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!alarmSet) - [self _setupAlarm]; - - *data = MAPIBoolValue (memCtx, (alarm != nil)); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidReminderTime: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!alarmSet) - [self _setupAlarm]; - - return (alarm - ? [self getPidTagStartDate: data inMemCtx: memCtx] - : MAPISTORE_ERR_NOT_FOUND); -} - -- (enum mapistore_error) getPidLidReminderDelta: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND; - iCalTrigger *trigger; - NSCalendarDate *startDate, *relationDate, *alarmDate; - NSTimeInterval interval; - NSString *relation; - - if (!alarmSet) - [self _setupAlarm]; - - if (alarm) - { - trigger = [alarm trigger]; - if ([[trigger valueType] caseInsensitiveCompare: @"DURATION"] == NSOrderedSame) - { - startDate = [event startDate]; - relation = [[trigger relationType] lowercaseString]; - interval = [[trigger flattenedValuesForKey: @""] - durationAsTimeInterval]; - if ([relation isEqualToString: @"end"]) - relationDate = [event endDate]; - else - relationDate = startDate; - - // Compute the next alarm date with respect to the reference date - if (relationDate) - { - alarmDate = [relationDate addTimeInterval: interval]; - interval = [startDate timeIntervalSinceDate: alarmDate]; - *data = MAPILongValue (memCtx, (int) (interval / 60)); - rc = MAPISTORE_SUCCESS; - } - } - } - - return rc; -} - -- (enum mapistore_error) getPidLidReminderSignalTime: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_SUCCESS; - NSCalendarDate *alarmDate; - - if (!alarmSet) - [self _setupAlarm]; - - if (alarm) - { - alarmDate = [alarm nextAlarmDate]; - *data = [alarmDate asFileTimeInMemCtx: memCtx]; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidLidReminderOverride: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_SUCCESS; - - if (!alarmSet) - [self _setupAlarm]; - - if (alarm) - *data = MAPIBoolValue (memCtx, YES); - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidLidReminderPlaySound: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_SUCCESS; - - if (!alarmSet) - [self _setupAlarm]; - - if (alarm) - *data = MAPIBoolValue (memCtx, YES); - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidLidReminderFileParameter: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - // if (!alarmSet) - // [self _setupAlarm]; - - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidLidReminderType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidLidTimeZoneDescription: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - NSString *tzid; - - tzid = [timeZone tzId]; - if ([tzid length] > 0) - { - *data = [tzid asUnicodeInMemCtx: memCtx]; - rc = MAPISTORE_SUCCESS; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidLidTimeZoneStruct: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - - *data = [timeZone asTimeZoneStructInMemCtx: memCtx]; - rc = MAPISTORE_SUCCESS; - - return rc; -} - -- (enum mapistore_error) getPidLidAppointmentTimeZoneDefinitionStartDisplay: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - - /* [MS-OXOCAL] 3.1.5.5.1: This property is used in floating (all-day) events, - specified in floating time, to convert the start date from UTC to the user's - time zone */ - if ([event isAllDay] || [event isRecurrent]) - { - /* [MS-OXOCAL] 2.2.1.42: This property can only have the E flag set in the - TimeZoneDefinition struct */ - *data = [timeZone asZoneTimeDefinitionWithFlags: TZRULE_FLAG_EFFECTIVE_TZREG - inMemCtx: memCtx]; - rc = MAPISTORE_SUCCESS; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidLidAppointmentTimeZoneDefinitionEndDisplay: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidLidAppointmentTimeZoneDefinitionStartDisplay: data - inMemCtx: memCtx]; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreAttachment.h b/Attic/OpenChange/MAPIStoreAttachment.h deleted file mode 100644 index 24ba32c43..000000000 --- a/Attic/OpenChange/MAPIStoreAttachment.h +++ /dev/null @@ -1,59 +0,0 @@ -/* MAPIStoreAttachment.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTOREATTACHMENT_H -#define MAPISTOREATTACHMENT_H - -#import "MAPIStoreObject.h" - -@class NSData; -@class MAPIStoreEmbeddedMessage; - -@interface MAPIStoreAttachment : MAPIStoreObject -{ - uint32_t aid; -} - -- (void) setAID: (uint32_t) newAID; -- (uint32_t) AID; - -- (enum mapistore_error) openEmbeddedMessage: (MAPIStoreEmbeddedMessage **) messagePtr - withMID: (uint64_t *) mid - withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) createEmbeddedMessage: (MAPIStoreEmbeddedMessage **) messagePtr - withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr - inMemCtx: (TALLOC_CTX *) memCtx; - -/* helpers */ -- (NSData *) mimeAttachTag; - -/* move & copy operations */ -- (void) copyToAttachment: (MAPIStoreAttachment *) newAttachment inMemCtx: (TALLOC_CTX *) memCtx; - -/* subclasses */ -- (MAPIStoreEmbeddedMessage *) openEmbeddedMessage; -- (MAPIStoreEmbeddedMessage *) createEmbeddedMessage; - -@end - -#endif /* MAPISTOREATTACHMENT_H */ diff --git a/Attic/OpenChange/MAPIStoreAttachment.m b/Attic/OpenChange/MAPIStoreAttachment.m deleted file mode 100644 index 754436d7e..000000000 --- a/Attic/OpenChange/MAPIStoreAttachment.m +++ /dev/null @@ -1,194 +0,0 @@ -/* MAPIStoreAttachment.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import - -#import "MAPIStoreAttachment.h" -#import "MAPIStoreEmbeddedMessage.h" -#import "MAPIStoreContext.h" -#import "MAPIStoreMapping.h" -#import "MAPIStoreMessage.h" -#import "MAPIStoreTypes.h" -#import "NSObject+MAPIStore.h" - -#undef DEBUG -#include -#include -#include -#include - -@implementation MAPIStoreAttachment - -- (void) setAID: (uint32_t) newAID -{ - aid = newAID; -} - -- (uint32_t) AID -{ - return aid; -} - -- (NSString *) nameInContainer -{ - return [NSString stringWithFormat: @"%d", aid]; -} - -- (NSData *) mimeAttachTag -{ - static NSData *mimeAttachTag = nil; - char tagBytes[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x14, 0x03, 0x0a, 0x04}; - - if (!mimeAttachTag) - { - mimeAttachTag = [NSData dataWithBytes: tagBytes length: 9]; - [mimeAttachTag retain]; - } - - return mimeAttachTag; -} - -- (enum mapistore_error) getPidTagMid: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongLongValue (memCtx, [container objectId]); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAttachNumber: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, aid); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagRenderingPosition: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, 0xffffffff); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAccessLevel: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getLongZero: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) openEmbeddedMessage: (MAPIStoreEmbeddedMessage **) messagePtr - withMID: (uint64_t *) mid - withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr - inMemCtx: (TALLOC_CTX *) memCtx -{ - MAPIStoreEmbeddedMessage *attMessage; - struct mapistore_message *mapistoreMsg; - - mapistoreMsg = talloc_zero (memCtx, struct mapistore_message); - - attMessage = [self openEmbeddedMessage]; - if (attMessage) - { - *mid = [attMessage objectId]; - *messagePtr = attMessage; - *mapistoreMsgPtr = mapistoreMsg; - } - - return (attMessage ? MAPISTORE_SUCCESS : MAPISTORE_ERROR); -} - -- (enum mapistore_error) createEmbeddedMessage: (MAPIStoreEmbeddedMessage **) messagePtr - withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr - inMemCtx: (TALLOC_CTX *) memCtx -{ - MAPIStoreEmbeddedMessage *attMessage; - struct mapistore_message *mapistoreMsg; - - mapistoreMsg = talloc_zero (memCtx, struct mapistore_message); - attMessage = [self createEmbeddedMessage]; - if (attMessage) - { - *messagePtr = attMessage; - *mapistoreMsgPtr = mapistoreMsg; - } - - return (attMessage ? MAPISTORE_SUCCESS : MAPISTORE_ERROR); -} - -- (NSDate *) creationTime -{ - return [container creationTime]; -} - -- (NSDate *) lastModificationTime -{ - return [container lastModificationTime]; -} - -- (uint64_t) objectVersion -{ - /* attachments have no version number */ - return ULLONG_MAX; -} - -- (void) copyToAttachment: (MAPIStoreAttachment *) newAttachment inMemCtx: (TALLOC_CTX *) memCtx -{ - void *attachMethod; - enum mapistore_error error; - MAPIStoreEmbeddedMessage *embeddedMessage, *newEmbeddedMessage; - - [self copyPropertiesToObject: newAttachment inMemCtx: memCtx]; - - attachMethod = NULL; - error = [self getProperty: &attachMethod - withTag: PidTagAttachMethod - inMemCtx: NULL]; - if (error == MAPISTORE_SUCCESS && attachMethod) - { - if (*(uint32_t *) attachMethod == afEmbeddedMessage) - { - embeddedMessage = [self openEmbeddedMessage]; - newEmbeddedMessage = [newAttachment createEmbeddedMessage]; - [embeddedMessage copyToMessage: newEmbeddedMessage inMemCtx: memCtx]; - } - talloc_free (attachMethod); - } -} - -/* subclasses */ -- (MAPIStoreEmbeddedMessage *) openEmbeddedMessage -{ - // [self subclassResponsibility: _cmd]; - - return nil; -} - -- (MAPIStoreEmbeddedMessage *) createEmbeddedMessage -{ - [self subclassResponsibility: _cmd]; - - return nil; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreAttachmentTable.h b/Attic/OpenChange/MAPIStoreAttachmentTable.h deleted file mode 100644 index d066a7b8c..000000000 --- a/Attic/OpenChange/MAPIStoreAttachmentTable.h +++ /dev/null @@ -1,31 +0,0 @@ -/* MAPIStoreAttachmentTable.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTOREATTACHMENTTABLE_H -#define MAPISTOREATTACHMENTTABLE_H - -#import "MAPIStoreTable.h" - -@interface MAPIStoreAttachmentTable : MAPIStoreTable -@end - -#endif /* MAPISTOREATTACHMENTTABLE_H */ diff --git a/Attic/OpenChange/MAPIStoreAttachmentTable.m b/Attic/OpenChange/MAPIStoreAttachmentTable.m deleted file mode 100644 index 61c82dd1b..000000000 --- a/Attic/OpenChange/MAPIStoreAttachmentTable.m +++ /dev/null @@ -1,73 +0,0 @@ -/* MAPIStoreAttachmentTable.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import - -#import "MAPIStoreMessage.h" - -#import "MAPIStoreAttachmentTable.h" - -@implementation MAPIStoreAttachmentTable - -- (NSArray *) childKeys -{ - if (!childKeys) - { - childKeys = [(MAPIStoreMessage *) - container attachmentKeysMatchingQualifier: nil - andSortOrderings: sortOrderings]; - [childKeys retain]; - } - - return childKeys; -} - -- (NSArray *) restrictedChildKeys -{ - NSArray *keys; - - if (!restrictedChildKeys) - { - if (restrictionState != MAPIRestrictionStateAlwaysTrue) - { - if (restrictionState == MAPIRestrictionStateNeedsEval) - keys = [(MAPIStoreMessage *) - container attachmentKeysMatchingQualifier: restriction - andSortOrderings: sortOrderings]; - else - keys = [NSArray array]; - } - else - keys = [self childKeys]; - - ASSIGN (restrictedChildKeys, keys); - } - - return restrictedChildKeys; -} - -- (id) lookupChild: (NSString *) childKey -{ - return [(MAPIStoreMessage *) container lookupAttachment: childKey]; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreAuthenticator.h b/Attic/OpenChange/MAPIStoreAuthenticator.h deleted file mode 100644 index ce88a60be..000000000 --- a/Attic/OpenChange/MAPIStoreAuthenticator.h +++ /dev/null @@ -1,54 +0,0 @@ - -/* MAPIStoreAuthenticator.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 MAPISTOREAUTHENTICATOR_H -#define MAPISTOREAUTHENTICATOR_H - -#import - -@class NSString; -@class NSURL; - -@class WOContext; - -@interface MAPIStoreAuthenticator : NSObject -{ - NSString *username; - NSString *password; -} - -- (void) setUsername: (NSString *) newUsername; -- (NSString *) username; - -- (void) setPassword: (NSString *) newPassword; - -- (NSString *) imapPasswordInContext: (WOContext *) context - forURL: (NSURL *) server - forceRenew: (BOOL) renew; - -- (NSString *) passwordInContext: (WOContext *) context; - - -@end - -#endif /* MAPISTOREAUTHENTICATOR_H */ diff --git a/Attic/OpenChange/MAPIStoreAuthenticator.m b/Attic/OpenChange/MAPIStoreAuthenticator.m deleted file mode 100644 index 41e4ed081..000000000 --- a/Attic/OpenChange/MAPIStoreAuthenticator.m +++ /dev/null @@ -1,79 +0,0 @@ -/* MAPIStoreAuthenticator.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -#import -#import - -#import -#import - -#import "MAPIStoreAuthenticator.h" - -@implementation MAPIStoreAuthenticator - -- (void) dealloc -{ - [username release]; - [password release]; - [super dealloc]; -} - -- (void) setUsername: (NSString *) newUsername -{ - ASSIGN (username, newUsername); -} - -- (NSString *) username -{ - return username; -} - -- (void) setPassword: (NSString *) newPassword -{ - ASSIGN (password, newPassword); -} - -- (SOGoUser *) userInContext: (WOContext *)_ctx -{ - return [SOGoUser userWithLogin: username - roles: [NSArray arrayWithObject: SoRole_Authenticated]]; -} - -- (NSString *) imapPasswordInContext: (WOContext *) context - forURL: (NSURL *) server - forceRenew: (BOOL) renew -{ - NSString *imapPassword; - - if (renew) - imapPassword = nil; - else - imapPassword = password; - - return imapPassword; -} - -- (NSString *) passwordInContext: (WOContext *) context -{ - return password; -} -@end diff --git a/Attic/OpenChange/MAPIStoreCalTaskFolder.h b/Attic/OpenChange/MAPIStoreCalTaskFolder.h deleted file mode 100644 index 92b75e463..000000000 --- a/Attic/OpenChange/MAPIStoreCalTaskFolder.h +++ /dev/null @@ -1,35 +0,0 @@ -/* MAPIStoreCalTaskFolder.h - this file is part of SOGo - * - * Copyright (C) 2016 Enrique J. Hernandez - * - * Author: Enrique J. Hernandez - * - * 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. - */ - -#ifndef MAPISTORECALTASKFOLDER_H -#define MAPISTORECALTASKFOLDER_H - -#import "MAPIStoreGCSFolder.h" - -/* This class is intended to share code between Calendar and Tasks as - of nowadays share the table */ - -@interface MAPIStoreCalTaskFolder : MAPIStoreGCSFolder - -@end - -#endif /* MAPISTORECALTASKFOLDER_H */ diff --git a/Attic/OpenChange/MAPIStoreCalTaskFolder.m b/Attic/OpenChange/MAPIStoreCalTaskFolder.m deleted file mode 100644 index 8876c77e5..000000000 --- a/Attic/OpenChange/MAPIStoreCalTaskFolder.m +++ /dev/null @@ -1,101 +0,0 @@ -/* MAPIStoreCalTaskFolder.m - this file is part of SOGo - * - * Copyright (C) 2016 Enrique J. Hernandez - * - * Author: Enrique J. Hernandez - * - * 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. - */ -#import -#import -#import -#import - -#import - -#import "MAPIStoreCalTaskFolder.h" - -@implementation MAPIStoreCalTaskFolder - -- (NSArray *) expandRoles: (NSArray *) roles -{ - static NSDictionary *rolesMap = nil; - NSArray *subRoles; - NSMutableSet *expandedRoles; - NSString *role, *subRole; - NSUInteger i, max, j; - - if (!rolesMap) - { - /* Build the map of array permissions */ - rolesMap = [[NSDictionary alloc] initWithObjects: [NSArray arrayWithObjects: - [NSArray arrayWithObjects: SOGoCalendarRole_PublicDAndTViewer, - SOGoCalendarRole_PublicViewer, - SOGoCalendarRole_PublicResponder, - SOGoCalendarRole_PublicModifier, nil], - [NSArray arrayWithObjects: SOGoCalendarRole_ConfidentialDAndTViewer, - SOGoCalendarRole_ConfidentialViewer, - SOGoCalendarRole_ConfidentialResponder, - SOGoCalendarRole_ConfidentialModifier, nil], - [NSArray arrayWithObjects: SOGoCalendarRole_PrivateDAndTViewer, - SOGoCalendarRole_PrivateViewer, - SOGoCalendarRole_PrivateResponder, - SOGoCalendarRole_PrivateModifier, nil], - [NSArray arrayWithObjects: SOGoCalendarRole_ComponentDAndTViewer, - SOGoCalendarRole_ComponentViewer, - SOGoCalendarRole_ComponentResponder, - SOGoCalendarRole_ComponentModifier, nil], - nil] - forKeys: [NSArray arrayWithObjects: @"Public", @"Confidential", @"Private", - @"Component", nil]]; - } - - max = [roles count]; - expandedRoles = [NSMutableSet set]; - for (i = 0; i < max; i++) - { - role = [roles objectAtIndex: i]; - subRoles = nil; - if ([role hasPrefix: @"Public"]) - subRoles = [rolesMap objectForKey: @"Public"]; - else if ([role hasPrefix: @"Confidential"]) - subRoles = [rolesMap objectForKey: @"Confidential"]; - else if ([role hasPrefix: @"Private"]) - subRoles = [rolesMap objectForKey: @"Private"]; - else if ([role hasPrefix: @"Component"]) - subRoles = [rolesMap objectForKey: @"Component"]; - - if (subRoles) - { - for (j = 0; j < [subRoles count]; j++) - { - subRole = [subRoles objectAtIndex: j]; - [expandedRoles addObject: subRole]; - - if ([subRole isEqualToString: role]) - break; - } - } - else - { - [expandedRoles addObject: role]; - } - } - - return [expandedRoles allObjects]; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreCalTaskMessage.h b/Attic/OpenChange/MAPIStoreCalTaskMessage.h deleted file mode 100644 index 8e284b414..000000000 --- a/Attic/OpenChange/MAPIStoreCalTaskMessage.h +++ /dev/null @@ -1,40 +0,0 @@ -/* MAPIStoreCalTaskMessage.h - this file is part of SOGo - * - * Copyright (C) 2016 Enrique J. Hernandez - * - * Author: Enrique J. Hernandez - * - * 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. - */ - -#ifndef MAPISTORECALTASKMESSAGE_H -#define MAPISTORECALTASKMESSAGE_H - -#import "MAPIStoreGCSMessage.h" - -/* This class is intended to share common logic for Calendar and Tasks - as of today they are stored in the same table. This is relevant for - permissions */ -@interface MAPIStoreCalTaskMessage : MAPIStoreGCSMessage -{ -} - -/* Get the sensitivity (access class) from a message */ -- (NSUInteger) sensitivity; - -@end - -#endif /* MAPISTORECALTASKMESSAGE_H */ diff --git a/Attic/OpenChange/MAPIStoreCalTaskMessage.m b/Attic/OpenChange/MAPIStoreCalTaskMessage.m deleted file mode 100644 index b88e9c2ef..000000000 --- a/Attic/OpenChange/MAPIStoreCalTaskMessage.m +++ /dev/null @@ -1,107 +0,0 @@ -/* MAPIStoreCalTaskMessage.h - this file is part of SOGo - * - * Copyright (C) 2016 Enrique J. Hernandez - * - * Author: Enrique J. Hernandez - * - * 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 - -#import - -#import - -#import "MAPIStoreFolder.h" -#import "MAPIStoreCalTaskMessage.h" - -@implementation MAPIStoreCalTaskMessage - -/* It must be implemented by subclasses */ -- (NSUInteger) sensitivity -{ - [self subclassResponsibility: _cmd]; - - return 0; -} - -- (NSArray *) expandRoles: (NSArray *) roles -{ - return [container expandRoles: roles]; -} - -- (BOOL) subscriberCanModifyMessage -{ - BOOL rc; - NSArray *roles; - - roles = [self activeUserRoles]; - - if (isNew) - rc = [roles containsObject: SOGoRole_ObjectCreator]; - else - rc = ([roles containsObject: SOGoCalendarRole_ComponentModifier] - || [roles containsObject: SOGoCalendarRole_ComponentResponder]); - - /* Check if the message is owned and it has permission to edit it */ - if (!rc && [roles containsObject: MAPIStoreRightEditOwn]) - { - NSString *currentUser; - - currentUser = [[container context] activeUser]; - rc = [currentUser isEqual: [self ownerUser]]; - } - - if (!rc) - { - NSUInteger sensitivity; - - /* Get sensitivity of the message to check if the user can - modify the message */ - sensitivity = [self sensitivity]; - /* FIXME: Use OpenChange constant names */ - switch (sensitivity) - { - case 0: /* PUBLIC */ - rc = [roles containsObject: SOGoCalendarRole_PublicModifier] - || [roles containsObject: SOGoCalendarRole_PublicResponder]; - break; - case 1: /* PERSONAL */ - case 2: /* PRIVATE */ - rc = [roles containsObject: SOGoCalendarRole_PrivateModifier] - || [roles containsObject: SOGoCalendarRole_PrivateResponder]; - break; - case 3: /* CONFIDENTIAL */ - rc = [roles containsObject: SOGoCalendarRole_ConfidentialModifier] - || [roles containsObject: SOGoCalendarRole_ConfidentialResponder]; - } - } - return rc; -} - -- (BOOL) subscriberCanReadMessage -{ - NSArray *roles; - - roles = [self activeUserRoles]; - - return ([roles containsObject: SOGoCalendarRole_ComponentViewer] - || [roles containsObject: SOGoCalendarRole_ComponentDAndTViewer] - || [self subscriberCanModifyMessage]); -} - -@end diff --git a/Attic/OpenChange/MAPIStoreCalendarAttachment.h b/Attic/OpenChange/MAPIStoreCalendarAttachment.h deleted file mode 100644 index b0a35d6b2..000000000 --- a/Attic/OpenChange/MAPIStoreCalendarAttachment.h +++ /dev/null @@ -1,43 +0,0 @@ -/* MAPIStoreCalendarAttachment.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTORECALENDARATTACHMENT_H -#define MAPISTORECALENDARATTACHMENT_H - -#import "MAPIStoreAttachment.h" - -@class NSTimeZone; - -@class iCalEvent; - -@interface MAPIStoreCalendarAttachment : MAPIStoreAttachment -{ - iCalEvent *event; - NSTimeZone *timeZone; -} - -- (void) setEvent: (iCalEvent *) newEvent; -- (iCalEvent *) event; - -@end - -#endif /* MAPISTORECALENDARATTACHMENT_H */ diff --git a/Attic/OpenChange/MAPIStoreCalendarAttachment.m b/Attic/OpenChange/MAPIStoreCalendarAttachment.m deleted file mode 100644 index b2044b602..000000000 --- a/Attic/OpenChange/MAPIStoreCalendarAttachment.m +++ /dev/null @@ -1,255 +0,0 @@ -/* MAPIStoreCalendarAttachment.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import -#import -#import -#import - -#import -#import - -#import "iCalEvent+MAPIStore.h" -#import "MAPIStoreCalendarEmbeddedMessage.h" -#import "MAPIStoreTypes.h" -#import "MAPIStoreUserContext.h" -#import "NSDate+MAPIStore.h" -#import "NSData+MAPIStore.h" -#import "NSObject+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreCalendarAttachment.h" - -#undef DEBUG -#include -#include -#include -#include - -@implementation MAPIStoreCalendarAttachment - -- (id) init -{ - if ((self = [super init])) - { - event = nil; - timeZone = nil; - } - - return self; -} - -- (id) initInContainer: (MAPIStoreObject *) newContainer -{ - MAPIStoreUserContext *userContext; - - if ((self = [super initInContainer: newContainer])) - { - userContext = [newContainer userContext]; - ASSIGN (timeZone, [userContext timeZone]); - } - - return self; -} - -- (void) dealloc -{ - [event release]; - [timeZone release]; - [super dealloc]; -} - -- (void) setEvent: (iCalEvent *) newEvent -{ - ASSIGN (event, newEvent); -} - -- (iCalEvent *) event -{ - return event; -} - -- (NSString *) nameInContainer -{ - return [[event uniqueChildWithTag: @"recurrence-id"] - flattenedValuesForKey: @""]; -} - -- (enum mapistore_error) getPidTagAttachmentHidden: (void **) data - inMemCtx: (TALLOC_CTX *) localMemCtx -{ - return [self getYes: data inMemCtx: localMemCtx]; -} - -- (enum mapistore_error) getPidTagAttachmentFlags: (void **) data - inMemCtx: (TALLOC_CTX *) localMemCtx -{ - *data = MAPILongValue (localMemCtx, 0x00000002); /* afException */ - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAttachmentLinkId: (void **) data - inMemCtx: (TALLOC_CTX *) localMemCtx -{ - return [self getLongZero: data inMemCtx: localMemCtx]; -} - -- (enum mapistore_error) getPidTagAttachFlags: (void **) data - inMemCtx: (TALLOC_CTX *) localMemCtx -{ - return [self getLongZero: data inMemCtx: localMemCtx]; -} - -- (enum mapistore_error) getPidTagAttachMethod: (void **) data - inMemCtx: (TALLOC_CTX *) localMemCtx -{ - *data = MAPILongValue (localMemCtx, afEmbeddedMessage); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAttachEncoding: (void **) data - inMemCtx: (TALLOC_CTX *) localMemCtx -{ - *data = [[NSData data] asBinaryInMemCtx: localMemCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagDisplayName: (void **) data - inMemCtx: (TALLOC_CTX *) localMemCtx -{ - *data = [@"Untitled" asUnicodeInMemCtx: localMemCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAttachmentContactPhoto: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getNo: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagExceptionReplaceTime: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - NSCalendarDate *dateValue; - NSInteger offset; - - dateValue = [event recurrenceId]; - if (dateValue) - { - rc = MAPISTORE_SUCCESS; - - if ([event isAllDay]) - { - offset = -[timeZone secondsFromGMTForDate: dateValue]; - dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: offset]; - } - [dateValue setTimeZone: utcTZ]; - *data = [dateValue asFileTimeInMemCtx: memCtx]; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidTagExceptionStartTime: (void **) data - inMemCtx: (TALLOC_CTX *) localMemCtx -{ - enum mapistore_error rc; - NSCalendarDate *dateValue; - NSInteger offset; - - if ([event recurrenceId] != nil) - { - dateValue = [event startDate]; - [dateValue setTimeZone: timeZone]; - if (![event isAllDay]) - { - offset = [timeZone secondsFromGMTForDate: dateValue]; - dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: offset]; - } - *data = [dateValue asFileTimeInMemCtx: localMemCtx]; - rc = MAPISTORE_SUCCESS; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidTagExceptionEndTime: (void **) data - inMemCtx: (TALLOC_CTX *) localMemCtx -{ - enum mapistore_error rc; - NSCalendarDate *dateValue; - NSInteger offset; - - if ([event recurrenceId] != nil) - { - dateValue = [event startDate]; - [dateValue setTimeZone: timeZone]; - offset = [event durationAsTimeInterval]; - if (![event isAllDay]) - offset += [timeZone secondsFromGMTForDate: dateValue]; - dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: offset]; - *data = [dateValue asFileTimeInMemCtx: localMemCtx]; - rc = MAPISTORE_SUCCESS; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -/* subclasses */ -- (MAPIStoreCalendarEmbeddedMessage *) openEmbeddedMessage -{ - MAPIStoreCalendarEmbeddedMessage *msg; - - msg = [MAPIStoreCalendarEmbeddedMessage - mapiStoreObjectInContainer: self]; - - return msg; -} - -- (MAPIStoreCalendarEmbeddedMessage *) createEmbeddedMessage -{ - MAPIStoreCalendarEmbeddedMessage *msg; - - msg = [self openEmbeddedMessage]; - [msg setIsNew: YES]; - - return msg; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreCalendarContext.h b/Attic/OpenChange/MAPIStoreCalendarContext.h deleted file mode 100644 index e6f804805..000000000 --- a/Attic/OpenChange/MAPIStoreCalendarContext.h +++ /dev/null @@ -1,32 +0,0 @@ -/* MAPIStoreCalendarContext.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 MAPISTORECALENDARCONTEXT_H -#define MAPISTORECALENDARCONTEXT_H - -#import "MAPIStoreGCSBaseContext.h" - -@interface MAPIStoreCalendarContext : MAPIStoreGCSBaseContext - -@end - -#endif /* MAPISTORECALENDARCONTEXT_H */ diff --git a/Attic/OpenChange/MAPIStoreCalendarContext.m b/Attic/OpenChange/MAPIStoreCalendarContext.m deleted file mode 100644 index 035741afb..000000000 --- a/Attic/OpenChange/MAPIStoreCalendarContext.m +++ /dev/null @@ -1,64 +0,0 @@ -/* MAPIStoreCalendarContext.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -#import -#import - -#import "MAPIStoreMapping.h" -#import "MAPIStoreCalendarFolder.h" -#import "MAPIStoreUserContext.h" - -#import "MAPIStoreCalendarContext.h" - -#undef DEBUG -#include - -static Class MAPIStoreCalendarFolderK; - -@implementation MAPIStoreCalendarContext - -+ (void) initialize -{ - MAPIStoreCalendarFolderK = [MAPIStoreCalendarFolder class]; -} - -+ (NSString *) MAPIModuleName -{ - return @"calendar"; -} - -+ (enum mapistore_context_role) MAPIContextRole -{ - return MAPISTORE_CALENDAR_ROLE; -} - -- (Class) MAPIStoreFolderClass -{ - return MAPIStoreCalendarFolderK; -} - -+ (NSString *) folderNameSuffix -{ - return @"c"; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreCalendarEmbeddedMessage.h b/Attic/OpenChange/MAPIStoreCalendarEmbeddedMessage.h deleted file mode 100644 index 3e27c575c..000000000 --- a/Attic/OpenChange/MAPIStoreCalendarEmbeddedMessage.h +++ /dev/null @@ -1,34 +0,0 @@ -/* MAPIStoreCalendarEmbeddedMessage.h - this file is part of SOGo - * - * Copyright (C) 2012 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. - */ - -#ifndef MAPISTORECALENDAREMBEDDEDMESSAGE_H -#define MAPISTORECALENDAREMBEDDEDMESSAGE_H - -#import "MAPIStoreEmbeddedMessage.h" - -@class MAPIStoreAppointmentWrapper; - -@interface MAPIStoreCalendarEmbeddedMessage : MAPIStoreEmbeddedMessage - -@end - -#endif /* MAPISTORECALENDAREMBEDDEDMESSAGE_H */ diff --git a/Attic/OpenChange/MAPIStoreCalendarEmbeddedMessage.m b/Attic/OpenChange/MAPIStoreCalendarEmbeddedMessage.m deleted file mode 100644 index 02a776949..000000000 --- a/Attic/OpenChange/MAPIStoreCalendarEmbeddedMessage.m +++ /dev/null @@ -1,215 +0,0 @@ -/* MAPIStoreCalendarEmbeddedMessage.m - this file is part of SOGo - * - * Copyright (C) 2012 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. - */ - -#include - -#import -#import - -#import - -#import -#import "iCalEvent+MAPIStore.h" - -#import "MAPIStoreAppointmentWrapper.h" -#import "MAPIStoreCalendarAttachment.h" -#import "MAPIStoreContext.h" -#import "MAPIStoreUserContext.h" -#import "MAPIStoreTypes.h" -#import "NSObject+MAPIStore.h" - -#import "MAPIStoreCalendarEmbeddedMessage.h" - -#include - -@implementation MAPIStoreCalendarEmbeddedMessage - -- (id) initInContainer: (id) newContainer -{ - MAPIStoreContext *context; - MAPIStoreUserContext *userContext; - MAPIStoreAppointmentWrapper *appointmentWrapper; - - if ((self = [super initInContainer: newContainer])) - { - context = [self context]; - userContext = [self userContext]; - appointmentWrapper - = [MAPIStoreAppointmentWrapper - wrapperWithICalEvent: [newContainer event] - andUser: [userContext sogoUser] - andSenderEmail: nil - withConnectionInfo: [context connectionInfo]]; - [self addProxy: appointmentWrapper]; - } - - return self; -} - -- (NSDate *) creationTime -{ - return [[container event] created]; -} - -- (NSDate *) lastModificationTime -{ - return [[container event] lastModified]; -} - -- (void) getMessageData: (struct mapistore_message **) dataPtr - inMemCtx: (TALLOC_CTX *) memCtx -{ - struct mapistore_message *msgData; - - [super getMessageData: &msgData inMemCtx: memCtx]; - - /* HACK: we know the first (and only) proxy is our appointment wrapper - instance, but this might not always be true */ - [[proxies objectAtIndex: 0] fillMessageData: msgData - inMemCtx: memCtx]; - *dataPtr = msgData; -} - -- (enum mapistore_error) getPidTagMessageClass: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = talloc_strdup (memCtx, "IPM.OLE.CLASS.{00061055-0000-0000-C000-000000000046}"); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagMessageFlags: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, MSGFLAG_UNMODIFIED); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagProcessed: (void **) data inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getYes: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagResponseRequested: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getYes: data inMemCtx: memCtx]; -} - -/* discarded properties */ - -- (enum mapistore_error) getPidLidAppointmentLastSequence: (void **) - inMemCtx: (TALLOC_CTX *) memCtx -{ - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidLidMeetingWorkspaceUrl: (void **) - inMemCtx: (TALLOC_CTX *) memCtx -{ - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidLidContacts: (void **) - inMemCtx: (TALLOC_CTX *) memCtx -{ - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidTagSensitivity: (void **) - inMemCtx: (TALLOC_CTX *) memCtx -{ - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidLidPrivate: (void **) - inMemCtx: (TALLOC_CTX *) memCtx -{ - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidNameKeywords: (void **) - inMemCtx: (TALLOC_CTX *) memCtx -{ - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidLidFExceptionalBody: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getNo: data inMemCtx: memCtx]; -} - -- (void) save: (TALLOC_CTX *) memCtx -{ -// (gdb) po embeddedMessage->properties -// 2442592320 = "2012-07-11 22:30:00 +0000"; -// 2448359488 = "2012-07-11 22:30:00 +0000"; -// 2442723392 = "2012-07-11 22:30:00 +0000"; -// 2442068032 = "2012-07-11 22:30:00 +0000"; -// 2441740352 = "2012-07-11 23:00:00 +0000"; -// 131083 = 1; 2442330115 = 2; -// 235339779 = 9; -// 6291520 = "2012-07-11 16:00:00 +0000"; -// 2442526784 = "2012-07-11 23:00:00 +0000"; -// 2818059 = 0; -// 1703967 = "IPM.OLE.CLASS.{00061055-0000-0000-C000-000000000046}"; -// 3538947 = 0; -// 1071513603 = 28591; 805830720 = "2012-07-10 16:42:00 +0000"; -// 2485977346 = <02013000 02001500 45006100 73007400 -// 65007200 6e002000 53007400 61006e00 64006100 72006400 20005400 69006d00 -// 65000200 02013e00 0000d607 00000000 00000000 00000000 00002c01 00000000 -// 0000c4ff ffff0000 0a000000 05000200 00000000 00000000 04000000 01000200 -// 00000000 00000201 3e000200 d7070000 00000000 00000000 00000000 2c010000 -// 00000000 c4ffffff 00000b00 00000100 02000000 00000000 00000300 00000200 -// 02000000 00000000>; 2454257728 = "2012-07-11 16:00:00 +0000"; 2442985475 = -// 118330; 1507331 = 1; 805765184 = "2012-07-09 18:32:00 +0000"; 2442657856 = -// "2012-07-11 23:00:00 +0000"; 2443051039 = "11.0"; 236912651 = 1; 2485911810 = -// <02013000 02001500 45006100 73007400 65007200 6e002000 53007400 61006e00 -// 64006100 72006400 20005400 69006d00 65000200 02013e00 0000d607 00000000 -// 00000000 00000000 00002c01 00000000 0000c4ff ffff0000 0a000000 05000200 -// 00000000 00000000 04000000 01000200 00000000 00000201 3e000200 d7070000 -// 00000000 00000000 00000000 2c010000 00000000 c4ffffff 00000b00 00000100 -// 02000000 00000000 00000300 00000200 02000000 00000000>; 2441543683 = 30; -// 2442068032 = "2012-07-11 22:30:00 +0000"; -// 1073348639 = "OpenChange User"; -// 806027522 = <2d64f6f5 89a59243 992d29d1 49173b3a>; 6357056 = "2012-07-11 -// 16:30:00 +0000"; -// */ - -// // 0x92490040 = 2454257728 - -// } - - SOGoUser *activeUser; - - activeUser = [[self context] activeUser]; - - [[container event] updateFromMAPIProperties: properties - inUserContext: [self userContext] - withActiveUser: activeUser - isNew: NO - inMemCtx: memCtx]; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreCalendarFolder.h b/Attic/OpenChange/MAPIStoreCalendarFolder.h deleted file mode 100644 index 9b3a4cf5c..000000000 --- a/Attic/OpenChange/MAPIStoreCalendarFolder.h +++ /dev/null @@ -1,32 +0,0 @@ -/* MAPIStoreCalendarFolder.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTORECALENDARFOLDER_H -#define MAPISTORECALENDARFOLDER_H - -#import "MAPIStoreCalTaskFolder.h" - -@interface MAPIStoreCalendarFolder : MAPIStoreCalTaskFolder - -@end - -#endif /* MAPISTORECALENDARFOLDER_H */ diff --git a/Attic/OpenChange/MAPIStoreCalendarFolder.m b/Attic/OpenChange/MAPIStoreCalendarFolder.m deleted file mode 100644 index ed949e638..000000000 --- a/Attic/OpenChange/MAPIStoreCalendarFolder.m +++ /dev/null @@ -1,226 +0,0 @@ -/* MAPIStoreCalendarFolder.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#import "MAPIApplication.h" -#import "MAPIStoreCalendarContext.h" -#import "MAPIStoreCalendarMessage.h" -#import "MAPIStoreCalendarMessageTable.h" -#import "MAPIStoreUserContext.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreCalendarFolder.h" - -#include -#include -#include - -@implementation MAPIStoreCalendarFolder - -- (MAPIStoreMessageTable *) messageTable -{ - [self synchroniseCache]; - return [MAPIStoreCalendarMessageTable tableForContainer: self]; -} - -- (NSString *) component -{ - return @"vevent"; -} - -- (MAPIStoreMessage *) createMessage -{ - MAPIStoreMessage *newMessage; - SOGoAppointmentObject *newEntry; - NSString *name; - - [[self userContext] activate]; - - name = [NSString stringWithFormat: @"%@.ics", - [SOGoObject globallyUniqueObjectId]]; - newEntry = [SOGoAppointmentObject objectWithName: name - inContainer: sogoObject]; - [newEntry setIsNew: YES]; - newMessage = [MAPIStoreCalendarMessage mapiStoreObjectWithSOGoObject: newEntry - inContainer: self]; - return newMessage; -} - -- (NSArray *) rolesForExchangeRights: (uint32_t) rights -{ - /* Limitations - - Following rights are not supported by SOGo specifically: - - - CreateSubfolders: No calendar subfolders - - FolderVisible: It is inferred by other rights when extracting - */ - NSMutableArray *roles; - - roles = [NSMutableArray arrayWithCapacity: 6]; - if (rights & RightsCreateItems) - [roles addObject: SOGoRole_ObjectCreator]; - if (rights & RightsDeleteAll) - [roles addObject: SOGoRole_ObjectEraser]; - if (rights & RightsDeleteOwn) - [roles addObject: MAPIStoreRightDeleteOwn]; - - if (rights & RightsEditAll) - { - [roles addObject: SOGoCalendarRole_PublicModifier]; - [roles addObject: SOGoCalendarRole_PrivateModifier]; - [roles addObject: SOGoCalendarRole_ConfidentialModifier]; - } - if (rights & RightsEditOwn) - [roles addObject: MAPIStoreRightEditOwn]; - - if (rights & RightsReadItems) - { - [roles addObject: SOGoCalendarRole_PublicViewer]; - [roles addObject: SOGoCalendarRole_PrivateViewer]; - [roles addObject: SOGoCalendarRole_ConfidentialViewer]; - } - if (rights & RightsFreeBusySimple) - [roles addObject: SOGoCalendarRole_PublicDAndTViewer]; - - if (rights & RightsFreeBusyDetailed) - [roles addObject: SOGoCalendarRole_ConfidentialDAndTViewer]; - - if (rights & RightsFolderOwner) - [roles addObject: MAPIStoreRightFolderOwner]; - - if (rights & RightsFolderContact) - [roles addObject: MAPIStoreRightFolderContact]; - - // [self logWithFormat: @"roles for rights %.8x = (%@)", rights, roles]; - - return roles; -} - -- (uint32_t) exchangeRightsForRoles: (NSArray *) roles -{ - uint32_t rights = 0; - - if ([roles containsObject: SOGoRole_ObjectCreator]) - rights |= RightsCreateItems; - if ([roles containsObject: SOGoRole_ObjectEraser]) - rights |= RightsDeleteAll | RightsDeleteOwn; - if ([roles containsObject: SOGoCalendarRole_PublicModifier] - && [roles containsObject: SOGoCalendarRole_PrivateModifier] - && [roles containsObject: SOGoCalendarRole_ConfidentialModifier]) - rights |= RightsReadItems | RightsEditAll | RightsEditOwn | RightsFreeBusySimple | RightsFreeBusyDetailed; - else if ([roles containsObject: SOGoCalendarRole_PublicViewer] - && [roles containsObject: SOGoCalendarRole_PrivateViewer] - && [roles containsObject: SOGoCalendarRole_ConfidentialViewer]) - rights |= RightsReadItems; - - if ([roles containsObject: MAPIStoreRightEditOwn]) - rights |= RightsEditOwn; - if ([roles containsObject: MAPIStoreRightDeleteOwn]) - rights |= RightsDeleteOwn; - - if ([roles containsObject: SOGoCalendarRole_PublicDAndTViewer]) - rights |= RightsFreeBusySimple; - - if ([roles containsObject: SOGoCalendarRole_ConfidentialDAndTViewer]) - rights |= RightsFreeBusySimple | RightsFreeBusyDetailed; - - if ((rights & RightsReadItems) != 0 || (rights & RightsCreateItems) != 0 || (rights & RightsDeleteAll) != 0) - rights |= RoleNone; /* actually "folder visible" */ - - if ([roles containsObject: MAPIStoreRightFolderOwner]) - rights |= RightsFolderOwner | RoleNone; - - if ([roles containsObject: MAPIStoreRightFolderContact]) - rights |= RightsFolderContact; - - // [self logWithFormat: @"rights for roles (%@) = %.8x", roles, rights]; - - return rights; -} - -- (BOOL) subscriberCanReadMessages -{ - static NSArray *viewerRoles = nil; - - if (!viewerRoles) - viewerRoles = [[NSArray alloc] initWithObjects: - SOGoCalendarRole_PublicViewer, - SOGoCalendarRole_PublicDAndTViewer, - SOGoCalendarRole_PrivateViewer, - SOGoCalendarRole_PrivateDAndTViewer, - SOGoCalendarRole_ConfidentialViewer, - SOGoCalendarRole_ConfidentialDAndTViewer, - nil]; - - return ([[self activeUserRoles] firstObjectCommonWithArray: viewerRoles] - != nil); -} - -- (BOOL) subscriberCanModifyMessages -{ - static NSArray *modifierRoles = nil; - - if (!modifierRoles) - modifierRoles = [[NSArray alloc] initWithObjects: - SOGoCalendarRole_PublicModifier, - SOGoCalendarRole_PrivateModifier, - SOGoCalendarRole_ConfidentialModifier, - nil]; - - return ([[self activeUserRoles] firstObjectCommonWithArray: modifierRoles] - != nil); -} - -- (EOQualifier *) aclQualifier -{ - return [EOQualifier qualifierWithQualifierFormat: - [(SOGoAppointmentFolder *) sogoObject aclSQLListingFilter]]; -} - -- (enum mapistore_error) getPidTagContainerClass: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [@"IPF.Appointment" asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagDefaultPostMessageClass: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [@"IPM.Appointment" asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreCalendarMessage.h b/Attic/OpenChange/MAPIStoreCalendarMessage.h deleted file mode 100644 index 99e286073..000000000 --- a/Attic/OpenChange/MAPIStoreCalendarMessage.h +++ /dev/null @@ -1,40 +0,0 @@ -/* MAPIStoreCalendarMessage.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTORECALENDARMESSAGE_H -#define MAPISTORECALENDARMESSAGE_H - -#import "MAPIStoreCalTaskMessage.h" - -@class iCalCalendar; -@class iCalEvent; -@class MAPIStoreAppointmentWrapper; - -@interface MAPIStoreCalendarMessage : MAPIStoreCalTaskMessage -{ - iCalCalendar *calendar; - iCalEvent *masterEvent; -} - -@end - -#endif /* MAPISTORECALENDARMESSAGE_H */ diff --git a/Attic/OpenChange/MAPIStoreCalendarMessage.m b/Attic/OpenChange/MAPIStoreCalendarMessage.m deleted file mode 100644 index 5ec92d07f..000000000 --- a/Attic/OpenChange/MAPIStoreCalendarMessage.m +++ /dev/null @@ -1,669 +0,0 @@ -/* MAPIStoreCalendarMessage.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -/* TODO: - - merge common code with tasks - - take the tz definitions from Outlook */ - -#include -#include - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#import "iCalEvent+MAPIStore.h" -#import "MAPIStoreAppointmentWrapper.h" -#import "MAPIStoreCalendarAttachment.h" -#import "MAPIStoreCalendarFolder.h" -#import "MAPIStoreContext.h" -#import "MAPIStoreMapping.h" -#import "MAPIStoreRecurrenceUtils.h" -#import "MAPIStoreTypes.h" -#import "MAPIStoreUserContext.h" -#import "NSDate+MAPIStore.h" -#import "NSData+MAPIStore.h" -#import "NSObject+MAPIStore.h" -#import "NSString+MAPIStore.h" -#import "NSValue+MAPIStore.h" - -#import "MAPIStoreCalendarMessage.h" - -#undef DEBUG -#include -#include -#include -#include -#include -#include -#include - -// extern void ndr_print_AppointmentRecurrencePattern(struct ndr_print *ndr, const char *name, const struct AppointmentRecurrencePattern *r); - -static Class NSArrayK, MAPIStoreAppointmentWrapperK; - -@implementation SOGoAppointmentObject (MAPIStoreExtension) - -- (Class) mapistoreMessageClass -{ - return [MAPIStoreCalendarMessage class]; -} - -@end - -@implementation MAPIStoreCalendarMessage - -+ (void) initialize -{ - NSArrayK = [NSArray class]; - MAPIStoreAppointmentWrapperK = [MAPIStoreAppointmentWrapper class]; -} - -+ (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP - inMemCtx: (TALLOC_CTX *) memCtx -{ - BOOL listedProperties[65536]; - NSUInteger count; - uint16_t propId; - - memset (listedProperties, NO, 65536 * sizeof (BOOL)); - [super getAvailableProperties: propertiesP inMemCtx: memCtx]; - for (count = 0; count < (*propertiesP)->cValues; count++) - { - propId = ((*propertiesP)->aulPropTag[count] >> 16) & 0xffff; - listedProperties[propId] = YES; - } - [MAPIStoreAppointmentWrapper fillAvailableProperties: *propertiesP - withExclusions: listedProperties]; - - return MAPISTORE_SUCCESS; -} - -- (id) init -{ - if ((self = [super init])) - { - calendar = nil; - masterEvent = nil; - } - - return self; -} - -- (void) _setupAttachmentParts -{ - NSUInteger count, max; - NSArray *events; - NSString *newKey; - MAPIStoreCalendarAttachment *attachment; - NSUInteger aid; - iCalEvent *event; - - events = [calendar events]; - max = [events count]; - for (count = 1; count < max; count++) - { - attachment = [MAPIStoreCalendarAttachment - mapiStoreObjectInContainer: self]; - /* we now that there are no attachments yet, so we can assume that the - right AID is 0 from the start */ - aid = count - 1; - [attachment setAID: aid]; - event = [events objectAtIndex: count]; - [attachment setEvent: event]; - newKey = [[event uniqueChildWithTag: @"recurrence-id"] - flattenedValuesForKey: @""]; - [attachmentParts setObject: attachment forKey: newKey]; - } -} - -- (id) initWithSOGoObject: (id) newSOGoObject - inContainer: (MAPIStoreObject *) newFolder -{ - MAPIStoreContext *context; - MAPIStoreUserContext *userContext; - iCalCalendar *origCalendar; - MAPIStoreAppointmentWrapper *appointmentWrapper; - - if ((self = [super initWithSOGoObject: newSOGoObject - inContainer: newFolder])) - { - if ([newSOGoObject isNew]) - { - ASSIGN (calendar, [iCalCalendar groupWithTag: @"vcalendar"]); - [calendar setVersion: @"2.0"]; - [calendar setProdID: @"-//Inverse inc.//OpenChange+SOGo//EN"]; - masterEvent = [iCalEvent groupWithTag: @"vevent"]; - [calendar addChild: masterEvent]; - [masterEvent setCreated: [NSCalendarDate date]]; - } - else - { - origCalendar = [sogoObject calendar: YES secure: YES]; - if (!origCalendar) - { - [self errorWithFormat: @"Incorrect calendar event %@. Empty message is created", - [self url]]; - return self; - } - calendar = [origCalendar mutableCopy]; - masterEvent = [[calendar events] objectAtIndex: 0]; - [self _setupAttachmentParts]; - } - context = [self context]; - userContext = [self userContext]; - appointmentWrapper - = [MAPIStoreAppointmentWrapper wrapperWithICalEvent: masterEvent - andUser: [userContext sogoUser] - andSenderEmail: nil - withConnectionInfo: [context connectionInfo]]; - [self addProxy: appointmentWrapper]; - } - - return self; -} - -- (void) dealloc -{ - //NSLog(@"MAPIStoreCalendarMessage: -dealloc (%p)", self); - [calendar release]; - [super dealloc]; -} - -- (MAPIStoreAppointmentWrapper *) _appointmentWrapper -{ - NSUInteger i, max; - id proxy; - max = [proxies count]; - for (i = 0; i < max; i++) { - proxy = [proxies objectAtIndex: i]; - if ([proxy isKindOfClass: MAPIStoreAppointmentWrapperK]) - { - return proxy; - } - } - return nil; -} - - -/* getters */ -- (enum mapistore_error) getPidTagMessageClass: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - SOGoUser *owner; - - owner = [[self userContext] sogoUser]; - if ([masterEvent userAsAttendee: owner]) - *data = talloc_strdup (memCtx, "IPM.Schedule.Meeting.Request"); - else - *data = talloc_strdup (memCtx, "IPM.Appointment"); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidSideEffects: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, - seOpenToDelete | seOpenToCopy | seOpenToMove - | seCoerceToInbox | seOpenForCtxMenu); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagProcessed: (void **) data inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getYes: data inMemCtx: memCtx]; -} - -- (void) getMessageData: (struct mapistore_message **) dataPtr - inMemCtx: (TALLOC_CTX *) memCtx -{ - static NSString *recTypes[] = {@"orig", @"to", @"cc", @"bcc"}; - static NSInteger recTypesValue[] = {MAPI_ORIG, MAPI_TO, MAPI_CC, MAPI_BCC}; - struct mapistore_message *msgData; - NSDictionary *recipients, *contactInfos; - NSString *email; - NSArray *attendees; - NSDictionary *attendee; - SOGoUserManager *mgr; - struct mapistore_message_recipient *recipient; - NSUInteger nRecType, maxRecTypes, count, max, propCount; - NSObject *currentValue; - - [super getMessageData: &msgData inMemCtx: memCtx]; - - /* The presence of the "recipients" meta-property means that our most recent - list of recipients has not been saved yet and that we must return that - one instead of the one stored in the event. */ - recipients = [properties objectForKey: @"recipients"]; - if (recipients) - { - mgr = [SOGoUserManager sharedUserManager]; - - /* TODO: this code might need to be moved into MAPIStoreMessage */ - msgData->columns = set_SPropTagArray (msgData, 9, - PR_OBJECT_TYPE, - PR_DISPLAY_TYPE, - PR_7BIT_DISPLAY_NAME_UNICODE, - PR_SMTP_ADDRESS_UNICODE, - PR_SEND_INTERNET_ENCODING, - PR_RECIPIENT_DISPLAY_NAME_UNICODE, - PR_RECIPIENT_FLAGS, - PR_RECIPIENT_ENTRYID, - PR_RECIPIENT_TRACKSTATUS); - - maxRecTypes = sizeof(recTypes) / sizeof(recTypes[0]); - for (nRecType = 0; nRecType < maxRecTypes; nRecType++) - { - attendees = [recipients objectForKey: recTypes[nRecType]]; - max = [attendees count]; - if (max > 0) - { - msgData->recipients_count += max; - msgData->recipients = talloc_realloc(msgData, - msgData->recipients, struct - mapistore_message_recipient, msgData->recipients_count); - recipient = msgData->recipients; - for (count = 0; count < max; count++) - { - attendee = [attendees objectAtIndex: count]; - recipient->type = recTypesValue[nRecType]; - email = [attendee objectForKey: @"email"]; - if (email) - { - contactInfos - = [mgr contactInfosForUserWithUIDorEmail: email]; - recipient->username = [[contactInfos - objectForKey: @"c_uid"] - asUnicodeInMemCtx: msgData]; - } - else - recipient->username = NULL; - - recipient->data = talloc_array(msgData, void *, - msgData->columns->cValues); - for (propCount = 0; - propCount < msgData->columns->cValues; - propCount++) - { - currentValue = [attendee objectForKey: MAPIPropertyKey (msgData->columns->aulPropTag[propCount])]; - [currentValue getValue: recipient->data + propCount - forTag: msgData->columns->aulPropTag[propCount] - inMemCtx: msgData]; - } - recipient++; - } - } - } - } - else - { - [[self _appointmentWrapper] fillMessageData: msgData - inMemCtx: memCtx]; - } - - *dataPtr = msgData; -} - -- (enum mapistore_error) getPidTagResponseRequested: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getYes: data inMemCtx: memCtx]; -} - -/* This three methods: getPidTagNormalizedSubject, - getPidTagSensitivity and getPidTagImportance are implemented in - MAPIStoreMessage base class, then the proxy method is not reached - (see MAPIStoreObject). -*/ -- (enum mapistore_error) getPidTagNormalizedSubject: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - MAPIStoreAppointmentWrapper *appointmentWrapper; - - appointmentWrapper = [self _appointmentWrapper]; - if (appointmentWrapper) - return [appointmentWrapper getPidTagNormalizedSubject: data inMemCtx: memCtx]; - - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidTagSensitivity: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - MAPIStoreAppointmentWrapper *appointmentWrapper; - - appointmentWrapper = [self _appointmentWrapper]; - if (appointmentWrapper) - return [appointmentWrapper getPidTagSensitivity: data inMemCtx: memCtx]; - - return [self getLongZero: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagImportance: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - MAPIStoreAppointmentWrapper *appointmentWrapper; - - appointmentWrapper = [self _appointmentWrapper]; - if (appointmentWrapper) - return [appointmentWrapper getPidTagImportance: data inMemCtx: memCtx]; - - *data = MAPILongValue (memCtx, 1); - - return MAPISTORE_SUCCESS; -} - - -- (NSString *) _uidFromGlobalObjectId: (TALLOC_CTX *) memCtx -{ - NSData *objectId; - NSString *uid = nil; - char *bytesDup, *uidStart; - NSUInteger length; - - /* NOTE: we only handle the generic case at the moment, see - MAPIStoreAppointmentWrapper */ - objectId = [properties - objectForKey: MAPIPropertyKey (PidLidGlobalObjectId)]; - if (objectId) - { - length = [objectId length]; - bytesDup = talloc_array (memCtx, char, length + 1); - memcpy (bytesDup, [objectId bytes], length); - bytesDup[length] = 0; - uidStart = bytesDup + length - 1; - while (uidStart != bytesDup && *(uidStart - 1)) - uidStart--; - if (uidStart > bytesDup && *uidStart) - uid = [NSString stringWithUTF8String: uidStart]; - talloc_free (bytesDup); - } - - return uid; -} - -- (SOGoAppointmentObject *) _resurrectRecord: (NSString *) cname - fromFolder: (SOGoAppointmentFolder *) folder -{ - NSArray *records; - EOQualifier *qualifier; - EOFetchSpecification *fs; - GCSFolder *ocsFolder; - SOGoAppointmentObject *newObject; - NSMutableDictionary *newRecord; - static NSArray *childRecordFields = nil; - - if (!childRecordFields) - { - childRecordFields = [NSArray arrayWithObjects: @"c_name", - @"c_creationdate", @"c_lastmodified", - @"c_content", nil]; - [childRecordFields retain]; - } - - ocsFolder = [folder ocsFolder]; - - qualifier - = [EOQualifier qualifierWithQualifierFormat: - [NSString stringWithFormat: @"c_name='%@'", cname]]; - fs = [EOFetchSpecification fetchSpecificationWithEntityName: [ocsFolder folderName] - qualifier: qualifier - sortOrderings: nil]; - records = [ocsFolder fetchFields: childRecordFields - fetchSpecification: fs - ignoreDeleted: NO]; - if ([records isKindOfClass: NSArrayK] && [records count]) - { - newRecord = [[records objectAtIndex: 0] mutableCopy]; - [newRecord setObject: [NSNumber numberWithInt: 0] - forKey: @"c_version"]; - newObject = [SOGoAppointmentObject objectWithRecord: newRecord - inContainer: folder]; - [newRecord autorelease]; - [newObject setIsNew: NO]; - } - else - newObject = nil; - - - return newObject; -} - -- (void) _fixupAppointmentObjectWithUID: (NSString *) uid -{ - NSString *cname, *url; - MAPIStoreMapping *mapping; - uint64_t objectId; - WOContext *woContext; - SOGoAppointmentFolder *folder; - SOGoAppointmentObject *newObject; - - cname = [[container sogoObject] resourceNameForEventUID: uid]; - if (cname) - isNew = NO; - else - cname = [NSString stringWithFormat: @"%@.ics", uid]; - - mapping = [self mapping]; - - url = [NSString stringWithFormat: @"%@%@", [container url], cname]; - folder = [sogoObject container]; - - /* reinstantiate the old sogo object and attach it to self */ - [[self userContext] activate]; - woContext = [[self userContext] woContext]; - if (isNew) - { - /* event could have been deleted, let's try to resurrect it */ - newObject = [self _resurrectRecord: cname fromFolder: folder]; - if (!newObject) - { - newObject = [SOGoAppointmentObject objectWithName: cname - inContainer: folder]; - [newObject setIsNew: YES]; - } - } - else - { - /* dissociate the object url from the old object's id */ - objectId = [mapping idFromURL: url]; - [mapping unregisterURLWithID: objectId]; - newObject = [folder lookupName: cname - inContext: woContext - acquire: NO]; - } - - /* dissociate the object url associated with this object, as we want to - discard it */ - objectId = [self objectId]; - [mapping unregisterURLWithID: objectId]; - - /* associate the new object url with this object id */ - [mapping registerURL: url withID: objectId]; - - [newObject setContext: woContext]; - ASSIGN (sogoObject, newObject); -} - -- (NSUInteger) sensitivity -{ - return [[self _appointmentWrapper] sensitivity]; -} - -- (NSString *) creator -{ - return [[self _appointmentWrapper] creator]; -} - -- (NSString *) owner -{ - return [[self _appointmentWrapper] owner]; -} - -- (void) _updateAttachedEvents -{ - NSArray *allAttachments; - NSUInteger count, max; - NSString *uid, *summary; - iCalEvent *event; - MAPIStoreCalendarAttachment *attachment; - - /* ensure that all exception events have the same UID as the master */ - uid = [masterEvent uid]; - summary = [masterEvent summary]; - - allAttachments = [attachmentParts allValues]; - max = [allAttachments count]; - for (count = 0; count < max; count++) - { - attachment = [allAttachments objectAtIndex: count]; - event = [attachment event]; - if ([[event summary] length] == 0) - [event setSummary: summary]; - [event setUid: uid]; - } -} - -- (void) save: (TALLOC_CTX *) memCtx -{ - // iCalCalendar *vCalendar; - // NSCalendarDate *now; - NSString *uid, *nameInContainer; - // iCalEvent *newEvent; - // iCalPerson *userPerson; - SOGoUser *activeUser; - NSRange rangeOfDot; - - if (isNew) - { - uid = [self _uidFromGlobalObjectId: memCtx]; - if (uid) - { - /* Hack required because of what's explained in oxocal 3.1.4.7.1: - basically, Outlook creates a copy of the event and then removes - the old instance. We perform a trickery to avoid performing those - operations in the backend, in a way that enables us to recover - the initial instance and act solely on it. */ - [self _fixupAppointmentObjectWithUID: uid]; - } - else - { - /* We create a UID from the nameInContainer, or the reverse if the - latter is already set... */ - nameInContainer = [sogoObject nameInContainer]; - if (nameInContainer) - { - rangeOfDot = [nameInContainer rangeOfString: @"." - options: NSBackwardsSearch]; - if (rangeOfDot.location == NSNotFound) - uid = nameInContainer; - else - uid = [nameInContainer substringToIndex: rangeOfDot.location]; - } - else - { - uid = [SOGoObject globallyUniqueObjectId]; - nameInContainer = [NSString stringWithFormat: @"%@.ics", uid]; - [sogoObject setNameInContainer: nameInContainer]; - } - } - [masterEvent setUid: uid]; - } - - // [self logWithFormat: @"-save, event props:"]; - // MAPIStoreDumpMessageProperties (newProperties); - - // now = [NSCalendarDate date]; - - activeUser = [[self context] activeUser]; - [masterEvent updateFromMAPIProperties: properties - inUserContext: [self userContext] - withActiveUser: activeUser - isNew: isNew - inMemCtx: memCtx]; - [self _updateAttachedEvents]; - [[self userContext] activate]; - [sogoObject updateContentWithCalendar: calendar - fromRequest: nil]; - [self updateVersions]; -} - -- (id) lookupAttachment: (NSString *) childKey -{ - return [attachmentParts objectForKey: childKey]; -} - -- (MAPIStoreAttachment *) createAttachment -{ - MAPIStoreCalendarAttachment *newAttachment; - uint32_t newAid; - NSString *newKey; - iCalEvent *newEvent; - - newAid = [[self attachmentKeys] count]; - - newAttachment = [MAPIStoreCalendarAttachment - mapiStoreObjectInContainer: self]; - [newAttachment setAID: newAid]; - newEvent = [iCalEvent groupWithTag: @"vevent"]; - [newAttachment setEvent: newEvent]; - [calendar addToEvents: newEvent]; - - newKey = [NSString stringWithFormat: @"%ul", newAid]; - [attachmentParts setObject: newAttachment - forKey: newKey]; - [attachmentKeys release]; - attachmentKeys = nil; - - return newAttachment; -} - -- (enum mapistore_error) setReadFlag: (uint8_t) flag -{ - return MAPISTORE_SUCCESS; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreCalendarMessageTable.h b/Attic/OpenChange/MAPIStoreCalendarMessageTable.h deleted file mode 100644 index eeccbc455..000000000 --- a/Attic/OpenChange/MAPIStoreCalendarMessageTable.h +++ /dev/null @@ -1,32 +0,0 @@ -/* MAPIStoreCalendarMessageTable.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 MAPISTORECALENDARMESSAGETABLE_H -#define MAPISTORECALENDARMESSAGETABLE_H - -#import "MAPIStoreGCSMessageTable.h" - -@interface MAPIStoreCalendarMessageTable : MAPIStoreGCSMessageTable - -@end - -#endif /* MAPISTORECALENDARMESSAGETABLE_H */ diff --git a/Attic/OpenChange/MAPIStoreCalendarMessageTable.m b/Attic/OpenChange/MAPIStoreCalendarMessageTable.m deleted file mode 100644 index bbf05274f..000000000 --- a/Attic/OpenChange/MAPIStoreCalendarMessageTable.m +++ /dev/null @@ -1,193 +0,0 @@ -/* MAPIStoreCalendarMessageTable.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -#import -#import -#import - -#import - -#import - -#import "MAPIStoreCalendarMessage.h" -#import "MAPIStoreTypes.h" -#import "NSDate+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreCalendarMessageTable.h" - -#include - -static Class MAPIStoreCalendarMessageK = Nil; - -@implementation MAPIStoreCalendarMessageTable - -+ (void) initialize -{ - MAPIStoreCalendarMessageK = [MAPIStoreCalendarMessage class]; -} - -+ (Class) childObjectClass -{ - return MAPIStoreCalendarMessageK; -} - -- (EOQualifier *) _orgMailNotNullQualifier -{ - static EOQualifier *orgMailQualifier = nil; - EOQualifier *notNullQualifier, *nullQualifier, *notEmptyQualifier, *emptyQualifier; - - if (!orgMailQualifier) - { - nullQualifier = [[EOKeyValueQualifier alloc] - initWithKey: @"c_orgmail" - operatorSelector: EOQualifierOperatorEqual - value: [NSNull null]]; - notNullQualifier = [[EONotQualifier alloc] - initWithQualifier: nullQualifier]; - emptyQualifier = [[EOKeyValueQualifier alloc] - initWithKey: @"c_orgmail" - operatorSelector: EOQualifierOperatorEqual - value: @""]; - notEmptyQualifier = [[EONotQualifier alloc] - initWithQualifier: emptyQualifier]; - orgMailQualifier = [[EOAndQualifier alloc] - initWithQualifiers: notNullQualifier, - notEmptyQualifier, nil]; - [nullQualifier release]; - [notNullQualifier release]; - [emptyQualifier release]; - [notEmptyQualifier release]; - } - - return orgMailQualifier; -} - -- (MAPIRestrictionState) evaluatePropertyRestriction: (struct mapi_SPropertyRestriction *) res - intoQualifier: (EOQualifier **) qualifier -{ - MAPIRestrictionState rc; - id value; - NSMutableString *likeString; - NSString *likePartString; - EOAndQualifier *andQualifier, *stringQualifier; - union { - uint32_t longValue; - char charValue[4]; - } apptIdValue; - - value = NSObjectFromMAPISPropValue (&res->lpProp); - switch ((uint32_t) res->ulPropTag) - { - case PR_MESSAGE_CLASS_UNICODE: - if ([value isEqualToString: @"IPM.Appointment"]) - rc = MAPIRestrictionStateAlwaysTrue; - else - rc = MAPIRestrictionStateAlwaysFalse; - break; - case PR_OWNER_APPT_ID: - // c_orgmail != NULL && c_orgmail != '' && c_uid like 'ab%89'; - apptIdValue.longValue = [value unsignedLongValue]; - likeString = [NSMutableString string]; - likePartString = [[NSString alloc] - initWithBytes: apptIdValue.charValue - length: 2 - encoding: NSISOLatin1StringEncoding]; - [likeString appendString: likePartString]; - [likePartString release]; - [likeString appendString: @"%%"]; - likePartString = [[NSString alloc] - initWithBytes: apptIdValue.charValue + 2 - length: 2 - encoding: NSISOLatin1StringEncoding]; - [likeString appendString: likePartString]; - [likePartString release]; - stringQualifier = [[EOKeyValueQualifier alloc] - initWithKey: @"c_uid" - operatorSelector: EOQualifierOperatorLike - value: likeString]; - andQualifier = [[EOAndQualifier alloc] - initWithQualifiers: [self _orgMailNotNullQualifier], - stringQualifier, nil]; - [andQualifier autorelease]; - [stringQualifier release]; - *qualifier = andQualifier; - rc = MAPIRestrictionStateNeedsEval; - break; - case PidLidBusyStatus: - rc = MAPIRestrictionStateAlwaysTrue; // should be based on c_isopaque - break; - default: - rc = [super evaluatePropertyRestriction: res intoQualifier: qualifier]; - } - - return rc; -} - -- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property -{ - static NSMutableDictionary *knownProperties = nil; - - if (!knownProperties) - { - knownProperties = [NSMutableDictionary new]; - [knownProperties setObject: @"c_startdate" - forKey: MAPIPropertyKey (PidLidAppointmentStartWhole)]; - [knownProperties setObject: @"c_enddate" - forKey: MAPIPropertyKey (PidLidAppointmentEndWhole)]; - [knownProperties setObject: @"c_iscycle" - forKey: MAPIPropertyKey (PidLidRecurring)]; - } - - return [knownProperties objectForKey: MAPIPropertyKey (property)]; -} - -/* sorting */ - -- (NSString *) sortIdentifierForProperty: (enum MAPITAGS) property -{ - static NSMutableDictionary *knownProperties = nil; - - if (!knownProperties) - { - knownProperties = [NSMutableDictionary new]; - [knownProperties setObject: @"c_startdate" - forKey: MAPIPropertyKey (PidLidAppointmentStartWhole)]; - [knownProperties setObject: @"c_enddate" - forKey: MAPIPropertyKey (PidLidAppointmentEndWhole)]; - [knownProperties setObject: @"c_iscycle" - forKey: MAPIPropertyKey (PidLidRecurring)]; - [knownProperties setObject: @"c_isallday" - forKey: MAPIPropertyKey (PidLidAppointmentSubType)]; - [knownProperties setObject: @"c_creationdate" - forKey: MAPIPropertyKey (PR_CREATION_TIME)]; - [knownProperties setObject: @"c_uid" - forKey: MAPIPropertyKey (PR_OWNER_APPT_ID)]; - /* Use by oxcfxics to sort the latest first */ - [knownProperties setObject: @"c_lastmodified" - forKey: MAPIPropertyKey (PidTagMessageDeliveryTime)]; - } - - return [knownProperties objectForKey: MAPIPropertyKey (property)]; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreContactsAttachment.h b/Attic/OpenChange/MAPIStoreContactsAttachment.h deleted file mode 100644 index c4a368849..000000000 --- a/Attic/OpenChange/MAPIStoreContactsAttachment.h +++ /dev/null @@ -1,41 +0,0 @@ -/* MAPIStoreContactsAttachment.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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 MAPISTORECONTACTSATTACHMENT_H -#define MAPISTORECONTACTSATTACHMENT_H - -#import "MAPIStoreAttachment.h" - -@class NSData; -@class NGVCardPhoto; - -@interface MAPIStoreContactsAttachment : MAPIStoreAttachment -{ - NGVCardPhoto *photo; - NSData *photoData; -} - -- (void) setPhoto: (NGVCardPhoto *) newPhoto; - -@end - -#endif /* MAPISTORECONTACTSATTACHMENT_H */ diff --git a/Attic/OpenChange/MAPIStoreContactsAttachment.m b/Attic/OpenChange/MAPIStoreContactsAttachment.m deleted file mode 100644 index 6b0d73133..000000000 --- a/Attic/OpenChange/MAPIStoreContactsAttachment.m +++ /dev/null @@ -1,197 +0,0 @@ -/* MAPIStoreContactsAttachment.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import -#import -#import -#import - -#import "MAPIStoreTypes.h" -#import "NSData+MAPIStore.h" -#import "NSDate+MAPIStore.h" -#import "NSObject+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreContactsAttachment.h" - -#include - -/* TODO: handle URL pictures via PidTagAttachMethod = ref ? */ - -@implementation MAPIStoreContactsAttachment - -- (id) init -{ - if ((self = [super init])) - { - photo = nil; - photoData = nil; - } - - return self; -} - -- (void) dealloc -{ - [photo release]; - [photoData release]; - [super dealloc]; -} - -- (void) setPhoto: (NGVCardPhoto *) newPhoto -{ - ASSIGN (photo, newPhoto); -} - -- (NSString *) fileExtension -{ - NSString *type, *extension; - - type = [photo type]; - if ([type isEqualToString: @"JPEG"] - || [type isEqualToString: @"JPG"]) - extension = @".jpg"; - else if ([type isEqualToString: @"PNG"]) - extension = @".png"; - else if ([type isEqualToString: @"BMP"]) - extension = @".bmp"; - else if ([type isEqualToString: @"GIF"]) - extension = @".gif"; - else - extension = nil; - - return extension; -} - -- (NSDate *) creationTime -{ - return [container creationTime]; -} - -- (NSDate *) lastModificationTime -{ - return [container lastModificationTime]; -} - -- (enum mapistore_error) getPidTagAttachEncoding: (void **) data inMemCtx: (TALLOC_CTX *) memCtx; -{ - *data = [[NSData data] asBinaryInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAttachFlags: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getLongZero: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagAttachmentFlags: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getLongZero: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagAttachmentHidden: (void **) data inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getNo: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagAttachmentLinkId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getLongZero: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagAttachMethod: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, 0x00000001); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAttachmentContactPhoto: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getYes: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagAttachDataBinary: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!photoData) - ASSIGN (photoData, - [[photo flattenedValuesForKey: @""] dataByDecodingBase64]); - - *data = [photoData asBinaryInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAttachSize: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!photoData) - ASSIGN (photoData, - [[photo flattenedValuesForKey: @""] dataByDecodingBase64]); - - *data = MAPILongValue (memCtx, [photoData length]); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAttachExtension: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [[self fileExtension] asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAttachLongFilename: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *filename; - - filename = [NSString stringWithFormat: @"ContactPhoto%@", - [self fileExtension]]; - - *data = [filename asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAttachFilename: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagAttachLongFilename: data - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagDisplayName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagAttachLongFilename: data inMemCtx: memCtx]; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreContactsContext.h b/Attic/OpenChange/MAPIStoreContactsContext.h deleted file mode 100644 index 68120215e..000000000 --- a/Attic/OpenChange/MAPIStoreContactsContext.h +++ /dev/null @@ -1,32 +0,0 @@ -/* MAPIStoreContactsContext.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 MAPISTORECONTACTSCONTEXT_H -#define MAPISTORECONTACTSCONTEXT_H - -#import "MAPIStoreGCSBaseContext.h" - -@interface MAPIStoreContactsContext : MAPIStoreGCSBaseContext - -@end - -#endif /* MAPISTORECONTACTSCONTEXT_H */ diff --git a/Attic/OpenChange/MAPIStoreContactsContext.m b/Attic/OpenChange/MAPIStoreContactsContext.m deleted file mode 100644 index bfef33e27..000000000 --- a/Attic/OpenChange/MAPIStoreContactsContext.m +++ /dev/null @@ -1,59 +0,0 @@ -/* MAPIStoreContactsContext.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -#import - -#import - -#import "MAPIStoreContactsFolder.h" -#import "MAPIStoreUserContext.h" - -#import "MAPIStoreContactsContext.h" - -#undef DEBUG -#include - -static Class MAPIStoreContactsFolderK; - -@implementation MAPIStoreContactsContext - -+ (void) initialize -{ - MAPIStoreContactsFolderK = [MAPIStoreContactsFolder class]; -} - -+ (NSString *) MAPIModuleName -{ - return @"contacts"; -} - -+ (enum mapistore_context_role) MAPIContextRole -{ - return MAPISTORE_CONTACTS_ROLE; -} - -- (Class) MAPIStoreFolderClass -{ - return MAPIStoreContactsFolderK; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreContactsFolder.h b/Attic/OpenChange/MAPIStoreContactsFolder.h deleted file mode 100644 index 2bade99f7..000000000 --- a/Attic/OpenChange/MAPIStoreContactsFolder.h +++ /dev/null @@ -1,32 +0,0 @@ -/* MAPIStoreContactsFolder.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTORECONTACTSFOLDER_H -#define MAPISTORECONTACTSFOLDER_H - -#import "MAPIStoreGCSFolder.h" - -@interface MAPIStoreContactsFolder : MAPIStoreGCSFolder - -@end - -#endif /* MAPISTORECONTACTSFOLDER_H */ diff --git a/Attic/OpenChange/MAPIStoreContactsFolder.m b/Attic/OpenChange/MAPIStoreContactsFolder.m deleted file mode 100644 index d55c34a25..000000000 --- a/Attic/OpenChange/MAPIStoreContactsFolder.m +++ /dev/null @@ -1,157 +0,0 @@ -/* MAPIStoreContactsFolder.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import -#import -#import -#import -#import -#import - -#import "MAPIApplication.h" -#import "MAPIStoreUserContext.h" -#import "MAPIStoreContactsContext.h" -#import "MAPIStoreContactsMessage.h" -#import "MAPIStoreContactsMessageTable.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreContactsFolder.h" - -#include -#include -#include - -@implementation MAPIStoreContactsFolder - -- (MAPIStoreMessageTable *) messageTable -{ - [self synchroniseCache]; - return [MAPIStoreContactsMessageTable tableForContainer: self]; -} - -- (NSString *) component -{ - return @"vcard"; -} - -- (MAPIStoreMessage *) createMessage -{ - MAPIStoreMessage *newMessage; - SOGoContactGCSEntry *newEntry; - NSString *name; - - [[self userContext] activate]; - - name = [NSString stringWithFormat: @"%@.vcf", - [SOGoObject globallyUniqueObjectId]]; - newEntry = [SOGoContactGCSEntry objectWithName: name - inContainer: sogoObject]; - [newEntry setIsNew: YES]; - newMessage = [MAPIStoreContactsMessage mapiStoreObjectWithSOGoObject: newEntry - inContainer: self]; - - return newMessage; -} - -- (NSArray *) rolesForExchangeRights: (uint32_t) rights -{ - /* Limitations - - Following rights are not supported by SOGo specifically: - - - CreateSubfolders: No contacts subfolders - - FolderVisible: It is inferred by other rights when extracting - */ - NSMutableArray *roles; - - roles = [NSMutableArray arrayWithCapacity: 8]; - if (rights & RightsCreateItems) - [roles addObject: SOGoRole_ObjectCreator]; - if (rights & RightsDeleteAll) - [roles addObject: SOGoRole_ObjectEraser]; - if (rights & RightsDeleteOwn) - [roles addObject: MAPIStoreRightDeleteOwn]; - if (rights & RightsEditAll) - [roles addObject: SOGoRole_ObjectEditor]; - if (rights & RightsEditOwn) - [roles addObject: MAPIStoreRightEditOwn]; - if (rights & RightsReadItems) - [roles addObject: SOGoRole_ObjectViewer]; - - if (rights & RightsFolderOwner) - [roles addObject: MAPIStoreRightFolderOwner]; - if (rights & RightsFolderContact) - [roles addObject: MAPIStoreRightFolderContact]; - - return roles; -} - -- (uint32_t) exchangeRightsForRoles: (NSArray *) roles -{ - uint32_t rights = 0; - - if ([roles containsObject: SOGoRole_ObjectCreator]) - rights |= RightsCreateItems; - - if ([roles containsObject: SOGoRole_ObjectEraser]) - rights |= RightsDeleteAll | RightsDeleteOwn; - else if ([roles containsObject: MAPIStoreRightDeleteOwn]) - rights |= RightsDeleteOwn; - - if ([roles containsObject: SOGoRole_ObjectEditor]) - rights |= RightsEditAll | RightsEditOwn; - else if ([roles containsObject: MAPIStoreRightEditOwn]) - rights |= RightsEditOwn; - - if ([roles containsObject: SOGoRole_ObjectViewer]) - rights |= RightsReadItems; - if (rights != 0) - rights |= RoleNone; /* actually "folder visible" */ - - if ([roles containsObject: MAPIStoreRightFolderOwner]) - rights |= RightsFolderOwner | RoleNone; - - if ([roles containsObject: MAPIStoreRightFolderContact]) - rights |= RightsFolderContact; - - return rights; -} - -- (BOOL) subscriberCanModifyMessages -{ - return [[self activeUserRoles] containsObject: SOGoRole_ObjectEditor]; -} - -- (BOOL) subscriberCanReadMessages -{ - return [[self activeUserRoles] containsObject: SOGoRole_ObjectViewer]; -} - -- (enum mapistore_error) getPidTagDefaultPostMessageClass: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [@"IPM.Contact" asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreContactsMessage.h b/Attic/OpenChange/MAPIStoreContactsMessage.h deleted file mode 100644 index 48d5bafb0..000000000 --- a/Attic/OpenChange/MAPIStoreContactsMessage.h +++ /dev/null @@ -1,35 +0,0 @@ -/* MAPIStoreContactsMessage.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTORECONTACTSMESSAGE_H -#define MAPISTORECONTACTSMESSAGE_H - -#import "MAPIStoreGCSMessage.h" - -@interface MAPIStoreContactsMessage : MAPIStoreGCSMessage -{ - BOOL fetchedAttachments; -} - -@end - -#endif /* MAPISTORECONTACTSMESSAGE_H */ diff --git a/Attic/OpenChange/MAPIStoreContactsMessage.m b/Attic/OpenChange/MAPIStoreContactsMessage.m deleted file mode 100644 index 344f31c39..000000000 --- a/Attic/OpenChange/MAPIStoreContactsMessage.m +++ /dev/null @@ -1,1619 +0,0 @@ -/* MAPIStoreContactsMessage.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 Inverse inc - * - * Author: Wolfgang Sourdeau - * Ludovic Marcotte - * - * 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. - */ - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#import "MAPIStoreAttachment.h" -#import "MAPIStoreContactsAttachment.h" -#import "MAPIStoreContactsFolder.h" -#import "MAPIStoreContext.h" -#import "MAPIStorePropertySelectors.h" -#import "MAPIStoreSamDBUtils.h" -#import "MAPIStoreTypes.h" -#import "NSArray+MAPIStore.h" -#import "NSDate+MAPIStore.h" -#import "NSData+MAPIStore.h" -#import "NSObject+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreContactsMessage.h" - -#undef DEBUG -#include -#include -#include -#include -#include - -@implementation SOGoContactGCSEntry (MAPIStoreExtension) - -- (Class) mapistoreMessageClass -{ - return [MAPIStoreContactsMessage class]; -} - -@end - -@implementation MAPIStoreContactsMessage - -- (id) init -{ - if ((self = [super init])) - { - fetchedAttachments = NO; - } - - return self; -} - -// TODO: this should be combined with the version found -// in UIxContactEditor.m -- (CardElement *) _elementWithTag: (NSString *) tag - ofType: (NSString *) type - forCard: (NGVCard *) card -{ - NSArray *elements; - CardElement *element; - - elements = [card childrenWithTag: tag - andAttribute: @"type" havingValue: type]; - if ([elements count] > 0) - element = [elements objectAtIndex: 0]; - else - { - element = [CardElement new]; - [element autorelease]; - [element setTag: tag]; - [element addType: type]; - [card addChild: element]; - } - - return element; -} - -- (enum mapistore_error) getPidTagIconIndex: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - /* see http://msdn.microsoft.com/en-us/library/cc815472.aspx */ - *data = MAPILongValue (memCtx, 0x00000200); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAlternateRecipientAllowed: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx - -{ - return [self getYes: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagMessageFlags: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, MSGFLAG_READ); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagDeleteAfterSubmit: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx - -{ - return [self getNo: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagMessageClass: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = talloc_strdup (memCtx, "IPM.Contact"); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagSendInternetEncoding: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, 0x00065001); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagNormalizedSubject: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagDisplayName: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidFileUnder: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *surName, *givenName, *middleName; - NSMutableString *fileUnder; - CardElement *n; - - n = [[sogoObject vCard] n]; - surName = [n flattenedValueAtIndex: 0 - forKey: @""]; - fileUnder = [surName mutableCopy]; - [fileUnder autorelease]; - [fileUnder appendString: @","]; - givenName = [n flattenedValueAtIndex: 1 - forKey: @""]; - if ([givenName length] > 0) - [fileUnder appendFormat: @" %@", givenName]; - middleName = [n flattenedValueAtIndex: 2 - forKey: @""]; - if ([middleName length] > 0) - [fileUnder appendFormat: @" %@", middleName]; - - *data = [fileUnder asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidFileUnderId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, 0x00008017); /* what ol2003 sets */ - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAccount: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidLidEmail1EmailAddress: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagContactEmailAddresses: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *stringValue; - - stringValue = [[sogoObject vCard] preferredEMail]; - if (!stringValue) - stringValue = @""; - *data = [[NSArray arrayWithObject: stringValue] - asMVUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagEmsAbTargetAddress: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *stringValue; - - stringValue = [[sogoObject vCard] preferredEMail]; - *data = [[NSString stringWithFormat: @"SMTP:%@", stringValue] - asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagSearchKey: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *stringValue; - - stringValue = [[sogoObject vCard] preferredEMail]; - *data = [[stringValue dataUsingEncoding: NSASCIIStringEncoding] - asBinaryInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagMailPermission: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getYes: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagBody: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_SUCCESS; - NSString *stringValue; - - stringValue = [[sogoObject vCard] note]; - if ([stringValue length] > 0) - *data = [stringValue asUnicodeInMemCtx: memCtx]; - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidTagSensitivity: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getLongZero: data inMemCtx: memCtx]; -} - -// --------------------------------------------------------- -// Contact Name Properties [MS-OXOCNTC 2.2.1.1] -// --------------------------------------------------------- - -- (enum mapistore_error) getPidTagNickname: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *stringValue; - - stringValue = [[sogoObject vCard] nickname]; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagGeneration: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *stringValue; - - stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"] - flattenedValueAtIndex: 4 - forKey: @""]; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagSurname: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *stringValue; - - stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"] - flattenedValueAtIndex: 0 - forKey: @""]; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagMiddleName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *stringValue; - - stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"] - flattenedValueAtIndex: 2 - forKey: @""]; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagGivenName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *stringValue; - - stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"] - flattenedValueAtIndex: 1 - forKey: @""]; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagDisplayNamePrefix: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *stringValue; - - stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"] - flattenedValueAtIndex: 3 - forKey: @""]; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -// ------------------------------------------------------- -// Electronic Address Properties [MS-OXOCNTC 2.2.1.2] -// ------------------------------------------------------- - -enum { // [MS-OXOCNTC] 2.2.1.2.11 - AddressBookProviderEmailValueEmail1 = 0, - AddressBookProviderEmailValueEmail2, - AddressBookProviderEmailValueEmail3, - AddressBookProviderEmailValueBusinessFax, - AddressBookProviderEmailValueHomeFax, - AddressBookProviderEmailValuePrimaryFax -}; - -/* - Fetch Email1, Email2 and Email3 values from the vcard. - Returns nil if not found -*/ -- (NSString *) _fetchEmailAddress: (NSUInteger) position -{ - NSMutableArray *emails; - NSString *email, *stringValue = nil; - NGVCard *card; - NSUInteger count, max; - - card = [sogoObject vCard]; - - if (position == 1) - // Predefined email - return [card preferredEMail]; - - emails = [NSMutableArray array]; - [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] flattenedValuesForKey: @""]; - - if ([email caseInsensitiveCompare: [card preferredEMail]] != NSOrderedSame) - { - position--; - if (position == 1) - stringValue = email; - } - } - - return stringValue; -} - -/* - Store on *data the given email (position) - It can return MAPISTORE_ERR_NOT_FOUND if the email doesn't exist -*/ -- (enum mapistore_error) _getPidLidEmailAddress: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx - atPosition: (NSUInteger) position -{ - NSString *email; - - email = [self _fetchEmailAddress: position]; - if (!email) return MAPISTORE_ERR_NOT_FOUND; - - *data = [email asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidEmail1EmailAddress: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getPidLidEmailAddress: data inMemCtx: memCtx atPosition: 1]; -} - -- (enum mapistore_error) getPidLidEmail2EmailAddress: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getPidLidEmailAddress: data inMemCtx: memCtx atPosition: 2]; -} - -- (enum mapistore_error) getPidLidEmail3EmailAddress: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getPidLidEmailAddress: data inMemCtx: memCtx atPosition: 3]; -} - -- (enum mapistore_error) getPidLidEmail1OriginalDisplayName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidLidEmail1EmailAddress: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidEmail2OriginalDisplayName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidLidEmail2EmailAddress: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidEmail3OriginalDisplayName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidLidEmail3EmailAddress: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidEmail1AddressType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (![self _fetchEmailAddress: 1]) return MAPISTORE_ERR_NOT_FOUND; - - return [self getSMTPAddrType: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidEmail2AddressType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (![self _fetchEmailAddress: 2]) return MAPISTORE_ERR_NOT_FOUND; - - return [self getSMTPAddrType: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidEmail3AddressType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (![self _fetchEmailAddress: 3]) return MAPISTORE_ERR_NOT_FOUND; - - return [self getSMTPAddrType: data inMemCtx: memCtx]; -} - -/* - Store on *data a string with the display name for the given email (position) - It can return MAPISTORE_ERR_NOT_FOUND if the email doesn't exist -*/ -- (enum mapistore_error) _getPidLidEmailDisplayName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx - atPosition: (NSUInteger) position -{ - NGVCard *vCard; - NSString *fn, *email; - - email = [self _fetchEmailAddress: position]; - if (!email) return MAPISTORE_ERR_NOT_FOUND; - - vCard = [sogoObject vCard]; - fn = [vCard fn]; - - *data = [[NSString stringWithFormat: @"%@ (%@)", fn, email] - asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidEmail1DisplayName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getPidLidEmailDisplayName: data inMemCtx: memCtx atPosition: 1]; -} - -- (enum mapistore_error) getPidLidEmail2DisplayName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getPidLidEmailDisplayName: data inMemCtx: memCtx atPosition: 2]; -} - -- (enum mapistore_error) getPidLidEmail3DisplayName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getPidLidEmailDisplayName: data inMemCtx: memCtx atPosition: 3]; -} - -/* - Return an entry id (either one-off or addressbook entry) for the given email - It can return nil if the email doesn't exist -*/ -- (NSData *) _buildEntryIdForEmail: (NSUInteger) position -{ - NSString *email, *username; - NSData *data; - SOGoUserManager *mgr; - NSDictionary *contactInfos; - - email = [self _fetchEmailAddress: position]; - if (!email) return nil; - - // Try to figure out if this email is from local domain - mgr = [SOGoUserManager sharedUserManager]; - contactInfos = [mgr contactInfosForUserWithUIDorEmail: email]; - if (contactInfos) - { - username = [contactInfos objectForKey: @"sAMAccountName"]; - data = MAPIStoreInternalEntryId ([[self context] connectionInfo], username); - } - else - data = MAPIStoreExternalEntryId ([[sogoObject vCard] fn], email); - - return data; -} -/* - Store on *data an entryId for the given email (position) - It can return MAPISTORE_ERR_NOT_FOUND if the email doesn't exist -*/ -- (enum mapistore_error) _getPidLidEmailOriginalEntryId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx - atPosition: (NSUInteger) position -{ - NSData *value; - - value = [self _buildEntryIdForEmail: position]; - if (!value) return MAPISTORE_ERR_NOT_FOUND; - - *data = [value asBinaryInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidEmail1OriginalEntryId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getPidLidEmailOriginalEntryId: data - inMemCtx: memCtx - atPosition: 1]; -} - -- (enum mapistore_error) getPidLidEmail2OriginalEntryId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getPidLidEmailOriginalEntryId: data - inMemCtx: memCtx - atPosition: 2]; -} - -- (enum mapistore_error) getPidLidEmail3OriginalEntryId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getPidLidEmailOriginalEntryId: data - inMemCtx: memCtx - atPosition: 3]; -} - -- (enum mapistore_error) _getElement: (NSString *) elementTag - ofType: (NSString *) aType - excluding: (NSString *) aTypeToExclude - atPos: (NSUInteger) pos - inData: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSArray *elements; - CardElement *ce; - NSUInteger count, max; - NGVCard *vCard; - NSString *stringValue; - - stringValue = nil; - - vCard = [sogoObject vCard]; - elements = [[vCard childrenWithTag: elementTag] - cardElementsWithAttribute: @"type" - havingValue: aType]; - max = [elements count]; - for (count = 0; !stringValue && count < max; count++) - { - ce = [elements objectAtIndex: count]; - if (!aTypeToExclude - || ![ce hasAttribute: @"type" havingValue: aTypeToExclude]) - stringValue = [ce flattenedValueAtIndex: pos forKey: @""]; - } - - if (!stringValue) - return MAPISTORE_ERR_NOT_FOUND; - - *data = [stringValue asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagBusinessFaxNumber: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"tel" ofType: @"fax" excluding: nil - atPos: 0 inData: data inMemCtx: memCtx]; -} - -/* - [MS-OXOCNTC] 2.2.1.2.11 - https://msdn.microsoft.com/en-us/library/ee158427%28v=exchg.80%29.aspx -*/ -- (NSArray *) _buildAddressBookProviderEmailList -{ - NSMutableArray *list = [[NSMutableArray alloc] init]; - NSArray *elements; - - // Is there a fax number? - elements = [[[sogoObject vCard] childrenWithTag: @"tel"] - cardElementsWithAttribute: @"type" - havingValue: @"fax"]; - if ([elements count] > 0) - [list addObject: [NSNumber numberWithInteger: AddressBookProviderEmailValueBusinessFax]]; - - // How many different email addresses? - if ([self _fetchEmailAddress: 1]) - [list addObject: [NSNumber numberWithInteger: AddressBookProviderEmailValueEmail1]]; - else - return list; - if ([self _fetchEmailAddress: 2]) - [list addObject: [NSNumber numberWithInteger: AddressBookProviderEmailValueEmail2]]; - else - return list; - if ([self _fetchEmailAddress: 3]) - [list addObject: [NSNumber numberWithInteger: AddressBookProviderEmailValueEmail3]]; - - return list; -} - -- (enum mapistore_error) getPidLidAddressBookProviderArrayType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - // [MS-OXOCNTC] 2.2.1.2.12 - // https://msdn.microsoft.com/en-us/library/ee218011%28v=exchg.80%29.aspx - uint32_t value = 0; - NSArray *emailList = [self _buildAddressBookProviderEmailList]; - - if ([emailList count] > 0) - { - for (NSNumber *maskValue in emailList) - value |= 1 << [maskValue intValue]; - - *data = MAPILongValue (memCtx, value); - - return MAPISTORE_SUCCESS; - } - else - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidLidAddressBookProviderEmailList: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSArray *emailList = [self _buildAddressBookProviderEmailList]; - - if ([emailList count] > 0) - { - *data = [emailList asMVLongInMemCtx: memCtx]; - return MAPISTORE_SUCCESS; - } - else - return MAPISTORE_ERR_NOT_FOUND; -} - -// --------------------------------------------------------- -// Physical Address Properties [MS-OXOCNTC 2.2.1.3] -// --------------------------------------------------------- - -// Home Address - -- (enum mapistore_error) getPidTagHomeAddressStreet: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"adr" ofType: @"home" excluding: nil - atPos: 2 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagHomeAddressCity: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"adr" ofType: @"home" excluding: nil - atPos: 3 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagHomeAddressStateOrProvince: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"adr" ofType: @"home" excluding: nil - atPos: 4 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagHomeAddressPostalCode: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"adr" ofType: @"home" excluding: nil - atPos: 5 inData: data inMemCtx: memCtx]; -} -- (enum mapistore_error) getPidTagHomeAddressCountry: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"adr" ofType: @"home" excluding: nil - atPos: 6 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagHomeAddressPostOfficeBox: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"adr" ofType: @"home" excluding: nil - atPos: 0 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidHomeAddress: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"label" ofType: @"home" excluding: nil - atPos: 0 inData: data inMemCtx: memCtx]; -} - -// Work Address - -- (enum mapistore_error) getPidLidWorkAddressStreet: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"adr" ofType: @"work" excluding: nil - atPos: 2 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidWorkAddressCity: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"adr" ofType: @"work" excluding: nil - atPos: 3 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidWorkAddressState: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"adr" ofType: @"work" excluding: nil - atPos: 4 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidWorkAddressPostalCode: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"adr" ofType: @"work" excluding: nil - atPos: 5 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidWorkAddressCountry: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"adr" ofType: @"work" excluding: nil - atPos: 6 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidWorkAddressPostOfficeBox: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"adr" ofType: @"work" excluding: nil - atPos: 0 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidWorkAddress: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"label" ofType: @"work" excluding: nil - atPos: 0 inData: data inMemCtx: memCtx]; -} - -// Mailing Address - -- (enum mapistore_error) getPidTagStreetAddress: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"adr" ofType: @"pref" excluding: nil - atPos: 2 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagLocality: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"adr" ofType: @"pref" excluding: nil - atPos: 3 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagStateOrProvince: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"adr" ofType: @"pref" excluding: nil - atPos: 4 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagPostalCode: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"adr" ofType: @"pref" excluding: nil - atPos: 5 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagCountry: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"adr" ofType: @"pref" excluding: nil - atPos: 6 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagPostOfficeBox: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"adr" ofType: @"pref" excluding: nil - atPos: 0 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagPostalAddress: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"label" ofType: @"pref" excluding: nil - atPos: 0 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidPostalAddressId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSArray *elements; - CardElement *element; - uint32_t longValue = 0; - NGVCard *vCard; - - vCard = [sogoObject vCard]; - elements = [[vCard childrenWithTag: @"adr"] - cardElementsWithAttribute: @"type" - havingValue: @"pref"]; - if ([elements count] > 0) - { - element = [elements objectAtIndex: 0]; - if ([element hasAttribute: @"type" - 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. - } - *data = MAPILongValue (memCtx, longValue); - - return MAPISTORE_SUCCESS; -} - -// ------------------------------------------------------- -// Telephone Properties [MS-OXOCNTC 2.2.1.4] -// ------------------------------------------------------- - -- (enum mapistore_error) getPidTagPagerTelephoneNumber: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"tel" ofType: @"pager" excluding: nil - atPos: 0 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagBusinessTelephoneNumber: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"tel" ofType: @"work" excluding: @"fax" - atPos: 0 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagHomeTelephoneNumber: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"tel" ofType: @"home" excluding: @"fax" - atPos: 0 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagPrimaryTelephoneNumber: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"tel" ofType: @"pref" excluding: nil - atPos: 0 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagMobileTelephoneNumber: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"tel" ofType: @"cell" excluding: nil - atPos: 0 inData: data inMemCtx: memCtx]; -} - -// --------------------------------------------------------- -// Event Properties [MS-OXOCNTC 2.2.1.5] -// --------------------------------------------------------- - -- (enum mapistore_error) getPidTagBirthday: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSCalendarDate *dateValue; - NSString *stringValue; - enum mapistore_error rc = MAPISTORE_SUCCESS; - - stringValue = [[sogoObject vCard] bday]; - if ([stringValue length] != 0) - { - dateValue = [NSCalendarDate dateWithString: stringValue - calendarFormat: @"%Y-%m-%d"]; - //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; -} - -- (enum mapistore_error) getPidTagWeddingAnniversary: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSCalendarDate *dateValue; - NSString *stringValue; - enum mapistore_error rc = MAPISTORE_SUCCESS; - - stringValue = [[[sogoObject vCard] uniqueChildWithTag: @"x-ms-anniversary"] - flattenedValuesForKey: @""]; - if ([stringValue length] != 0) - { - dateValue = [NSCalendarDate dateWithString: stringValue - calendarFormat: @"%Y-%m-%d"]; - *data = [dateValue asFileTimeInMemCtx: memCtx]; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -// --------------------------------------------------------- -// Professional Properties [MS-OXOCNTC 2.2.1.6] -// --------------------------------------------------------- - -- (enum mapistore_error) getPidTagTitle: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *stringValue; - - stringValue = [[sogoObject vCard] title]; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagCompanyName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - CardElement *org; - - org = [[sogoObject vCard] org]; - *data = [[org flattenedValueAtIndex: 0 forKey: @""] - asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagDepartmentName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - CardElement *org; - - org = [[sogoObject vCard] org]; - *data = [[org flattenedValueAtIndex: 1 forKey: @""] - asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagOfficeLocation: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *stringValue; - enum mapistore_error rc = MAPISTORE_SUCCESS; - - stringValue = [[[sogoObject vCard] uniqueChildWithTag: @"x-ms-office"] - flattenedValuesForKey: @""]; - if ([stringValue length] != 0) - *data = [stringValue asUnicodeInMemCtx: memCtx]; - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidTagManagerName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *stringValue; - enum mapistore_error rc = MAPISTORE_SUCCESS; - - stringValue = [[[sogoObject vCard] uniqueChildWithTag: @"x-ms-manager"] - flattenedValuesForKey: @""]; - if ([stringValue length] != 0) - *data = [stringValue asUnicodeInMemCtx: memCtx]; - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidTagAssistant: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *stringValue; - enum mapistore_error rc = MAPISTORE_SUCCESS; - - stringValue = [[[sogoObject vCard] uniqueChildWithTag: @"x-ms-assistant"] - flattenedValuesForKey: @""]; - if ([stringValue length] != 0) - *data = [stringValue asUnicodeInMemCtx: memCtx]; - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidTagProfession: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *stringValue; - enum mapistore_error rc = MAPISTORE_SUCCESS; - - stringValue = [[sogoObject vCard] role]; - if (stringValue) - *data = [stringValue asUnicodeInMemCtx: memCtx]; - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -// --------------------------------------------------------- -// Contact Photo Properties [MS-OXOCNTC 2.2.1.8] -// --------------------------------------------------------- - -- (void) _fetchAttachmentParts -{ - NGVCardPhoto *photo; - MAPIStoreContactsAttachment *attachment; - NSString *encoding; - - photo = (NGVCardPhoto *) [[sogoObject vCard] firstChildWithTag: @"photo"]; - if (photo) - { - encoding = [[photo value: 0 ofAttribute: @"encoding"] uppercaseString]; - if ([encoding isEqualToString: @"B"] - || [encoding isEqualToString: @"BASE64"]) - { - attachment = [MAPIStoreContactsAttachment - mapiStoreObjectInContainer: self]; - [attachment setAID: 0]; - [attachment setPhoto: photo]; - [attachmentParts setObject: attachment forKey: @"photo"]; - } - } - - fetchedAttachments = YES; -} - -- (enum mapistore_error) getPidLidHasPicture: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!fetchedAttachments) - [self _fetchAttachmentParts]; - - *data = MAPIBoolValue (memCtx, ([attachmentParts count] > 0)); - - return MAPISTORE_SUCCESS; -} - -- (NSArray *) attachmentKeysMatchingQualifier: (EOQualifier *) qualifier - andSortOrderings: (NSArray *) sortOrderings -{ - if (!fetchedAttachments) - [self _fetchAttachmentParts]; - - return [super attachmentKeysMatchingQualifier: qualifier - andSortOrderings: sortOrderings]; -} - -- (id) lookupAttachment: (NSString *) childKey -{ - if (!fetchedAttachments) - [self _fetchAttachmentParts]; - - return [attachmentParts objectForKey: childKey]; -} - -- (void) _updatePhotoInVCard: (NGVCard *) card - fromProperties: (NSDictionary *) attachmentProps -{ - NSString *photoExt, *photoType, *content; - CardElement *photo; - - if ([[attachmentProps - objectForKey: MAPIPropertyKey (PR_ATTACHMENT_CONTACTPHOTO)] - boolValue]) - { - photoExt = [[attachmentProps - objectForKey: MAPIPropertyKey (PR_ATTACH_EXTENSION_UNICODE)] - uppercaseString]; - if ([photoExt isEqualToString: @".JPG"]) - photoType = @"JPEG"; - else if ([photoExt isEqualToString: @".PNG"]) - photoType = @"PNG"; - else if ([photoExt isEqualToString: @".BMP"]) - photoType = @"BMP"; - else if ([photoExt isEqualToString: @".GIF"]) - photoType = @"GIF"; - else - photoType = nil; - - content = [[attachmentProps - objectForKey: MAPIPropertyKey (PR_ATTACH_DATA_BIN)] - stringByEncodingBase64]; - if (photoType && content) - { - photo = [card uniqueChildWithTag: @"photo"]; - [photo setValue: 0 ofAttribute: @"type" - to: photoType]; - [photo setValue: 0 ofAttribute: @"encoding" - to: @"b"]; - [photo setSingleValue: [content stringByReplacingString: @"\n" - withString: @""] - atIndex: 0 forKey: @""]; - } - } -} - -// --------------------------------------------------------- -// Other Properties [MS-OXOCNTC 2.2.1.10] -// --------------------------------------------------------- - -- (enum mapistore_error) getPidTagSpouseName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *stringValue; - enum mapistore_error rc = MAPISTORE_SUCCESS; - - stringValue = [[[sogoObject vCard] uniqueChildWithTag: @"x-ms-spouse"] - flattenedValuesForKey: @""]; - if ([stringValue length] != 0) - *data = [stringValue asUnicodeInMemCtx: memCtx]; - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidLidInstantMessagingAddress: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *stringValue; - - stringValue = [[[sogoObject vCard] uniqueChildWithTag: @"x-aim"] - flattenedValuesForKey: @""]; - if (!stringValue) - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidFreeBusyLocation: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *stringValue; - enum mapistore_error rc = MAPISTORE_SUCCESS; - - stringValue = [[[sogoObject vCard] uniqueChildWithTag: @"fburl"] - flattenedValuesForKey: @""]; - if ([stringValue length] != 0) - *data = [stringValue asUnicodeInMemCtx: memCtx]; - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidTagPersonalHomePage: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"url" ofType: @"home" excluding: nil - atPos: 0 inData: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagBusinessHomePage: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getElement: @"url" ofType: @"work" excluding: nil - atPos: 0 inData: data inMemCtx: memCtx]; -} - -// --------------------------------------------------------- -// Permissions -// --------------------------------------------------------- - -- (NSString *) creator -{ - return [[[sogoObject vCard] uniqueChildWithTag: @"x-openchange-creator"] - flattenedValuesForKey: @""]; -} - -- (NSString *) owner -{ - return [self creator]; -} - -- (BOOL) subscriberCanReadMessage -{ - return [[self activeUserRoles] containsObject: SOGoRole_ObjectViewer]; -} - -// --------------------------------------------------------- -// Save -// --------------------------------------------------------- -- (void) saveDistList:(TALLOC_CTX *) memCtx -{ - [self warnWithFormat: @"IPM.DistList messages are ignored"]; -} - -- (void) saveContact:(TALLOC_CTX *) memCtx -{ - NSArray *elements, *units; - CardElement *element; - NGVCard *newCard; - MAPIStoreAttachment *attachment; - int postalAddressId; - id value; - - [self logWithFormat: @"setMAPIProperties: %@", properties]; - - newCard = [sogoObject vCard]; - [newCard setTag: @"vcard"]; - [newCard setVersion: @"3.0"]; - [newCard setProdID: @"-//Inverse inc.//OpenChange+SOGo//EN"]; - [newCard setProfile: @"vCard"]; - - // Decomposed fullname - [newCard setNWithFamily: [properties objectForKey: MAPIPropertyKey(PR_SURNAME_UNICODE)] - given: [properties objectForKey: MAPIPropertyKey(PR_GIVEN_NAME_UNICODE)] - additional: [properties objectForKey: MAPIPropertyKey(PR_MIDDLE_NAME_UNICODE)] - prefixes: [properties objectForKey: MAPIPropertyKey(PR_DISPLAY_NAME_PREFIX_UNICODE)] - suffixes: [properties objectForKey: MAPIPropertyKey(PR_GENERATION_UNICODE)]]; - - // - // display name - // - value = [properties objectForKey: MAPIPropertyKey(PR_DISPLAY_NAME_UNICODE)]; - if (value) - [newCard setFn: value]; - - // - // email addresses handling - // - elements = [newCard childrenWithTag: @"email"]; - value = [properties objectForKey: MAPIPropertyKey(PidLidEmail1EmailAddress)]; - if (value) - { - if ([elements count] > 0) - [[elements objectAtIndex: 0] setSingleValue: value forKey: @""]; - else - [newCard addEmail: value - types: [NSArray arrayWithObject: @"pref"]]; - } - value = [properties objectForKey: MAPIPropertyKey (PidLidEmail2EmailAddress)]; - if (value) - { - if ([elements count] > 1) - [[elements objectAtIndex: 1] setSingleValue: value forKey: @""]; - else - [newCard addEmail: value types: nil]; - } - value = [properties objectForKey: MAPIPropertyKey (PidLidEmail3EmailAddress)]; - if (value) - { - if ([elements count] > 2) - [[elements objectAtIndex: 2] setSingleValue: value forKey: @""]; - else - [newCard addEmail: value types: nil]; - } - - // - // work postal addresses handling - // - // Possible values for PidLidPostalAddressId are: - // - // 0x00000000 - No address is selected as the Mailing Address. - // 0x00000001 - The Home Address is the Mailing Address. - // 0x00000002 - The Work Address is the Mailing Address - // 0x00000003 - The Other Address is the Mailing Address. - // - // - postalAddressId = [[properties objectForKey: MAPIPropertyKey (PidLidPostalAddressId)] - intValue]; - - value = [properties objectForKey: MAPIPropertyKey(PidLidWorkAddress)]; - if ([value length]) - { - elements = [newCard childrenWithTag: @"label" - andAttribute: @"type" - havingValue: @"work"]; - if ([elements count] > 0) - element = [elements objectAtIndex: 0]; - else - { - element = [CardElement elementWithTag: @"label"]; - [element addAttribute: @"type" value: @"work"]; - [newCard addChild: element]; - } - if (postalAddressId == 2) - { - [element removeValue: @"pref" - fromAttribute: @"type"]; - [element addAttribute: @"type" - value: @"pref"]; - } - [element setSingleValue: value forKey: @""]; - } - - elements = [newCard childrenWithTag: @"adr" - andAttribute: @"type" - havingValue: @"work"]; - if ([elements count] > 0) - element = [elements objectAtIndex: 0]; - else - { - element = [CardElement elementWithTag: @"adr"]; - [element addAttribute: @"type" value: @"work"]; - [newCard addChild: element]; - } - if (postalAddressId == 2) - [element addAttribute: @"type" value: @"pref"]; - value = [properties objectForKey: MAPIPropertyKey(PidLidWorkAddressPostOfficeBox)]; - if (value) - [element setSingleValue: value atIndex: 0 forKey: @""]; - value = [properties objectForKey: MAPIPropertyKey(PidLidWorkAddressStreet)]; - if (value) - [element setSingleValue: value atIndex: 2 forKey: @""]; - value = [properties objectForKey: MAPIPropertyKey(PidLidWorkAddressCity)]; - if (value) - [element setSingleValue: value atIndex: 3 forKey: @""]; - value = [properties objectForKey: MAPIPropertyKey(PidLidWorkAddressState)]; - if (value) - [element setSingleValue: value atIndex: 4 forKey: @""]; - value = [properties objectForKey: MAPIPropertyKey(PidLidWorkAddressPostalCode)]; - if (value) - [element setSingleValue: value atIndex: 5 forKey: @""]; - value = [properties objectForKey: MAPIPropertyKey(PidLidWorkAddressCountry)]; - if (value) - [element setSingleValue: value atIndex: 6 forKey: @""]; - - // - // home postal addresses handling - // - value = [properties objectForKey: MAPIPropertyKey(PidLidHomeAddress)]; - if ([value length]) - { - elements = [newCard childrenWithTag: @"label" - andAttribute: @"type" - havingValue: @"home"]; - if ([elements count] > 0) - element = [elements objectAtIndex: 0]; - else - { - element = [CardElement elementWithTag: @"label"]; - [element addAttribute: @"type" value: @"home"]; - [newCard addChild: element]; - } - if (postalAddressId == 1) - { - [element removeValue: @"pref" - fromAttribute: @"type"]; - [element addAttribute: @"type" - value: @"pref"]; - } - [element setSingleValue: value forKey: @""]; - } - - elements = [newCard childrenWithTag: @"adr" - andAttribute: @"type" - havingValue: @"home"]; - if ([elements count] > 0) - element = [elements objectAtIndex: 0]; - else - { - element = [CardElement elementWithTag: @"adr"]; - [element addAttribute: @"type" value: @"home"]; - [newCard addChild: element]; - } - if (postalAddressId == 1) - [element addAttribute: @"type" value: @"pref"]; - - value = [properties objectForKey: MAPIPropertyKey(PR_HOME_ADDRESS_POST_OFFICE_BOX_UNICODE)]; - if (value) - [element setSingleValue: value atIndex: 0 forKey: @""]; - value = [properties objectForKey: MAPIPropertyKey( PR_HOME_ADDRESS_STREET_UNICODE)]; - if (value) - [element setSingleValue: value atIndex: 2 forKey: @""]; - value = [properties objectForKey: MAPIPropertyKey(PR_HOME_ADDRESS_CITY_UNICODE)]; - if (value) - [element setSingleValue: value atIndex: 3 forKey: @""]; - value = [properties objectForKey: MAPIPropertyKey(PR_HOME_ADDRESS_STATE_OR_PROVINCE_UNICODE)]; - if (value) - [element setSingleValue: value atIndex: 4 forKey: @""]; - value = [properties objectForKey: MAPIPropertyKey(PR_HOME_ADDRESS_POSTAL_CODE_UNICODE)]; - if (value) - [element setSingleValue: value atIndex: 5 forKey: @""]; - value = [properties objectForKey: MAPIPropertyKey(PR_HOME_ADDRESS_COUNTRY_UNICODE)]; - if (value) - [element setSingleValue: value atIndex: 6 forKey: @""]; - - - // - // telephone numbers: work, home, fax, pager and mobile - // - element = [self _elementWithTag: @"tel" ofType: @"work" forCard: newCard]; - value = [properties objectForKey: MAPIPropertyKey(PR_OFFICE_TELEPHONE_NUMBER_UNICODE)]; - if (value) - [element setSingleValue: value forKey: @""]; - - element = [self _elementWithTag: @"tel" ofType: @"home" forCard: newCard]; - value = [properties objectForKey: MAPIPropertyKey(PR_HOME_TELEPHONE_NUMBER_UNICODE)]; - if (value) - [element setSingleValue: value forKey: @""]; - - element = [self _elementWithTag: @"tel" ofType: @"fax" forCard: newCard]; - value = [properties objectForKey: MAPIPropertyKey(PR_BUSINESS_FAX_NUMBER_UNICODE)]; - if (value) - [element setSingleValue: value forKey: @""]; - - element = [self _elementWithTag: @"tel" ofType: @"pager" forCard: newCard]; - value = [properties objectForKey: MAPIPropertyKey(PR_PAGER_TELEPHONE_NUMBER_UNICODE)]; - if (value) - [element setSingleValue: value forKey: @""]; - - element = [self _elementWithTag: @"tel" ofType: @"cell" forCard: newCard]; - value = [properties objectForKey: MAPIPropertyKey(PR_MOBILE_TELEPHONE_NUMBER_UNICODE)]; - if (value) - [element setSingleValue: value forKey: @""]; - - - // - // job title, profession, nickname, company name, deparment, work url, im address/screen name and birthday - // - value = [properties objectForKey: MAPIPropertyKey(PR_TITLE_UNICODE)]; - if (value) - [newCard setTitle: value]; - - value = [properties objectForKey: MAPIPropertyKey(PR_PROFESSION_UNICODE)]; - if (value) - { - [newCard setRole: value]; - } - - value = [properties objectForKey: MAPIPropertyKey(PR_NICKNAME_UNICODE)]; - if (value) - [newCard setNickname: value]; - - value = [properties objectForKey: MAPIPropertyKey(PR_DEPARTMENT_NAME_UNICODE)]; - if (value) - units = [NSArray arrayWithObject: value]; - else - units = nil; - - value = [properties objectForKey: MAPIPropertyKey(PR_COMPANY_NAME_UNICODE)]; - if (value) - [newCard setOrg: value units: units]; - - value = [properties objectForKey: MAPIPropertyKey(PR_BUSINESS_HOME_PAGE_UNICODE)]; - if (value) - { - [[self _elementWithTag: @"url" ofType: @"work" forCard: newCard] - setSingleValue: value forKey: @""]; - } - - value = [properties objectForKey: MAPIPropertyKey(PidLidInstantMessagingAddress)]; - if (value) - { - [[newCard uniqueChildWithTag: @"x-aim"] - setSingleValue: value forKey: @""]; - } - - value = [properties objectForKey: MAPIPropertyKey(PR_BIRTHDAY)]; - if (value) - { - [newCard setBday: [value descriptionWithCalendarFormat: @"%Y-%m-%d"]]; - } - - // - // wedding anniversary, spouse's name, manager's name, assistant's name, office location, freebusy location - // - value = [properties objectForKey: MAPIPropertyKey(PidTagWeddingAnniversary)]; - if (value) - { - [[newCard uniqueChildWithTag: @"x-ms-anniversary"] - setSingleValue: [value descriptionWithCalendarFormat: @"%Y-%m-%d"] - forKey: @""]; - } - - value = [properties objectForKey: MAPIPropertyKey(PR_SPOUSE_NAME_UNICODE)]; - if (value) - { - [[newCard uniqueChildWithTag: @"x-ms-spouse"] - setSingleValue: value forKey: @""]; - } - - value = [properties objectForKey: MAPIPropertyKey(PR_MANAGER_NAME_UNICODE)]; - if (value) - { - [[newCard uniqueChildWithTag: @"x-ms-manager"] - setSingleValue: value forKey: @""]; - } - - value = [properties objectForKey: MAPIPropertyKey(PR_ASSISTANT_UNICODE)]; - if (value) - { - [[newCard uniqueChildWithTag: @"x-ms-assistant"] - setSingleValue: value forKey: @""]; - } - - value = [properties objectForKey: MAPIPropertyKey(PR_OFFICE_LOCATION_UNICODE)]; - if (value) - { - [[newCard uniqueChildWithTag: @"x-ms-office"] - setSingleValue: value forKey: @""]; - } - - value = [properties objectForKey: MAPIPropertyKey(PidLidFreeBusyLocation)]; - if (value) - { - [[newCard uniqueChildWithTag: @"fburl"] - setSingleValue: value forKey: @""]; - } - - /* photo */ - if ([attachmentParts count] > 0) - { - attachment = [[attachmentParts allValues] objectAtIndex: 0]; - [self _updatePhotoInVCard: newCard - fromProperties: [attachment properties]]; - } - - /* Note */ - value = [properties objectForKey: MAPIPropertyKey (PR_BODY_UNICODE)]; - if (!value) - { - value = [properties objectForKey: MAPIPropertyKey (PR_HTML)]; - if (value) - { - value = [[NSString alloc] initWithData: value - encoding: NSUTF8StringEncoding]; - [value autorelease]; - value = [value htmlToText]; - } - } - if (value) - [newCard setNote: value]; - - /* Store the creator name for sharing purposes */ - if (isNew) - { - value = [[[self context] activeUser] login]; - [[newCard uniqueChildWithTag: @"x-openchange-creator"] - setSingleValue: value forKey: @""]; - } - - // - // we save the new/modified card - // - [sogoObject saveComponent: newCard]; - - [self updateVersions]; -} - -- (void) save:(TALLOC_CTX *) memCtx -{ - NSString *messageClass = [properties objectForKey: MAPIPropertyKey(PR_MESSAGE_CLASS_UNICODE)]; - if ([messageClass isEqualToString: @"IPM.DistList"]) - [self saveDistList: memCtx]; - else - [self saveContact: memCtx]; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreContactsMessageTable.h b/Attic/OpenChange/MAPIStoreContactsMessageTable.h deleted file mode 100644 index 0563f9b2e..000000000 --- a/Attic/OpenChange/MAPIStoreContactsMessageTable.h +++ /dev/null @@ -1,31 +0,0 @@ -/* MAPIStoreContactsMessageTable.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 MAPISTORECONTACTSMESSAGETABLE_H -#define MAPISTORECONTACTSMESSAGETABLE_H - -#import "MAPIStoreGCSMessageTable.h" - -@interface MAPIStoreContactsMessageTable : MAPIStoreGCSMessageTable -@end - -#endif /* MAPISTORECONTACTSMESSAGETABLE_H */ diff --git a/Attic/OpenChange/MAPIStoreContactsMessageTable.m b/Attic/OpenChange/MAPIStoreContactsMessageTable.m deleted file mode 100644 index b88158a26..000000000 --- a/Attic/OpenChange/MAPIStoreContactsMessageTable.m +++ /dev/null @@ -1,231 +0,0 @@ -/* MAPIStoreContactsMessageTable.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -#import -#import -#import -#import - -#import -#import -#import -#import -#import - -#import - -#import "MAPIStoreContactsMessage.h" -#import "MAPIStoreTypes.h" -#import "NSDate+MAPIStore.h" -#import "NSArray+MAPIStore.h" -#import "NSData+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreContactsMessageTable.h" - -#include - -static Class MAPIStoreContactsMessageK, NGMailAddressK, NSDataK, NSStringK; - -@implementation MAPIStoreContactsMessageTable - -+ (void) initialize -{ - MAPIStoreContactsMessageK = [MAPIStoreContactsMessage class]; - NSDataK = [NSData class]; - NSStringK = [NSString class]; - NGMailAddressK = [NGMailAddress class]; -} - -+ (Class) childObjectClass -{ - return MAPIStoreContactsMessageK; -} - -- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property -{ - static NSMutableDictionary *knownProperties = nil; - - if (!knownProperties) - { - knownProperties = [NSMutableDictionary new]; - [knownProperties setObject: @"c_mail" - forKey: MAPIPropertyKey (PidLidEmail1EmailAddress)]; - [knownProperties setObject: @"c_mail" - forKey: MAPIPropertyKey (PidLidEmail2EmailAddress)]; - [knownProperties setObject: @"c_mail" - forKey: MAPIPropertyKey (PidLidEmail3EmailAddress)]; - [knownProperties setObject: @"c_cn" - forKey: MAPIPropertyKey (PidLidFileUnder)]; - [knownProperties setObject: @"c_cn" - forKey: MAPIPropertyKey (PidTagDisplayName)]; - [knownProperties setObject: @"c_cn" - forKey: MAPIPropertyKey (PidTagSubject)]; - } - - return [knownProperties objectForKey: MAPIPropertyKey (property)]; -} - -/* restrictions */ - -- (MAPIRestrictionState) evaluatePropertyRestriction: (struct mapi_SPropertyRestriction *) res - intoQualifier: (EOQualifier **) qualifier -{ - MAPIRestrictionState rc; - EOAndQualifier *andQualifier; - EOKeyValueQualifier *fullNameQualifier, *emailQualifier; - NSString *fullName, *email; - SEL operator; - id value, ngAddress; - - value = NSObjectFromMAPISPropValue (&res->lpProp); - switch ((uint32_t) res->ulPropTag) - { - case PR_MESSAGE_CLASS_UNICODE: - if ([value isEqualToString: @"IPM.Contact"]) - rc = MAPIRestrictionStateAlwaysTrue; - else - rc = MAPIRestrictionStateAlwaysFalse; - break; - - case PR_SENSITIVITY: - rc = MAPIRestrictionStateAlwaysTrue; - break; - case PidLidAddressBookProviderArrayType: - case PidLidAddressBookProviderEmailList: - /* FIXME: this is a hack. We should return a real qualifier here */ - rc = MAPIRestrictionStateAlwaysTrue; - break; - - case PidLidEmail1OriginalDisplayName: - case PidLidEmail2OriginalDisplayName: - case PidLidEmail3OriginalDisplayName: - rc = MAPIRestrictionStateAlwaysFalse; - value = NSObjectFromMAPISPropValue (&res->lpProp); - if (value && [value isKindOfClass: NSStringK]) - { - rc = MAPIRestrictionStateNeedsEval; - ngAddress = [[NGMailAddressParser mailAddressParserWithString: value] - parse]; - if ([ngAddress isKindOfClass: NGMailAddressK]) - { - operator = [self operatorFromRestrictionOperator: res->relop]; - fullName = [ngAddress displayName]; - email = [ngAddress address]; - emailQualifier = [[EOKeyValueQualifier alloc] - initWithKey: @"c_mail" - operatorSelector: operator - value: email]; - if ([fullName length] > 0) - { - fullNameQualifier = [[EOKeyValueQualifier alloc] - initWithKey: @"c_cn" - operatorSelector: operator - value: fullName]; - andQualifier = [[EOAndQualifier alloc] - initWithQualifiers: - emailQualifier, fullNameQualifier, nil]; - [fullNameQualifier release]; - [emailQualifier release]; - *qualifier = andQualifier; - } - else - *qualifier = emailQualifier; - [*qualifier autorelease]; - } - } - break; - case PidLidEmail1AddressType: - case PidLidEmail2AddressType: - case PidLidEmail3AddressType: - if ([value isEqualToString: @"SMTP"]) - rc = MAPIRestrictionStateAlwaysTrue; - else - rc = MAPIRestrictionStateAlwaysFalse; - break; - - default: - rc = [super evaluatePropertyRestriction: res intoQualifier: qualifier]; - } - - return rc; -} - -- (MAPIRestrictionState) evaluateContentRestriction: (struct mapi_SContentRestriction *) res - intoQualifier: (EOQualifier **) qualifier -{ - MAPIRestrictionState rc; - id value; - - value = NSObjectFromMAPISPropValue (&res->lpProp); - if ([value isKindOfClass: NSDataK]) - { - value = [[NSString alloc] initWithData: value - encoding: NSUTF8StringEncoding]; - [value autorelease]; - } - else if (![value isKindOfClass: NSStringK]) - [NSException raise: @"MAPIStoreTypeConversionException" - format: @"unhandled content restriction for class '%@'", - NSStringFromClass ([value class])]; - - switch (res->ulPropTag) - { - case PR_MESSAGE_CLASS_UNICODE: /* FIXME: should make use of c_component here */ - if ([value isEqualToString: @"IPM.Contact"]) - rc = MAPIRestrictionStateAlwaysTrue; - else - rc = MAPIRestrictionStateAlwaysFalse; - break; - default: - rc = [super evaluateContentRestriction: res intoQualifier: qualifier]; - } - - return rc; -} - -/* sorting */ - -- (NSString *) sortIdentifierForProperty: (enum MAPITAGS) property -{ - static NSMutableDictionary *knownProperties = nil; - - if (!knownProperties) - { - knownProperties = [NSMutableDictionary new]; - [knownProperties setObject: @"c_cn" - forKey: MAPIPropertyKey (PidLidFileUnder)]; - [knownProperties setObject: @"c_cn" - forKey: MAPIPropertyKey (PidTagDisplayName)]; - [knownProperties setObject: @"c_cn" - forKey: MAPIPropertyKey (PidTagSubject)]; - [knownProperties setObject: @"c_cn" - forKey: MAPIPropertyKey (PidTagNormalizedSubject)]; - /* Use by oxcfxics to sort the latest first */ - [knownProperties setObject: @"c_lastmodified" - forKey: MAPIPropertyKey (PidTagMessageDeliveryTime)]; - } - - return [knownProperties objectForKey: MAPIPropertyKey (property)]; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreContext.h b/Attic/OpenChange/MAPIStoreContext.h deleted file mode 100644 index 4bde9d79a..000000000 --- a/Attic/OpenChange/MAPIStoreContext.h +++ /dev/null @@ -1,125 +0,0 @@ -/* MAPIStoreContext.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 MAPISTORECONTEXT_H -#define MAPISTORECONTEXT_H - -#include - -#import - -@class NSArray; -@class NSFileHandle; -@class NSMutableArray; -@class NSMutableDictionary; -@class NSString; -@class NSURL; - -@class EOQualifier; - -@class WOContext; - -@class SOGoFolder; -@class SOGoMAPIFSFolder; -@class SOGoObject; -@class SOGoUser; - -@class MAPIStoreAuthenticator; -@class MAPIStoreAttachment; -@class MAPIStoreAttachmentTable; -@class MAPIStoreFolder; -@class MAPIStoreMessage; -@class MAPIStoreTable; -@class MAPIStoreUserContext; - -@interface MAPIStoreContext : NSObject -{ - struct mapistore_connection_info *connInfo; - NSMutableArray *containersBag; - SOGoUser *activeUser; /* the user accessing the resource */ - MAPIStoreUserContext *userContext; /* the owner or the resource */ - NSURL *contextUrl; -} - -+ (struct mapistore_contexts_list *) listAllContextsForUser: (NSString *) userName - withIndexing: (struct indexing_context *) indexing - inMemCtx: (TALLOC_CTX *) memCtx; -+ (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName - withIndexing: (struct indexing_context *) indexing - inMemCtx: (TALLOC_CTX *) memCtx; -+ (enum mapistore_error) createRootFolder: (NSString **) mapistoreUriP - withFID: (uint64_t ) fid - andName: (NSString *) folderName - forUser: (NSString *) username - withRole: (enum mapistore_context_role) role; - -+ (enum mapistore_error) openContext: (MAPIStoreContext **) contextPtr - withURI: (const char *) newUri - connectionInfo: (struct mapistore_connection_info *) newConnInfo - andTDBIndexing: (struct indexing_context *) indexing; - -- (id) initFromURL: (NSURL *) newUri - withConnectionInfo: (struct mapistore_connection_info *) newConnInfo - andTDBIndexing: (struct indexing_context *) indexing; - -- (NSURL *) url; -- (struct mapistore_connection_info *) connectionInfo; - -- (MAPIStoreUserContext *) userContext; - -- (SOGoUser *) activeUser; - -// - (id) lookupObject: (NSString *) objectURLString; - -/* backend methods */ -- (enum mapistore_error) getPath: (char **) path - ofFMID: (uint64_t) fmid - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getRootFolder: (MAPIStoreFolder **) folderPtr - withFID: (uint64_t) fmid; - -/* util methods */ -- (NSString *) extractChildNameFromURL: (NSString *) childURL - andFolderURLAt: (NSString **) folderURL; - -- (uint64_t) idForObjectWithKey: (NSString *) key - inFolderURL: (NSString *) folderURL; -- (NSArray *) getNewFMIDs: (uint64_t) max; -- (uint64_t) getNewChangeNumber; -- (NSArray *) getNewChangeNumbers: (uint64_t) max; - -/* subclass methods */ -+ (NSString *) MAPIModuleName; -+ (enum mapistore_context_role) MAPIContextRole; -+ (NSString *) - createRootSecondaryFolderWithFID: (uint64_t) fid - andName: (NSString *) folderName - forUser: (NSString *) userName; -- (Class) MAPIStoreFolderClass; - -/* the top-most parent of the context folder: SOGoMailAccount, - SOGoCalendarFolders, ... */ -- (id) rootSOGoFolder; - -@end - -#endif /* MAPISTORECONTEXT_H */ diff --git a/Attic/OpenChange/MAPIStoreContext.m b/Attic/OpenChange/MAPIStoreContext.m deleted file mode 100644 index 32a01e147..000000000 --- a/Attic/OpenChange/MAPIStoreContext.m +++ /dev/null @@ -1,644 +0,0 @@ -/* MAPIStoreContext.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -#import -#import -#import -#import - -#import -#import -#import - -#import -#import - -#import "MAPIStoreAttachment.h" -#import "MAPIStoreFallbackContext.h" -#import "MAPIStoreFolder.h" -#import "MAPIStoreFolderTable.h" -#import "MAPIStoreMapping.h" -#import "MAPIStoreMessage.h" -#import "MAPIStoreMessageTable.h" -#import "MAPIStoreFAIMessage.h" -#import "MAPIStoreFAIMessageTable.h" -#import "MAPIStoreTypes.h" -#import "MAPIStoreUserContext.h" -#import "NSArray+MAPIStore.h" -#import "NSObject+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreContext.h" - -#undef DEBUG -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* TODO: homogenize method names and order of parameters */ - -@implementation MAPIStoreContext : NSObject - -/* sogo://username:password@{contacts,calendar,tasks,journal,notes,mail}/dossier/id */ - -static Class NSExceptionK, MAPIStoreFallbackContextK, SOGoObjectK; - -static NSMutableDictionary *contextClassMapping; - -+ (void) initialize -{ - NSArray *classes; - Class currentClass; - NSUInteger count, max; - NSString *moduleName; - - NSExceptionK = [NSException class]; - SOGoObjectK = [SOGoObject class]; - - contextClassMapping = [NSMutableDictionary new]; - classes = GSObjCAllSubclassesOfClass (self); - max = [classes count]; - for (count = 0; count < max; count++) - { - currentClass = [classes objectAtIndex: count]; - moduleName = [currentClass MAPIModuleName]; - if (moduleName) - { - [contextClassMapping setObject: currentClass - forKey: moduleName]; - NSLog (@" registered class '%@' as handler of '%@' contexts", - NSStringFromClass (currentClass), moduleName); - } - } - - MAPIStoreFallbackContextK = [MAPIStoreFallbackContext class]; -} - -+ (struct mapistore_contexts_list *) listAllContextsForUser: (NSString *) userName - withIndexing: (struct indexing_context *) indexing - inMemCtx: (TALLOC_CTX *) memCtx -{ - struct mapistore_contexts_list *list, *current; - NSArray *classes; - Class currentClass; - NSUInteger count, max; - - list = NULL; - - // User context is activated on initialization - [MAPIStoreUserContext userContextWithUsername: userName - andTDBIndexing: indexing]; - - classes = GSObjCAllSubclassesOfClass (self); - max = [classes count]; - for (count = 0; count < max; count++) - { - currentClass = [classes objectAtIndex: count]; - current = [currentClass listContextsForUser: userName - withIndexing: indexing - inMemCtx: memCtx]; - if (current) - DLIST_CONCATENATE(list, current, void); - } - - return list; -} - -+ (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName - withIndexing: (struct indexing_context *) indexing - inMemCtx: (TALLOC_CTX *) memCtx -{ - return NULL; -} - -static Class -MAPIStoreLookupContextClassByRole (Class self, enum mapistore_context_role role) -{ - static NSMutableDictionary *classMapping = nil; - Class currentClass; - enum mapistore_context_role classRole; - NSNumber *roleNbr; - NSArray *classes; - NSUInteger count, max; - - if (!classMapping) - { - classMapping = [NSMutableDictionary new]; - classes = GSObjCAllSubclassesOfClass (self); - max = [classes count]; - for (count = 0; count < max; count++) - { - currentClass = [classes objectAtIndex: count]; - classRole = [currentClass MAPIContextRole]; - if (classRole != -1) - { - roleNbr = [NSNumber numberWithUnsignedInt: classRole]; - [classMapping setObject: currentClass - forKey: roleNbr]; - } - } - } - - roleNbr = [NSNumber numberWithUnsignedInt: role]; - - return [classMapping objectForKey: roleNbr]; -} - -+ (enum mapistore_error) createRootFolder: (NSString **) mapistoreUriP - withFID: (uint64_t) fid - andName: (NSString *) folderName - forUser: (NSString *) userName - withRole: (enum mapistore_context_role) role -{ - Class contextClass; - NSString *mapistoreURI; - enum mapistore_error rc = MAPISTORE_SUCCESS; - - contextClass = MAPIStoreLookupContextClassByRole (self, role); - if (!contextClass) - contextClass = MAPIStoreFallbackContextK; - - mapistoreURI = [contextClass createRootSecondaryFolderWithFID: fid - andName: folderName - forUser: userName]; - if (!mapistoreURI && contextClass != MAPIStoreFallbackContextK) - mapistoreURI = [MAPIStoreFallbackContextK createRootSecondaryFolderWithFID: fid - andName: folderName - forUser: userName]; - if (mapistoreURI) - *mapistoreUriP = mapistoreURI; - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -static inline NSURL *CompleteURLFromMapistoreURI (const char *uri) -{ - NSString *urlString; - NSURL *completeURL; - - urlString = [NSString stringWithFormat: @"sogo://%@", - [NSString stringWithUTF8String: uri]]; - if (![urlString hasSuffix: @"/"]) - urlString = [urlString stringByAppendingString: @"/"]; - completeURL = [NSURL URLWithString: urlString]; - - return completeURL; -} - -+ (enum mapistore_error) openContext: (MAPIStoreContext **) contextPtr - withURI: (const char *) newUri - connectionInfo: (struct mapistore_connection_info *) newConnInfo - andTDBIndexing: (struct indexing_context *) indexing -{ - MAPIStoreContext *context; - Class contextClass; - NSString *module; - NSURL *baseURL; - enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND; - - context = nil; - - baseURL = CompleteURLFromMapistoreURI (newUri); - if (baseURL) - { - module = [baseURL host]; - if (module) - { - contextClass = [contextClassMapping objectForKey: module]; - if (contextClass) - { - context = [[contextClass alloc] initFromURL: baseURL - withConnectionInfo: newConnInfo - andTDBIndexing: indexing]; - if (context) - { - [context autorelease]; - rc = MAPISTORE_SUCCESS; - *contextPtr = context; - } - } - else - NSLog (@"ERROR: unrecognized module name '%@'", module); - } - } - else - NSLog (@"ERROR: url could not be parsed"); - - return rc; -} - -- (id) init -{ - if ((self = [super init])) - { - activeUser = nil; - userContext = nil; - contextUrl = nil; - containersBag = [NSMutableArray new]; - } - - return self; -} - -- (id) initFromURL: (NSURL *) newUrl - withConnectionInfo: (struct mapistore_connection_info *) newConnInfo - andTDBIndexing: (struct indexing_context *) indexing -{ - NSString *username; - - if (newConnInfo == NULL) - { - return nil; - } - - if ((self = [self init])) - { - ASSIGN (contextUrl, newUrl); - - username = [newUrl user]; - if ([username length] == 0) - { - [self errorWithFormat: - @"attempt to instantiate a context with an empty owner"]; - [self release]; - return nil; - } - - ASSIGN (userContext, - [MAPIStoreUserContext userContextWithUsername: username - andTDBIndexing: indexing]); - connInfo = newConnInfo; - username = [NSString stringWithUTF8String: newConnInfo->username]; - ASSIGN (activeUser, [SOGoUser userWithLogin: username]); - if (!activeUser) - { - [self errorWithFormat: @"user '%@' not found in SOGo environment", - username]; - [self release]; - return nil; - } - } - - return self; -} - -- (void) dealloc -{ - [contextUrl release]; - [userContext release]; - [containersBag release]; - - [super dealloc]; -} - -- (MAPIStoreUserContext *) userContext -{ - return userContext; -} - -- (NSURL *) url -{ - return contextUrl; -} - -- (struct mapistore_connection_info *) connectionInfo -{ - return connInfo; -} - -- (SOGoUser *) activeUser -{ - return activeUser; -} - -- (enum mapistore_error) getPath: (char **) path - ofFMID: (uint64_t) fmid - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - NSString *objectURL, *url; - - url = [contextUrl absoluteString]; - // FIXME transform percent escapes but not for user part of the url - //[xxxx stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding]; - objectURL = [[userContext mapping] urlFromID: fmid]; - if (objectURL) - { - if ([objectURL hasPrefix: url]) - { - *path = [[objectURL substringFromIndex: 7] asUnicodeInMemCtx: memCtx]; - [self logWithFormat: @"found path '%s' for fmid 0x%.16"PRIx64"", *path, fmid]; - rc = MAPISTORE_SUCCESS; - } - else - { - [self logWithFormat: @"context (%@, %@) does not contain " - @"found fmid: 0x%.16"PRIx64"", objectURL, url, fmid]; - *path = NULL; - rc = MAPISTORE_SUCCESS; - } - } - else - { - [self errorWithFormat: @"%s: you should *never* get here", __PRETTY_FUNCTION__]; - *path = NULL; - rc = MAPISTORE_SUCCESS; - } - - return rc; -} - -- (void) ensureContextFolder -{ -} - -- (enum mapistore_error) getRootFolder: (MAPIStoreFolder **) folderPtr - withFID: (uint64_t) newFid -{ - enum mapistore_error rc; - MAPIStoreFolder *baseFolder; - SOGoFolder *currentFolder; - WOContext *woContext; - NSString *path; - NSArray *pathComponents; - NSUInteger count, max; - - [userContext activate]; - woContext = [userContext woContext]; - - [self ensureContextFolder]; - currentFolder = [self rootSOGoFolder]; - [containersBag addObject: currentFolder]; - - /* HACK: - -[NSURL path] returns unescaped strings in theory. In pratice, sometimes - it does, sometimes not. Therefore we use the result of our own - implementation of -[NSString - stringByReplacingPercentEscapeUsingEncoding:], which returns nil if the - original string contains non-ascii chars, from which we can determine - whether the path was unescaped or not. */ - path = [[contextUrl path] - stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding]; - if (!path) - path = [contextUrl path]; - - if ([path hasPrefix: @"/"]) - path = [path substringFromIndex: 1]; - if ([path hasSuffix: @"/"]) - path = [path substringToIndex: [path length] - 1]; - if ([path length] > 0) - { - pathComponents = [path componentsSeparatedByString: @"/"]; - max = [pathComponents count]; - for (count = 0; currentFolder && count < max; count++) - { - [woContext setClientObject: currentFolder]; - currentFolder = [currentFolder - lookupName: [pathComponents objectAtIndex: count] - inContext: woContext - acquire: NO]; - if ([currentFolder isKindOfClass: SOGoObjectK]) /* class common to all - SOGo folder types */ - [containersBag addObject: currentFolder]; - else - currentFolder = nil; - } - } - - if (currentFolder) - { - baseFolder = [[self MAPIStoreFolderClass] - mapiStoreObjectWithSOGoObject: currentFolder - inContainer: nil]; - [baseFolder setContext: self]; - - if ([[userContext sogoUser] isEqual: activeUser] - || [baseFolder subscriberCanReadMessages]) - { - *folderPtr = baseFolder; - rc = MAPISTORE_SUCCESS; - } - else - rc = MAPISTORE_ERR_DENIED; - - } - else if ([[userContext sogoUser] isEqual: activeUser]) - rc = MAPISTORE_ERR_NOT_FOUND; - else - rc = MAPISTORE_ERR_DENIED; - - return rc; -} - -/* utils */ - -- (NSString *) extractChildNameFromURL: (NSString *) objectURL - andFolderURLAt: (NSString **) folderURL; -{ - NSString *childKey; - NSRange lastSlash; - NSUInteger slashPtr; - - if ([objectURL hasSuffix: @"/"]) - objectURL = [objectURL substringToIndex: [objectURL length] - 2]; - lastSlash = [objectURL rangeOfString: @"/" - options: NSBackwardsSearch]; - if (lastSlash.location != NSNotFound) - { - slashPtr = NSMaxRange (lastSlash); - childKey = [objectURL substringFromIndex: slashPtr]; - if ([childKey length] == 0) - childKey = nil; - if (folderURL) - *folderURL = [objectURL substringToIndex: slashPtr]; - } - else - childKey = nil; - - return childKey; -} - -- (uint64_t) idForObjectWithKey: (NSString *) key - inFolderURL: (NSString *) folderURL -{ - NSString *childURL; - MAPIStoreMapping *mapping; - uint64_t mappingId; - enum mapistore_error ret; - - if (key) - childURL = [NSString stringWithFormat: @"%@%@", folderURL, - [key stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]]; - else - childURL = folderURL; - mapping = [userContext mapping]; - mappingId = [mapping idFromURL: childURL]; - if (mappingId == NSNotFound) - { - const char *owner; - - [self logWithFormat: @"No id exist yet for '%@', requesting one", childURL]; - owner = [[userContext username] UTF8String]; - ret = mapistore_indexing_get_new_folderID_as_user (connInfo->mstore_ctx, owner, &mappingId); - if (ret == MAPISTORE_SUCCESS) - [mapping registerURL: childURL withID: mappingId]; - else - [self errorWithFormat: @"Error trying to get new folder id (%d): %s", - ret, mapistore_errstr (ret)]; - } - - return mappingId; -} - -/* Get new change number from openchange db interface using - resource's owner user */ -- (uint64_t) getNewChangeNumber -{ - const char *owner; - enum MAPISTATUS retval; - uint64_t newVersionNumber; - - owner = [[userContext username] UTF8String]; - retval = openchangedb_get_new_changeNumber (connInfo->oc_ctx, owner, &newVersionNumber); - if (retval != MAPI_E_SUCCESS) - [NSException raise: @"MAPIStoreIOException" - format: @"Impossible to get new change number for %s: %s", owner, - mapi_get_errstr (retval)]; - - return newVersionNumber; -} - -/* Get new change numbers from openchange db interface using - resource's owner user */ -- (NSArray *) getNewChangeNumbers: (uint64_t) max -{ - const char *owner; - enum MAPISTATUS retval; - TALLOC_CTX *memCtx; - NSMutableArray *newChangeNumbers; - uint64_t count; - struct UI8Array_r *numbers; - NSString *newNumber; - - memCtx = talloc_new (NULL); - if (!memCtx) - [NSException raise: @"MAPIStoreIOException" - format: @"Not enough memory to allocate change numbers"]; - - newChangeNumbers = [NSMutableArray arrayWithCapacity: max]; - owner = [[userContext username] UTF8String]; - - retval = openchangedb_get_new_changeNumbers (connInfo->oc_ctx, memCtx, owner, max, &numbers); - if (retval != MAPI_E_SUCCESS || numbers->cValues != max) - { - talloc_free (memCtx); - [NSException raise: @"MAPIStoreIOException" - format: @"Failing to get %d new change numbers: %s", max, - mapi_get_errstr (retval)]; - } - - for (count = 0; count < max; count++) - { - newNumber = [NSString stringWithUnsignedLongLong: numbers->lpui8[count]]; - [newChangeNumbers addObject: newNumber]; - } - - talloc_free (memCtx); - - return newChangeNumbers; -} - -/* Get new fmids from mapistore_indexing interface using resource's - owner user */ -- (NSArray *) getNewFMIDs: (uint64_t) max -{ - const char *owner; - enum mapistore_error ret; - NSMutableArray *newFMIDs; - NSString *newNumber; - uint64_t count, newFID; - - newFMIDs = [NSMutableArray arrayWithCapacity: max]; - /* Get the resource's owner name */ - owner = [[userContext username] UTF8String]; - - for (count = 0; count < max; count++) - { - ret = mapistore_indexing_get_new_folderID_as_user (connInfo->mstore_ctx, owner, &newFID); - if (ret != MAPISTORE_SUCCESS) - [NSException raise: @"MAPIStoreIOException" - format: @"Impossible to get new fmid for %s", owner]; - - newNumber = [NSString stringWithUnsignedLongLong: newFID]; - [newFMIDs addObject: newNumber]; - } - - return newFMIDs; -} - -/* subclasses */ - -+ (NSString *) MAPIModuleName -{ - [self subclassResponsibility: _cmd]; - - return nil; -} - -+ (enum mapistore_context_role) MAPIContextRole -{ - return -1; -} - -+ (NSString *) - createRootSecondaryFolderWithFID: (uint64_t) fid - andName: (NSString *) folderName - forUser: (NSString *) userName -{ - [self subclassResponsibility: _cmd]; - - return nil; -} - -- (Class) MAPIStoreFolderClass -{ - [self subclassResponsibility: _cmd]; - - return nil; -} - -- (id) rootSOGoFolder -{ - [self subclassResponsibility: _cmd]; - - return nil; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreDBBaseContext.h b/Attic/OpenChange/MAPIStoreDBBaseContext.h deleted file mode 100644 index 62f5bd489..000000000 --- a/Attic/OpenChange/MAPIStoreDBBaseContext.h +++ /dev/null @@ -1,32 +0,0 @@ -/* MAPIStoreDBBaseContext.h - this file is part of SOGo - * - * Copyright (C) 2012 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 MAPISTOREDBBASECONTEXT_H -#define MAPISTOREDBBASECONTEXT_H - -#import "MAPIStoreContext.h" - -@interface MAPIStoreDBBaseContext : MAPIStoreContext - -@end - -#endif /* MAPISTOREDBBASECONTEXT_H */ diff --git a/Attic/OpenChange/MAPIStoreDBBaseContext.m b/Attic/OpenChange/MAPIStoreDBBaseContext.m deleted file mode 100644 index 22a15bc85..000000000 --- a/Attic/OpenChange/MAPIStoreDBBaseContext.m +++ /dev/null @@ -1,114 +0,0 @@ -/* MAPIStoreDBBaseContext.m - this file is part of SOGo - * - * Copyright (C) 2012-2014 Inverse inc. - * - * 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. - */ - -/* A generic parent class for all context that will store their data on the - disk in the form of a plist. */ - -#import -#import -#import - -#import - -#import "MAPIStoreDBFolder.h" -#import "MAPIStoreMapping.h" -#import "MAPIStoreUserContext.h" -#import - -#import "MAPIStoreDBBaseContext.h" - -#undef DEBUG -#include - -static Class MAPIStoreDBFolderK; - -@implementation MAPIStoreDBBaseContext - -+ (void) initialize -{ - MAPIStoreDBFolderK = [MAPIStoreDBFolder class]; -} - -+ (NSString *) MAPIModuleName -{ - return nil; -} - -- (Class) MAPIStoreFolderClass -{ - return MAPIStoreDBFolderK; -} - -- (void) ensureContextFolder -{ - SOGoCacheGCSFolder *currentFolder; - NSArray *parts; - NSMutableArray *folders; - NSString *folderName; - NSUInteger count, max; - - parts = [[contextUrl path] componentsSeparatedByString: @"/"]; - max = [parts count]; - folders = [NSMutableArray arrayWithCapacity: max]; - - /* build the folder chain */ - currentFolder = [self rootSOGoFolder]; - [folders addObject: currentFolder]; - for (count = 1; count < max; count++) - { - folderName = [parts objectAtIndex: count]; - if ([folderName length] > 0) - { - currentFolder = [SOGoCacheGCSFolder objectWithName: folderName - inContainer: currentFolder]; - [folders addObject: currentFolder]; - } - } - - /* ensure each folder in the chain actually exists, so that it becomes - "listable" in further operations */ - max = [folders count]; - for (count = 0; count < max; count++) - { - currentFolder = [folders objectAtIndex: count]; - [currentFolder reloadIfNeeded]; - if ([currentFolder isNew]) - [currentFolder save]; - } -} - -- (id) rootSOGoFolder -{ - SOGoCacheGCSFolder *folder; - - [userContext ensureFolderTableExists]; - - folder = [SOGoCacheGCSFolder objectWithName: [isa MAPIModuleName] - inContainer: nil]; - [folder setTableUrl: [userContext folderTableURL]]; - // [folder reloadIfNeeded]; - - /* we don't need to set the "path prefix" of the folder since the module - name is used as the label for the top folder */ - - return folder; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreDBFolder.h b/Attic/OpenChange/MAPIStoreDBFolder.h deleted file mode 100644 index 1da4d1bd9..000000000 --- a/Attic/OpenChange/MAPIStoreDBFolder.h +++ /dev/null @@ -1,43 +0,0 @@ -/* MAPIStoreDBFolder.h - this file is part of SOGo - * - * Copyright (C) 2012 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. - */ - -#ifndef MAPISTOREDBFOLDER_H -#define MAPISTOREDBFOLDER_H - -#import "MAPIStoreFolder.h" - -extern NSString *MAPIStoreRightReadItems; -extern NSString *MAPIStoreRightCreateItems; -extern NSString *MAPIStoreRightEditOwn; -extern NSString *MAPIStoreRightEditAll; -extern NSString *MAPIStoreRightDeleteOwn; -extern NSString *MAPIStoreRightDeleteAll; -extern NSString *MAPIStoreRightCreateSubfolders; -extern NSString *MAPIStoreRightFolderOwner; -extern NSString *MAPIStoreRightFolderContact; - -@interface MAPIStoreDBFolder : MAPIStoreFolder - -@end - - -#endif /* MAPISTOREDBFOLDER_H */ diff --git a/Attic/OpenChange/MAPIStoreDBFolder.m b/Attic/OpenChange/MAPIStoreDBFolder.m deleted file mode 100644 index 4fc954112..000000000 --- a/Attic/OpenChange/MAPIStoreDBFolder.m +++ /dev/null @@ -1,382 +0,0 @@ -/* MAPIStoreDBFolder.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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 - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import "MAPIStoreContext.h" -#import "MAPIStoreDBFolderTable.h" -#import "MAPIStoreDBMessage.h" -#import "MAPIStoreDBMessageTable.h" -#import "MAPIStoreMapping.h" -#import "MAPIStoreTypes.h" -#import "MAPIStoreUserContext.h" -#import -#import "SOGoMAPIDBMessage.h" - -#import "MAPIStoreDBFolder.h" - -#undef DEBUG -#include -#include - -static Class EOKeyValueQualifierK, SOGoCacheGCSFolderK, MAPIStoreDBFolderK; - -@implementation MAPIStoreDBFolder - -+ (void) initialize -{ - EOKeyValueQualifierK = [EOKeyValueQualifier class]; - SOGoCacheGCSFolderK = [SOGoCacheGCSFolder class]; - MAPIStoreDBFolderK = [MAPIStoreDBFolder class]; -} - -- (void) setupAuxiliaryObjects -{ - [super setupAuxiliaryObjects]; - ASSIGN (sogoObject, dbFolder); -} - -- (MAPIStoreMessageTable *) messageTable -{ - return [MAPIStoreDBMessageTable tableForContainer: self]; -} - -- (MAPIStoreFolderTable *) folderTable -{ - return [MAPIStoreDBFolderTable tableForContainer: self]; -} - -- (enum mapistore_error) createFolder: (struct SRow *) aRow - withFID: (uint64_t) newFID - andKey: (NSString **) newKeyP -{ - enum mapistore_error rc; - NSString *folderName, *nameInContainer; - SOGoCacheGCSFolder *newFolder; - struct SPropValue *value; - - value = get_SPropValue_SRow (aRow, PidTagDisplayName); - if (value) - folderName = [NSString stringWithUTF8String: value->value.lpszW]; - else - { - value = get_SPropValue_SRow (aRow, PidTagDisplayName_string8); - if (value) - folderName = [NSString stringWithUTF8String: (const char *) value->value.lpszA]; - else - folderName = nil; - } - - if (folderName) - { - nameInContainer = [NSString stringWithFormat: @"0x%.16"PRIx64, - (unsigned long long) newFID]; - newFolder = [SOGoCacheGCSFolderK objectWithName: nameInContainer - inContainer: sogoObject]; - [newFolder reloadIfNeeded]; - [[newFolder properties] setObject: folderName - forKey: MAPIPropertyKey (PidTagDisplayName)]; - [newFolder save]; - *newKeyP = nameInContainer; - rc = MAPISTORE_SUCCESS; - } - else - rc = MAPISTORE_ERR_INVALID_PARAMETER; - - return rc; -} - -- (enum mapistore_error) moveCopyToFolder: (MAPIStoreFolder *) targetFolder - withNewName: (NSString *) newFolderName - isMove: (BOOL) isMove - isRecursive: (BOOL) isRecursive - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - NSString *path, *pathComponent, *targetPath, *newPath; - NSString *newURL; - MAPIStoreMapping *mapping; - NSRange slashRange; - - pathComponent = nil; - - if (isMove && ([targetFolder isKindOfClass: MAPIStoreDBFolderK] || !targetFolder)) - { - path = [sogoObject path]; - slashRange = [path rangeOfString: @"/" options: NSBackwardsSearch]; - if (slashRange.location == NSNotFound) - [NSException raise: @"MAPIStoreIOException" - format: @"db folder path must start with a '/'"]; - else - pathComponent = [path substringFromIndex: slashRange.location + 1]; - - if (targetFolder) - { - targetPath = [[targetFolder sogoObject] path]; - newPath = [NSString stringWithFormat: @"%@/%@", - targetPath, pathComponent]; - [dbFolder changePathTo: newPath - intoNewContainer: [targetFolder dbFolder]]; - } - else - [dbFolder changePathTo: [NSString stringWithFormat: @"/fallback/%@", pathComponent] - intoNewContainer: nil]; - - mapping = [self mapping]; - - if (targetFolder) - newURL = [NSString stringWithFormat: @"%@%@/", - [targetFolder url], pathComponent]; - else - newURL = [NSString stringWithFormat: @"sogo://%@@fallback/%@/", - [[self userContext] username], pathComponent]; - - [mapping updateID: [self objectId] - withURL: newURL]; - - [targetFolder cleanupCaches]; - - rc = MAPISTORE_SUCCESS; - } - else - rc = [super moveCopyToFolder: targetFolder withNewName: newFolderName - isMove: isMove - isRecursive: isRecursive - inMemCtx: memCtx]; - - return rc; -} - -- (MAPIStoreMessage *) createMessage -{ - MAPIStoreMessage *newMessage; - SOGoMAPIDBMessage *fsObject; - NSString *newKey; - - [[self userContext] activate]; - - newKey = [NSString stringWithFormat: @"%@.plist", - [SOGoObject globallyUniqueObjectId]]; - fsObject = [SOGoMAPIDBMessage objectWithName: newKey - inContainer: sogoObject]; - [fsObject setObjectType: MAPIMessageCacheObject]; - [fsObject reloadIfNeeded]; - newMessage = [MAPIStoreDBMessage mapiStoreObjectWithSOGoObject: fsObject - inContainer: self]; - - return newMessage; -} - -- (NSArray *) messageKeysMatchingQualifier: (EOQualifier *) qualifier - andSortOrderings: (NSArray *) sortOrderings -{ - NSArray *keys; - SOGoUser *ownerUser; - - ownerUser = [[self userContext] sogoUser]; - if ([[context activeUser] isEqual: ownerUser] - || [self subscriberCanReadMessages]) - { - [[self userContext] activate]; - keys = [(SOGoCacheGCSFolder *) sogoObject childKeysOfType: MAPIMessageCacheObject - includeDeleted: NO - matchingQualifier: qualifier - andSortOrderings: sortOrderings]; - } - else - keys = [NSArray array]; - - return keys; -} - -- (NSArray *) folderKeysMatchingQualifier: (EOQualifier *) qualifier - andSortOrderings: (NSArray *) sortOrderings -{ - [[self userContext] activate]; - return [dbFolder childKeysOfType: MAPIFolderCacheObject - includeDeleted: NO - matchingQualifier: qualifier - andSortOrderings: sortOrderings]; -} - -/* TODO: now that we are DB-based, this method can easily be implemented - -- (NSArray *) getDeletedKeysFromChangeNumber: (uint64_t) changeNum - andCN: (NSNumber **) cnNbrs - inTableType: (enum mapistore_table_type) tableType -{ -} -*/ - -- (NSDate *) lastMessageModificationTime -{ - NSUInteger count, max; - NSDate *date, *fileDate; - MAPIStoreDBMessage *msg; - NSArray *messageKeys; - - messageKeys = [self messageKeys]; - - date = [NSCalendarDate date]; - //[self logWithFormat: @"current date: %@", date]; - - max = [messageKeys count]; - for (count = 0; count < max; count++) - { - msg = [self lookupMessage: [messageKeys objectAtIndex: count]]; - fileDate = [msg lastModificationTime]; - if ([date laterDate: fileDate] == fileDate) - { - //[self logWithFormat: @"current date: %@", date]; - - date = fileDate; - } - } - - return date; -} - -- (SOGoFolder *) aclFolder -{ - return sogoObject; -} - -- (NSArray *) rolesForExchangeRights: (uint32_t) rights -{ - NSMutableArray *roles; - - roles = [NSMutableArray arrayWithCapacity: 9]; - if (rights & RightsReadItems) - [roles addObject: MAPIStoreRightReadItems]; - if (rights & RightsCreateItems) - [roles addObject: MAPIStoreRightCreateItems]; - if (rights & RightsEditOwn) - [roles addObject: MAPIStoreRightEditOwn]; - if (rights & RightsDeleteOwn) - [roles addObject: MAPIStoreRightDeleteOwn]; - if (rights & RightsEditAll) - [roles addObject: MAPIStoreRightEditAll]; - if (rights & RightsDeleteAll) - [roles addObject: MAPIStoreRightDeleteAll]; - if (rights & RightsCreateSubfolders) - [roles addObject: MAPIStoreRightCreateSubfolders]; - if (rights & RightsFolderOwner) - [roles addObject: MAPIStoreRightFolderOwner]; - if (rights & RightsFolderContact) - [roles addObject: MAPIStoreRightFolderContact]; - - return roles; -} - -- (uint32_t) exchangeRightsForRoles: (NSArray *) roles -{ - uint32_t rights = 0; - - if ([roles containsObject: MAPIStoreRightReadItems]) - rights |= RightsReadItems; - if ([roles containsObject: MAPIStoreRightCreateItems]) - rights |= RightsCreateItems; - if ([roles containsObject: MAPIStoreRightEditOwn]) - rights |= RightsEditOwn; - if ([roles containsObject: MAPIStoreRightDeleteOwn]) - rights |= RightsDeleteOwn; - if ([roles containsObject: MAPIStoreRightEditAll]) - rights |= RightsEditAll | RightsEditOwn; - if ([roles containsObject: MAPIStoreRightDeleteAll]) - rights |= RightsDeleteAll | RightsDeleteOwn; - if ([roles containsObject: MAPIStoreRightCreateSubfolders]) - rights |= RightsCreateSubfolders; - if ([roles containsObject: MAPIStoreRightFolderOwner]) - rights |= RightsFolderOwner; - if ([roles containsObject: MAPIStoreRightFolderContact]) - rights |= RightsFolderContact; - if (rights != 0) - rights |= RoleNone; /* actually "folder visible" */ - - return rights; -} - -- (BOOL) _testRoleForActiveUser: (const NSString *) role -{ - SOGoUser *activeUser; - NSArray *roles; - - activeUser = [[self context] activeUser]; - - roles = [[self aclFolder] aclsForUser: [activeUser login]]; - - return [roles containsObject: role]; -} - -- (BOOL) subscriberCanCreateMessages -{ - return [self _testRoleForActiveUser: MAPIStoreRightCreateItems]; -} - -- (BOOL) subscriberCanModifyMessages -{ - return [self _testRoleForActiveUser: MAPIStoreRightEditAll]; -} - -- (BOOL) subscriberCanReadMessages -{ - NSString *displayName; - - /* when this folder is the "Freebusy Data" folder, we need to allow - subscribed to read an open contained messages in order to enable them to - find the "LocalFreebusy" message */ - [sogoObject reloadIfNeeded]; - - displayName = [[sogoObject properties] - objectForKey: MAPIPropertyKey (PidTagDisplayName)]; - - return ([displayName isEqualToString: @"Freebusy Data"] - || [self _testRoleForActiveUser: MAPIStoreRightReadItems]); -} - -- (BOOL) subscriberCanDeleteMessages -{ - return [self _testRoleForActiveUser: MAPIStoreRightDeleteAll]; -} - -- (BOOL) subscriberCanCreateSubFolders -{ - return [self _testRoleForActiveUser: MAPIStoreRightCreateSubfolders]; -} - -- (BOOL) supportsSubFolders -{ - return YES; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreDBFolderTable.h b/Attic/OpenChange/MAPIStoreDBFolderTable.h deleted file mode 100644 index afc3018e2..000000000 --- a/Attic/OpenChange/MAPIStoreDBFolderTable.h +++ /dev/null @@ -1,31 +0,0 @@ -/* MAPIStoreDBFolderTable.h - this file is part of SOGo - * - * Copyright (C) 2012 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 MAPISTOREDBFOLDERTABLE_H -#define MAPISTOREDBFOLDERTABLE_H - -#import "MAPIStoreFolderTable.h" - -@interface MAPIStoreDBFolderTable : MAPIStoreFolderTable -@end - -#endif /* MAPISTOREDBFOLDERTABLE_H */ diff --git a/Attic/OpenChange/MAPIStoreDBFolderTable.m b/Attic/OpenChange/MAPIStoreDBFolderTable.m deleted file mode 100644 index 01a40b7f0..000000000 --- a/Attic/OpenChange/MAPIStoreDBFolderTable.m +++ /dev/null @@ -1,36 +0,0 @@ -/* MAPIStoreDBFolderTable.m - this file is part of SOGo - * - * Copyright (C) 2012 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. - */ - -#import - -#import "MAPIStoreTypes.h" - -#import "MAPIStoreDBFolderTable.h" - -@implementation MAPIStoreDBFolderTable - -- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property -{ - return [NSString stringWithFormat: @"%@", MAPIPropertyKey (property)]; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreDBMessage.h b/Attic/OpenChange/MAPIStoreDBMessage.h deleted file mode 100644 index 532f53a8e..000000000 --- a/Attic/OpenChange/MAPIStoreDBMessage.h +++ /dev/null @@ -1,31 +0,0 @@ -/* MAPIStoreDBMessage.h - this file is part of SOGo - * - * Copyright (C) 2012 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. - */ - -#ifndef MAPISTOREDBMESSAGE_H -#define MAPISTOREDBMESSAGE_H - -#import "MAPIStoreMessage.h" - -@interface MAPIStoreDBMessage : MAPIStoreMessage -@end - -#endif /* MAPISTOREDBMESSAGE_H */ diff --git a/Attic/OpenChange/MAPIStoreDBMessage.m b/Attic/OpenChange/MAPIStoreDBMessage.m deleted file mode 100644 index ca2b772d0..000000000 --- a/Attic/OpenChange/MAPIStoreDBMessage.m +++ /dev/null @@ -1,495 +0,0 @@ -/* MAPIStoreDBMessage.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#import "MAPIStoreContext.h" -#import "MAPIStorePropertySelectors.h" -#import "SOGoMAPIDBMessage.h" - -#import "MAPIStoreDBFolder.h" -#import "MAPIStoreDBMessage.h" -#import "MAPIStoreTypes.h" -#import "NSData+MAPIStore.h" -#import "NSObject+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#undef DEBUG -#include -#include - -@implementation MAPIStoreDBMessage - -+ (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP - inMemCtx: (TALLOC_CTX *) memCtx -{ - struct SPropTagArray *properties; - NSUInteger count; - - enum MAPITAGS faiProperties[] = { - 0x68330048, /* PR_VIEW_CLSID */ - 0x68350102, /* PR_VIEW_STATE */ - 0x683c0102, - 0x683d0040, - 0x683e0102, - 0x683f0102, /* PR_VIEW_VIEWTYPE_KEY */ - 0x68410003, - 0x68420102, - 0x68450102, - 0x68460003, - 0x7006001F, /* PR_VD_NAME_W */ - 0x70030003, /* PR_VD_FLAGS */ - 0x70070003 /* PR_VD_VERSION */ - }; - - size_t faiSize = sizeof(faiProperties) / sizeof(enum MAPITAGS); - - properties = talloc_zero (memCtx, struct SPropTagArray); - properties->cValues = MAPIStoreSupportedPropertiesCount + faiSize; - properties->aulPropTag = talloc_array (properties, enum MAPITAGS, - MAPIStoreSupportedPropertiesCount + faiSize); - - for (count = 0; count < MAPIStoreSupportedPropertiesCount; count++) - properties->aulPropTag[count] = MAPIStoreSupportedProperties[count]; - - /* FIXME (hack): append a few undocumented properties that can be added to - FAI messages */ - for (count = 0; count < faiSize; count++) - properties->aulPropTag[MAPIStoreSupportedPropertiesCount+count] - = faiProperties[count]; - - *propertiesP = properties; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [[self class] getAvailableProperties: propertiesP - inMemCtx: memCtx]; -} - -- (id) initWithSOGoObject: (id) newSOGoObject - inContainer: (MAPIStoreObject *) newContainer -{ - if ((self = [super initWithSOGoObject: newSOGoObject - inContainer: newContainer])) - { - [properties release]; - properties = [newSOGoObject properties]; - [properties retain]; - } - - return self; -} - -- (NSString *) description -{ - id key, value; - NSEnumerator *propEnumerator; - NSMutableString *description; - - description = [NSMutableString stringWithFormat: @"%@ %@. Properties: {", NSStringFromClass ([self class]), - [self url]]; - - propEnumerator = [properties keyEnumerator]; - while ((key = [propEnumerator nextObject])) - { - uint32_t proptag = 0; - if ([key isKindOfClass: [NSString class]] && [(NSString *)key intValue] > 0) - proptag = [(NSString *)key intValue]; - else if ([key isKindOfClass: [NSNumber class]]) - proptag = [key unsignedLongValue]; - - if (proptag > 0) - { - const char *propTagName = get_proptag_name ([key unsignedLongValue]); - NSString *propName; - - if (propTagName) - propName = [NSString stringWithCString: propTagName - encoding: NSUTF8StringEncoding]; - else - propName = [NSString stringWithFormat: @"0x%.4x", [key unsignedLongValue]]; - - [description appendFormat: @"'%@': ", propName]; - } - else - [description appendFormat: @"'%@': ", key]; - - value = [properties objectForKey: key]; - [description appendFormat: @"%@ (%@), ", value, NSStringFromClass ([value class])]; - } - - [description appendString: @"}\n"]; - - return description; -} - -- (uint64_t) objectVersion -{ - /* Return the global counter from CN structure. - See [MS-OXCFXICS] Section 2.2.2.1 */ - NSNumber *versionNbr, *cn; - uint64_t objectVersion; - - [(SOGoMAPIDBMessage *) sogoObject reloadIfNeeded]; - versionNbr = [properties objectForKey: @"version_number"]; - if (versionNbr) - objectVersion = exchange_globcnt ([versionNbr unsignedLongLongValue]); - else - { - /* Old version which stored the CN structure not useful for searching */ - cn = [properties objectForKey: @"version"]; - if (cn) - objectVersion = (([cn unsignedLongLongValue] >> 16) - & 0x0000ffffffffffffLL); - else - objectVersion = ULLONG_MAX; - } - - return objectVersion; -} - -- (void) _updatePredecessorChangeList -{ - BOOL updated; - enum mapistore_error rc; - NSData *currentChangeList, *changeKey; - NSMutableArray *changeKeys; - NSMutableData *newChangeList; - NSUInteger count, len; - struct SizedXid *changes; - struct SPropValue property; - struct SRow aRow; - struct XID *currentChangeKey; - TALLOC_CTX *localMemCtx; - uint32_t nChanges; - - localMemCtx = talloc_new (NULL); - if (!localMemCtx) - { - [self errorWithFormat: @"No more memory"]; - return; - } - - changeKey = [self getReplicaKeyFromGlobCnt: [self objectVersion]]; - - currentChangeList = [properties objectForKey: MAPIPropertyKey (PidTagPredecessorChangeList)]; - if (!currentChangeList) - { - /* Create a new PredecessorChangeList */ - len = [changeKey length]; - newChangeList = [NSMutableData dataWithCapacity: len + 1]; - [newChangeList appendUInt8: len]; - [newChangeList appendData: changeKey]; - } - else - { - /* Update current predecessor change list with new change key */ - changes = [currentChangeList asSizedXidArrayInMemCtx: localMemCtx - with: &nChanges]; - - updated = NO; - currentChangeKey = [changeKey asXIDInMemCtx: localMemCtx]; - for (count = 0; count < nChanges && !updated; count++) - { - if (GUID_equal(&changes[count].XID.NameSpaceGuid, ¤tChangeKey->NameSpaceGuid)) - { - NSData *globCnt, *oldGlobCnt; - oldGlobCnt = [NSData dataWithBytes: changes[count].XID.LocalId.data length: changes[count].XID.LocalId.length]; - globCnt = [NSData dataWithBytes: currentChangeKey->LocalId.data length: currentChangeKey->LocalId.length]; - if ([globCnt compare: oldGlobCnt] == NSOrderedDescending) - { - if ([globCnt length] != [oldGlobCnt length]) - { - [self errorWithFormat: @"Cannot compare globcnt with different length: %@ and %@", globCnt, oldGlobCnt]; - abort(); - } - memcpy (changes[count].XID.LocalId.data, currentChangeKey->LocalId.data, currentChangeKey->LocalId.length); - updated = YES; - } - } - } - - /* Serialise it */ - changeKeys = [NSMutableArray array]; - - if (!updated) - [changeKeys addObject: changeKey]; - - for (count = 0; count < nChanges; count++) - { - changeKey = [NSData dataWithXID: &changes[count].XID]; - [changeKeys addObject: changeKey]; - } - - [changeKeys sortUsingFunction: MAPIChangeKeyGUIDCompare context: localMemCtx]; - - newChangeList = [NSMutableData data]; - len = [changeKeys count]; - for (count = 0; count < len; count++) - { - changeKey = [changeKeys objectAtIndex: count]; - [newChangeList appendUInt8: [changeKey length]]; - [newChangeList appendData: changeKey]; - } - } - - if ([newChangeList length] > 0) - { - property.ulPropTag = PidTagPredecessorChangeList; - property.value.bin = *[newChangeList asBinaryInMemCtx: localMemCtx]; - aRow.cValues = 1; - aRow.lpProps = &property; - rc = [self addPropertiesFromRow: &aRow]; - if (rc != MAPISTORE_SUCCESS) - [self errorWithFormat: @"Impossible to add a new predecessor change list: %d", rc]; - } - - talloc_free (localMemCtx); -} - -// -// FIXME: how this can happen? -// -// We might get there if for some reasons, all classes weren't able -// to tell us the message class. -// -- (enum mapistore_error) getPidTagMessageClass: (void **) data inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [@"IPM.Note" asUnicodeInMemCtx: memCtx]; - - [self logWithFormat: @"METHOD '%s' - unable to determine message class. Falling back to IPM.Note", __FUNCTION__]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getProperties: (struct mapistore_property_data *) data - withTags: (enum MAPITAGS *) tags - andCount: (uint16_t) columnCount - inMemCtx: (TALLOC_CTX *) memCtx -{ - [sogoObject reloadIfNeeded]; - - return [super getProperties: data - withTags: tags - andCount: columnCount - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getProperty: (void **) data - withTag: (enum MAPITAGS) propTag - inMemCtx: (TALLOC_CTX *) memCtx -{ - id value; - enum mapistore_error rc; - - value = [properties objectForKey: MAPIPropertyKey (propTag)]; - if (value) - rc = [value getValue: data forTag: propTag inMemCtx: memCtx]; - else - rc = [super getProperty: data withTag: propTag inMemCtx: memCtx]; - - return rc; -} - -- (void) addProperties: (NSDictionary *) newNewProperties -{ - [sogoObject reloadIfNeeded]; - - [super addProperties: newNewProperties]; -} - -- (void) save: (TALLOC_CTX *) memCtx -{ - uint64_t newVersion; - - if ([attachmentKeys count] > 0) - [properties setObject: attachmentParts forKey: @"attachments"]; - - newVersion = [[self context] getNewChangeNumber]; - newVersion = exchange_globcnt ((newVersion >> 16) & 0x0000ffffffffffffLL); - - [properties setObject: [NSNumber numberWithUnsignedLongLong: newVersion] - forKey: @"version_number"]; - - /* Remove old version */ - [properties removeObjectForKey: @"version"]; - - /* Update PredecessorChangeList accordingly */ - [self _updatePredecessorChangeList]; - - if (isNew) - { - NSString *lastModifierName; - - lastModifierName = (NSString *)[properties objectForKey: MAPIPropertyKey (PidTagLastModifierName)]; - if ([lastModifierName length] > 0) - [properties setObject: lastModifierName - forKey: MAPIPropertyKey (PidTagCreatorName)]; - } - - // [self logWithFormat: @"Saving %@", [self description]]; - // [self logWithFormat: @"%d props in dict", [properties count]]; - - [sogoObject save]; -} - -- (BOOL) _messageIsFreeBusy -{ - NSString *msgClass; - - /* This is a HACK until we figure out how to determine a message position in - the mailbox hierarchy.... (missing: folderid and role) */ - msgClass = [properties - objectForKey: MAPIPropertyKey (PR_MESSAGE_CLASS_UNICODE)]; - - return [msgClass isEqualToString: @"IPM.Microsoft.ScheduleData.FreeBusy"]; -} - -//----------------------------- -// Permissions -//----------------------------- - -- (BOOL) subscriberCanReadMessage -{ - return [(MAPIStoreFolder *) container subscriberCanReadMessages]; -} - -- (SOGoUser *) _ownerUser -{ - NSString *ownerName; - SOGoUser *ownerUser = nil; - - ownerName = [properties objectForKey: MAPIPropertyKey (PidTagCreatorName)]; - if ([ownerName length] > 0) - ownerUser = [SOGoUser userWithLogin: ownerName]; - - return ownerUser; -} - -- (NSArray *) activeUserRoles -{ - /* Override because of this exception: NSInvalidArgumentException, - reason: [SOGoMAPIDBMessage-aclsForUser:] should be overridden by - subclass */ - if (!activeUserRoles) - { - SOGoUser *activeUser; - - activeUser = [[self context] activeUser]; - activeUserRoles = [[container aclFolder] aclsForUser: [activeUser login]]; - [activeUserRoles retain]; - } - - return activeUserRoles; -} - -- (BOOL) subscriberCanModifyMessage -{ - BOOL rc; - NSArray *roles; - - roles = [self activeUserRoles]; - - if (isNew) - rc = [(MAPIStoreFolder *) container subscriberCanCreateMessages]; - else - rc = [roles containsObject: MAPIStoreRightEditAll]; - - /* Check if the message is owned and it has permission to edit it */ - if (!rc && [roles containsObject: MAPIStoreRightEditOwn]) - rc = [[[container context] activeUser] isEqual: [self _ownerUser]]; - - return rc; -} - -- (BOOL) subscriberCanDeleteMessage -{ - BOOL rc; - NSArray *roles; - - roles = [self activeUserRoles]; - - rc = [roles containsObject: MAPIStoreRightDeleteAll]; - - /* Check if the message is owned and it has permission to delete it */ - if (!rc && [roles containsObject: MAPIStoreRightDeleteOwn]) - rc = [[[container context] activeUser] isEqual: [self _ownerUser]]; - - return rc; -} - -- (NSDate *) creationTime -{ - return [sogoObject creationDate]; -} - -- (NSDate *) lastModificationTime -{ - return [sogoObject lastModified]; -} - -- (enum mapistore_error) setReadFlag: (uint8_t) flag -{ - /* Modify PidTagMessageFlags from SetMessageReadFlag and - SyncImportReadStateChanges ROPs */ - NSNumber *flags; - uint32_t newFlag; - - flags = [properties objectForKey: MAPIPropertyKey (PR_MESSAGE_FLAGS)]; - if (flags) - { - newFlag = [flags unsignedLongValue]; - if (flag & SUPPRESS_RECEIPT) - newFlag |= MSGFLAG_READ; - if (flag & CLEAR_RN_PENDING) - newFlag &= ~MSGFLAG_RN_PENDING; - if (flag & CLEAR_READ_FLAG) - newFlag &= ~MSGFLAG_READ; - if (flag & CLEAR_NRN_PENDING) - newFlag &= ~MSGFLAG_NRN_PENDING; - } - else - { - newFlag = MSGFLAG_READ; - if (flag & CLEAR_READ_FLAG) - newFlag = 0x0; - } - [properties setObject: [NSNumber numberWithUnsignedLong: newFlag] - forKey: MAPIPropertyKey (PR_MESSAGE_FLAGS)]; - - return MAPISTORE_SUCCESS; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreDBMessageTable.h b/Attic/OpenChange/MAPIStoreDBMessageTable.h deleted file mode 100644 index 4b9f66480..000000000 --- a/Attic/OpenChange/MAPIStoreDBMessageTable.h +++ /dev/null @@ -1,31 +0,0 @@ -/* MAPIStoreDBMessageTable.h - this file is part of SOGo - * - * Copyright (C) 2012 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. - */ - -#ifndef MAPISTOREDBMESSAGETABLE_H -#define MAPISTOREDBMESSAGETABLE_H - -#import "MAPIStoreMessageTable.h" - -@interface MAPIStoreDBMessageTable : MAPIStoreMessageTable -@end - -#endif /* MAPISTOREDBMESSAGETABLE_H */ diff --git a/Attic/OpenChange/MAPIStoreDBMessageTable.m b/Attic/OpenChange/MAPIStoreDBMessageTable.m deleted file mode 100644 index a8c68abd1..000000000 --- a/Attic/OpenChange/MAPIStoreDBMessageTable.m +++ /dev/null @@ -1,133 +0,0 @@ -/* MAPIStoreDBMessageTable.m - this file is part of SOGo - * - * Copyright (C) 2012 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. - */ - -#import -#import -#import - -#import "MAPIStoreTypes.h" -#import "MAPIStoreDBMessage.h" - -#import "MAPIStoreDBMessageTable.h" - -#undef DEBUG -#include - -static Class MAPIStoreDBMessageK = Nil; - -@implementation MAPIStoreDBMessageTable - -+ (void) initialize -{ - MAPIStoreDBMessageK = [MAPIStoreDBMessage class]; -} - -+ (Class) childObjectClass -{ - return MAPIStoreDBMessageK; -} - -- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property -{ - return [NSString stringWithFormat: @"%@", MAPIPropertyKey (property)]; -} - -- (MAPIRestrictionState) evaluatePropertyRestriction: (struct mapi_SPropertyRestriction *) res - intoQualifier: (EOQualifier **) qualifier -{ - MAPIRestrictionState rc; - id value; - NSNumber *version; - uint64_t cVersion; - - if ((uint32_t) res->ulPropTag == PidTagChangeNumber) - { - SEL operator; - - value = NSObjectFromMAPISPropValue (&res->lpProp); - cVersion = exchange_globcnt (([value unsignedLongLongValue] >> 16) - & 0x0000ffffffffffffLL); - version = [NSNumber numberWithUnsignedLongLong: cVersion]; - operator = [self operatorFromRestrictionOperator: res->relop]; - *qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"version_number" - operatorSelector: operator - value: version]; - [*qualifier autorelease]; - rc = MAPIRestrictionStateNeedsEval; - } - else if ((uint32_t) res->ulPropTag == PR_SUBJECT_UNICODE) - { - EOQualifier *subjectQualifier, *nSubjectQualifier, *subjectPQualifier; - EOQualifier *orQualifier, *andQualifier; - struct mapi_SPropertyRestriction subRes; - char *colPtr, *prefix; - - [super evaluatePropertyRestriction: res - intoQualifier: &subjectQualifier]; - - subRes.relop = res->relop; - subRes.ulPropTag = PR_NORMALIZED_SUBJECT_UNICODE; - subRes.lpProp.ulPropTag = PR_NORMALIZED_SUBJECT_UNICODE; - - colPtr = strstr (res->lpProp.value.lpszW, ":"); - if (colPtr) - subRes.lpProp.value.lpszW = colPtr + 1; - else - subRes.lpProp.value.lpszW = res->lpProp.value.lpszW; - - [self evaluatePropertyRestriction: &subRes - intoQualifier: &nSubjectQualifier]; - if (colPtr) - { - prefix = strndup (res->lpProp.value.lpszW, (colPtr - res->lpProp.value.lpszW)); - - subRes.relop = RELOP_EQ; - subRes.ulPropTag = PR_SUBJECT_PREFIX_UNICODE; - subRes.lpProp.ulPropTag = PR_SUBJECT_PREFIX_UNICODE; - subRes.lpProp.value.lpszW = prefix; - [self evaluatePropertyRestriction: &subRes - intoQualifier: &subjectPQualifier]; - free (prefix); - - andQualifier = [[EOOrQualifier alloc] - initWithQualifiers: - subjectPQualifier, nSubjectQualifier, nil]; - orQualifier = [[EOOrQualifier alloc] - initWithQualifiers: - subjectQualifier, andQualifier, nil]; - [andQualifier release]; - } - else - orQualifier = [[EOOrQualifier alloc] - initWithQualifiers: - subjectQualifier, nSubjectQualifier, nil]; - [orQualifier autorelease]; - *qualifier = orQualifier; - rc = MAPIRestrictionStateNeedsEval; - } - else - rc = [super evaluatePropertyRestriction: res intoQualifier: qualifier]; - - return rc; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreEmbeddedMessage.h b/Attic/OpenChange/MAPIStoreEmbeddedMessage.h deleted file mode 100644 index 4ef65f261..000000000 --- a/Attic/OpenChange/MAPIStoreEmbeddedMessage.h +++ /dev/null @@ -1,33 +0,0 @@ -/* MAPIStoreEmbeddedMessage.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTOREEMBEDDEDMESSAGE_H -#define MAPISTOREEMBEDDEDMESSAGE_H - -#import "MAPIStoreMessage.h" - -@interface MAPIStoreEmbeddedMessage : MAPIStoreMessage - -@end - - -#endif /* MAPISTOREEMBEDDEDMESSAGE_H */ diff --git a/Attic/OpenChange/MAPIStoreEmbeddedMessage.m b/Attic/OpenChange/MAPIStoreEmbeddedMessage.m deleted file mode 100644 index ff5f8b825..000000000 --- a/Attic/OpenChange/MAPIStoreEmbeddedMessage.m +++ /dev/null @@ -1,154 +0,0 @@ -/* MAPIStoreEmbeddedMessage.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import - -#import "MAPIStoreAttachment.h" -#import "MAPIStoreFolder.h" -#import "NSObject+MAPIStore.h" - -#import "MAPIStoreEmbeddedMessage.h" - -#include - -static Class MAPIStoreAttachmentK; - -@implementation MAPIStoreEmbeddedMessage - -+ (void) initialize -{ - MAPIStoreAttachmentK = [MAPIStoreAttachment class]; -} - -- (uint64_t) objectId -{ - NSString *objectKey; - MAPIStoreMessage *grandParent; - - grandParent = (MAPIStoreMessage *) [container container]; - - /* FIXME: this is a hack */ - objectKey = [NSString stringWithFormat: @"%@/%@/as-message", - [grandParent nameInContainer], - [container nameInContainer], - [self nameInContainer]]; - - return [(MAPIStoreFolder *) [grandParent container] - idForObjectWithKey: objectKey]; -} - -- (enum mapistore_error) getPidTagAccessLevel: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getLongZero: data inMemCtx: memCtx]; -} - -/* disabled properties */ -- (enum mapistore_error) getPidTagFolderId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidTagChangeKey: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidTagSourceKey: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidTagParentSourceKey: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidTagChangeNumber: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidTagInstID: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidTagInstanceNum: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidTagRowType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidTagDepth: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidTagIconIndex: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidTagGenerateExchangeViews: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidTagOriginalMessageClass: (void **) dataa - inMemCtx: (TALLOC_CTX *) memCtx -{ - return MAPISTORE_ERR_NOT_FOUND; -} - -/* common methods */ -- (NSString *) nameInContainer -{ - return @"as-message"; -} - -- (uint64_t) objectVersion -{ - return ULLONG_MAX; -} - -- (void) save: (TALLOC_CTX *) memCtx -{ - [self subclassResponsibility: _cmd]; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreFAIMessage.h b/Attic/OpenChange/MAPIStoreFAIMessage.h deleted file mode 100644 index 509bd37be..000000000 --- a/Attic/OpenChange/MAPIStoreFAIMessage.h +++ /dev/null @@ -1,31 +0,0 @@ -/* MAPIStoreFAIMessage.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTOREFAIMESSAGE_H -#define MAPISTOREFAIMESSAGE_H - -#import "MAPIStoreDBMessage.h" - -@interface MAPIStoreFAIMessage : MAPIStoreDBMessage -@end - -#endif /* MAPISTOREFAIMESSAGE_H */ diff --git a/Attic/OpenChange/MAPIStoreFAIMessage.m b/Attic/OpenChange/MAPIStoreFAIMessage.m deleted file mode 100644 index 1c0f1b9a0..000000000 --- a/Attic/OpenChange/MAPIStoreFAIMessage.m +++ /dev/null @@ -1,81 +0,0 @@ -/* MAPIStoreFAIMessage.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import - -#import "MAPIStoreActiveTables.h" -#import "MAPIStoreContext.h" -#import "MAPIStoreFolder.h" -#import "MAPIStoreUserContext.h" -#import "NSObject+MAPIStore.h" - -#import "MAPIStoreFAIMessage.h" - -#undef DEBUG -#include -#include -#include -#include -#include - -@implementation MAPIStoreFAIMessage - -- (NSArray *) activeContainerMessageTables -{ - return [[MAPIStoreActiveTables activeTables] - activeTablesForFMID: [container objectId] - andType: MAPISTORE_FAI_TABLE]; -} - -- (enum mapistore_error) getPidTagAssociated: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getYes: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) saveMessage: (TALLOC_CTX *) memCtx; -{ - enum mapistore_error rc; - MAPIStoreContext *context; - SOGoUser *ownerUser; - - context = [self context]; - ownerUser = [[self userContext] sogoUser]; - if ([[context activeUser] isEqual: ownerUser]) - rc = [super saveMessage: memCtx]; - else - rc = MAPISTORE_ERR_DENIED; - - return rc; -} - -- (BOOL) subscriberCanReadMessage -{ - return [(MAPIStoreFolder *)container subscriberCanReadMessages]; -} - -- (BOOL) subscriberCanModifyMessage -{ - return NO; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreFAIMessageTable.h b/Attic/OpenChange/MAPIStoreFAIMessageTable.h deleted file mode 100644 index c12f20f99..000000000 --- a/Attic/OpenChange/MAPIStoreFAIMessageTable.h +++ /dev/null @@ -1,31 +0,0 @@ -/* MAPIStoreFAIMessageTable.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTOREFAIMESSAGETABLE_H -#define MAPISTOREFAIMESSAGETABLE_H - -#import "MAPIStoreDBMessageTable.h" - -@interface MAPIStoreFAIMessageTable : MAPIStoreDBMessageTable -@end - -#endif /* MAPISTOREFAIMESSAGETABLE_H */ diff --git a/Attic/OpenChange/MAPIStoreFAIMessageTable.m b/Attic/OpenChange/MAPIStoreFAIMessageTable.m deleted file mode 100644 index 531299868..000000000 --- a/Attic/OpenChange/MAPIStoreFAIMessageTable.m +++ /dev/null @@ -1,101 +0,0 @@ -/* MAPIStoreFAIMessageTable.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import - -#import "MAPIStoreFAIMessage.h" -#import "MAPIStoreFolder.h" - -#import "MAPIStoreFAIMessageTable.h" - -#undef DEBUG -#include -#include -#include - -static Class MAPIStoreFAIMessageK = Nil; - -@implementation MAPIStoreFAIMessageTable - -+ (void) initialize -{ - MAPIStoreFAIMessageK = [MAPIStoreFAIMessage class]; -} - -+ (Class) childObjectClass -{ - return MAPIStoreFAIMessageK; -} - -- (id) init -{ - if ((self = [super init])) - { - tableType = MAPISTORE_FAI_TABLE; - } - - return self; -} - -- (NSArray *) childKeys -{ - if (!childKeys) - { - childKeys = [(MAPIStoreFolder *) - container faiMessageKeysMatchingQualifier: nil - andSortOrderings: sortOrderings]; - [childKeys retain]; - } - - return childKeys; -} - -- (NSArray *) restrictedChildKeys -{ - NSArray *keys; - - if (!restrictedChildKeys) - { - if (restrictionState != MAPIRestrictionStateAlwaysTrue) - { - if (restrictionState == MAPIRestrictionStateNeedsEval) - keys = [(MAPIStoreFolder *) - container faiMessageKeysMatchingQualifier: restriction - andSortOrderings: sortOrderings]; - else - keys = [NSArray array]; - } - else - keys = [self childKeys]; - - ASSIGN (restrictedChildKeys, keys); - } - - return restrictedChildKeys; -} - -- (id) lookupChild: (NSString *) childKey -{ - return [(MAPIStoreFolder *) container lookupFAIMessage: childKey]; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreFallbackContext.h b/Attic/OpenChange/MAPIStoreFallbackContext.h deleted file mode 100644 index a6a2707ab..000000000 --- a/Attic/OpenChange/MAPIStoreFallbackContext.h +++ /dev/null @@ -1,32 +0,0 @@ -/* MAPIStoreFallbackContext.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 MAPISTOREFALLBACKCONTEXT_H -#define MAPISTOREFALLBACKCONTEXT_H - -#import "MAPIStoreDBBaseContext.h" - -@interface MAPIStoreFallbackContext : MAPIStoreDBBaseContext - -@end - -#endif /* MAPISTOREFALLBACKCONTEXT_H */ diff --git a/Attic/OpenChange/MAPIStoreFallbackContext.m b/Attic/OpenChange/MAPIStoreFallbackContext.m deleted file mode 100644 index 1555226d5..000000000 --- a/Attic/OpenChange/MAPIStoreFallbackContext.m +++ /dev/null @@ -1,112 +0,0 @@ -/* MAPIStoreFallbackContext.m - this file is part of SOGo - * - * Copyright (C) 2011-2014 Inverse inc. - * - * 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. - */ - -#import -#import -#import - -#import "MAPIStoreUserContext.h" -#import "NSString+MAPIStore.h" -#import - -#import "MAPIStoreFallbackContext.h" - -#undef DEBUG -#include -#include -#include - -@implementation MAPIStoreFallbackContext - -+ (NSString *) MAPIModuleName -{ - return @"fallback"; -} - -+ (enum mapistore_context_role) MAPIContextRole -{ - return MAPISTORE_MAIL_ROLE; -} - -+ (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName - withIndexing: (struct indexing_context *) indexing - inMemCtx: (TALLOC_CTX *) memCtx -{ - struct mapistore_contexts_list *firstContext = NULL, *context; - SOGoCacheGCSFolder *root; - NSArray *names; - NSUInteger count, max; - NSString *baseURL, *url, *name; - MAPIStoreUserContext *userContext; - - baseURL = [NSString stringWithFormat: @"sogo://%@@fallback/", - [userName stringByReplacingOccurrencesOfString: @"@" - withString: @"%40"]]; - - - context = talloc_zero (memCtx, struct mapistore_contexts_list); - context->url = [baseURL asUnicodeInMemCtx: context]; - context->name = "Fallback"; - context->main_folder = true; - context->role = MAPISTORE_FALLBACK_ROLE; - context->tag = "tag"; - - DLIST_ADD_END (firstContext, context, void); - - /* Maybe emsmdbp_provisioning should be fixed in order to only take the uri - returned above to avoid deleting its entries... */ - root = [SOGoCacheGCSFolder objectWithName: [self MAPIModuleName] - inContainer: nil]; - [root setOwner: userName]; - userContext = [MAPIStoreUserContext userContextWithUsername: userName - andTDBIndexing: indexing]; - [userContext ensureFolderTableExists]; - [root setTableUrl: [userContext folderTableURL]]; - names = [root toManyRelationshipKeys]; - max = [names count]; - for (count = 0; count < max; count++) - { - name = [names objectAtIndex: count]; - url = [NSString stringWithFormat: @"%@%@/", baseURL, name]; - context = talloc_zero (memCtx, struct mapistore_contexts_list); - context->url = [url asUnicodeInMemCtx: context]; - context->name = [name asUnicodeInMemCtx: context]; - context->main_folder = false; - context->role = MAPISTORE_FALLBACK_ROLE; - context->tag = "tag"; - DLIST_ADD_END (firstContext, context, void); - } - - return firstContext; -} - -+ (NSString *) - createRootSecondaryFolderWithFID: (uint64_t) fid - andName: (NSString *) folderName - forUser: (NSString *) userName -{ - return [NSString stringWithFormat: @"sogo://%@@fallback/0x%.16"PRIx64"/", - [userName stringByReplacingOccurrencesOfString: @"@" - withString: @"%40"], - (unsigned long long) fid]; - -} - -@end diff --git a/Attic/OpenChange/MAPIStoreFolder.h b/Attic/OpenChange/MAPIStoreFolder.h deleted file mode 100644 index 46e13d235..000000000 --- a/Attic/OpenChange/MAPIStoreFolder.h +++ /dev/null @@ -1,209 +0,0 @@ -/* MAPIStoreFolder.h - this file is part of SOGo - * - * Copyright (C) 2011-2014 Inverse inc - * - * 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. - */ - -#ifndef MAPISTOREFOLDER_H -#define MAPISTOREFOLDER_H - -#import -#import - -@class NSArray; -@class NSMutableArray; -@class NSNumber; - -@class EOQualifier; - -@class MAPIStoreContext; -@class MAPIStoreMessage; -@class MAPIStoreFAIMessageTable; -@class MAPIStoreFolderTable; -@class MAPIStoreMessageTable; -@class MAPIStorePermissionsTable; -@class SOGoFolder; -@class SOGoCacheGCSFolder; -@class SOGoMAPIDBMessage; - -#import "MAPIStoreSOGoObject.h" - -/* MAPI Permissions - - This set has only sogo-openchange library scope - */ -extern NSString *MAPIStoreRightReadItems; -extern NSString *MAPIStoreRightCreateItems; -extern NSString *MAPIStoreRightEditOwn; -extern NSString *MAPIStoreRightEditAll; -extern NSString *MAPIStoreRightDeleteOwn; -extern NSString *MAPIStoreRightDeleteAll; -extern NSString *MAPIStoreRightCreateSubfolders; -extern NSString *MAPIStoreRightFolderOwner; -extern NSString *MAPIStoreRightFolderContact; - -@interface MAPIStoreFolder : MAPIStoreSOGoObject -{ - MAPIStoreContext *context; - // NSArray *messageKeys; - // NSArray *faiMessageKeys; - // NSArray *folderKeys; - - SOGoCacheGCSFolder *dbFolder; - // SOGoMAPIDBFolder *faiFolder; - // SOGoMAPIDBFolder *propsFolder; - // SOGoMAPIDBMessage *propsMessage; -} - -- (void) setContext: (MAPIStoreContext *) newContext; - -- (void) setupAuxiliaryObjects; - -- (SOGoCacheGCSFolder *) dbFolder; - -- (NSArray *) activeMessageTables; -- (NSArray *) activeFAIMessageTables; - -// - (SOGoMAPIDBMessage *) propertiesMessage; - -- (NSString *) childKeyFromURL: (NSString *) childURL; - -- (id) lookupMessageByURL: (NSString *) messageURL; -- (id) lookupFolderByURL: (NSString *) folderURL; - -/* permissions */ -- (MAPIStorePermissionsTable *) permissionsTable; -- (NSArray *) permissionEntries; - -- (NSArray *) expandRoles: (NSArray *) roles; - -/* message objects and tables */ -- (id) lookupMessage: (NSString *) messageKey; -- (NSArray *) messageKeys; - -/* FAI message objects and tables */ -- (id) lookupFAIMessage: (NSString *) messageKey; -- (MAPIStoreFAIMessageTable *) faiMessageTable; -- (NSArray *) faiMessageKeys; -- (NSArray *) faiMessageKeysMatchingQualifier: (EOQualifier *) qualifier - andSortOrderings: (NSArray *) sortOrderings; - -/* folder objects and tables */ -- (id) lookupFolder: (NSString *) folderKey; -- (MAPIStoreFolderTable *) folderTable; -- (NSArray *) folderKeys; -- (NSArray *) folderKeysMatchingQualifier: (EOQualifier *) qualifier - andSortOrderings: (NSArray *) sortOrderings; - -- (MAPIStoreMessage *) createMessage: (BOOL) isAssociated; - -/* backend interface */ - -- (enum mapistore_error) openFolder: (MAPIStoreFolder **) childFolderPtr - withFID: (uint64_t) fid; -- (enum mapistore_error) createFolder: (MAPIStoreFolder **) childFolderPtr - withRow: (struct SRow *) aRow - andFID: (uint64_t) fid; -- (enum mapistore_error) deleteFolder; -- (enum mapistore_error) getChildCount: (uint32_t *) rowCount - ofTableType: (enum mapistore_table_type) tableType; - -- (enum mapistore_error) createMessage: (MAPIStoreMessage **) messagePtr - withMID: (uint64_t) mid - isAssociated: (BOOL) isAssociated; - -- (enum mapistore_error) openMessage: (MAPIStoreMessage **) messagePtr - withMID: (uint64_t) mid - forWriting: (BOOL) readWrite - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) deleteMessageWithMID: (uint64_t) mid - andFlags: (uint8_t) flags; - -- (enum mapistore_error) moveCopyMessagesWithMIDs: (uint64_t *) srcMids - andCount: (uint32_t) count - fromFolder: (MAPIStoreFolder *) sourceFolder - withMIDs: (uint64_t *) targetMids - andChangeKeys: (struct Binary_r **) targetChangeKeys - andPredecessorChangeLists: (struct Binary_r **) targetPredecessorChangeLists - wantCopy: (uint8_t) want_copy - inMemCtx: (TALLOC_CTX *) memCtx; - -- (enum mapistore_error) moveCopyToFolder: (MAPIStoreFolder *) targetFolder - withNewName: (NSString *) newFolderName - isMove: (BOOL) isMove - isRecursive: (BOOL) isRecursive - inMemCtx: (TALLOC_CTX *) memCtx; - -- (enum mapistore_error) getDeletedFMIDs: (struct UI8Array_r **) fmidsPtr - andCN: (uint64_t *) cnPtr - fromChangeNumber: (uint64_t) changeNum - inTableType: (enum mapistore_table_type) tableType - inMemCtx: (TALLOC_CTX *) mem_ctx; - -- (enum mapistore_error) getTable: (MAPIStoreTable **) tablePtr - andRowCount: (uint32_t *) count - tableType: (enum mapistore_table_type) tableType - andHandleId: (uint32_t) handleId; - -- (enum mapistore_error) modifyPermissions: (struct PermissionData *) permissions - withCount: (uint16_t) pcount - andFlags: (int8_t) flags; -- (enum mapistore_error) preloadMessageBodiesWithMIDs: (const struct UI8Array_r *) mids - ofTableType: (enum mapistore_table_type) tableType; - - -/* helpers */ -- (uint64_t) idForObjectWithKey: (NSString *) childKey; -- (MAPIStoreFolder *) rootContainer; - -/* subclasses */ -- (MAPIStoreMessage *) createMessage; -- (MAPIStoreMessageTable *) messageTable; -- (NSArray *) messageKeysMatchingQualifier: (EOQualifier *) qualifier - andSortOrderings: (NSArray *) sortOrderings; -- (NSArray *) getDeletedKeysFromChangeNumber: (uint64_t) changeNum - andCN: (NSNumber **) cnNbr - inTableType: (enum mapistore_table_type) tableType; - -- (enum mapistore_error) createFolder: (struct SRow *) aRow - withFID: (uint64_t) newFID - andKey: (NSString **) newKeyP; - -- (NSCalendarDate *) lastMessageModificationTime; - -- (SOGoFolder *) aclFolder; -- (NSArray *) rolesForExchangeRights: (uint32_t) rights; -- (uint32_t) exchangeRightsForRoles: (NSArray *) roles; - -- (BOOL) subscriberCanCreateMessages; -- (BOOL) subscriberCanModifyMessages; -- (BOOL) subscriberCanReadMessages; -- (BOOL) subscriberCanDeleteMessages; -- (BOOL) subscriberCanCreateSubFolders; - -- (BOOL) supportsSubFolders; /* capability */ - -- (enum mapistore_error) preloadMessageBodiesWithKeys: (NSArray *) keys - ofTableType: (enum mapistore_table_type) tableType; - -/* subclass helpers */ -- (void) setupVersionsMessage; -- (void) ensureIDsForChildKeys: (NSArray *) keys; - -@end - -#endif /* MAPISTOREFOLDER_H */ diff --git a/Attic/OpenChange/MAPIStoreFolder.m b/Attic/OpenChange/MAPIStoreFolder.m deleted file mode 100644 index 43efcaff9..000000000 --- a/Attic/OpenChange/MAPIStoreFolder.m +++ /dev/null @@ -1,1897 +0,0 @@ -/* MAPIStoreFolder.m - this file is part of SOGo - * - * Copyright (C) 2011-2014 Inverse inc - * - * 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. - */ - -/* TODO: main key arrays must be initialized */ - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#import "MAPIStoreActiveTables.h" -#import "MAPIStoreContext.h" -#import "MAPIStoreFAIMessage.h" -#import "MAPIStoreFAIMessageTable.h" -#import "MAPIStoreFolder.h" -#import "MAPIStoreFolderTable.h" -#import "MAPIStoreMapping.h" -#import "MAPIStoreMessage.h" -#import "MAPIStorePermissionsTable.h" -#import "MAPIStoreSamDBUtils.h" -#import "MAPIStoreTypes.h" -#import "MAPIStoreUserContext.h" -#import "NSData+MAPIStore.h" -#import "NSDate+MAPIStore.h" -#import "NSString+MAPIStore.h" -#import "NSObject+MAPIStore.h" -#import -#import "SOGoMAPIDBMessage.h" -#import "SOGoCacheGCSObject+MAPIStore.h" -#import - -#include - -#undef DEBUG -#include -#include -#include -#include - -Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMessageTableK, MAPIStoreFolderTableK; - -/* MAPI permissions */ -NSString *MAPIStoreRightReadItems = @"RightsReadItems"; -NSString *MAPIStoreRightCreateItems = @"RightsCreateItems"; -NSString *MAPIStoreRightEditOwn = @"RightsEditOwn"; -NSString *MAPIStoreRightEditAll = @"RightsEditAll"; -NSString *MAPIStoreRightDeleteOwn = @"RightsDeleteOwn"; -NSString *MAPIStoreRightDeleteAll = @"RightsDeleteAll"; -NSString *MAPIStoreRightCreateSubfolders = @"RightsCreateSubfolders"; -NSString *MAPIStoreRightFolderOwner = @"RightsFolderOwner"; -NSString *MAPIStoreRightFolderContact = @"RightsFolderContact"; - -@implementation MAPIStoreFolder - -+ (void) initialize -{ - NSExceptionK = [NSException class]; - MAPIStoreFAIMessageK = [MAPIStoreFAIMessage class]; - MAPIStoreMessageTableK = [MAPIStoreMessageTable class]; - MAPIStoreFAIMessageTableK = [MAPIStoreFAIMessageTable class]; - MAPIStoreFolderTableK = [MAPIStoreFolderTable class]; -} - -- (id) init -{ - if ((self = [super init])) - { - // messageKeys = nil; - // faiMessageKeys = nil; - // folderKeys = nil; - dbFolder = nil; - context = nil; - - // propsFolder = nil; - // propsMessage = nil; - } - - return self; -} - -- (void) setupAuxiliaryObjects -{ - NSURL *folderURL; - NSMutableString *pathPrefix; - NSString *path, *folderName; - NSArray *parts; - NSUInteger lastPartIdx; - MAPIStoreUserContext *userContext; - - parts = 0; - lastPartIdx = 0; - folderURL = [NSURL URLWithString: [self url]]; - /* note: -[NSURL path] returns an unescaped representation */ - path = [folderURL path]; - path = [path substringFromIndex: 1]; - if ([path length] > 0) - { - parts = [path componentsSeparatedByString: @"/"]; - lastPartIdx = [parts count] - 1; - if ([path hasSuffix: @"/"]) - lastPartIdx--; - folderName = [parts objectAtIndex: lastPartIdx]; - } - else - folderName = [folderURL host]; - - userContext = [self userContext]; - [userContext activate]; - [userContext ensureFolderTableExists]; - - ASSIGN (dbFolder, - [SOGoCacheGCSFolder objectWithName: folderName - inContainer: [container dbFolder]]); - [dbFolder setTableUrl: [userContext folderTableURL]]; - if (!container && [path length] > 0) - { - pathPrefix = [NSMutableString stringWithCapacity: 64]; - [pathPrefix appendFormat: @"/%@", [folderURL host]]; - parts = [parts subarrayWithRange: NSMakeRange (0, lastPartIdx)]; - if ([parts count] > 0) - [pathPrefix appendFormat: @"/%@", [parts componentsJoinedByString: @"/"]]; - [dbFolder setPathPrefix: pathPrefix]; - } - [dbFolder reloadIfNeeded]; - - /* propsMessage and self share the same properties dictionary */ - // ASSIGN (propsMessage, - // [SOGoMAPIDBMessage objectWithName: @"properties.plist" - // inContainer: dbFolder]); - // [propsMessage setObjectType: MAPIInternalCacheObject]; - // [propsMessage reloadIfNeeded]; - [properties release]; - properties = [dbFolder properties]; - [properties retain]; - - [self setupVersionsMessage]; -} - -- (id) initWithSOGoObject: (id) newSOGoObject - inContainer: (MAPIStoreObject *) newContainer -{ - /* The instantiation of auxiliary folders is postponed when newContainer is - nil since there is no way to deduce the parent url. When setContext: is - invoked, it becomes possible again. */ - if ((self = [super initWithSOGoObject: newSOGoObject - inContainer: newContainer]) - && newContainer) - { - [self setupAuxiliaryObjects]; - } - - return self; -} - -- (void) setContext: (MAPIStoreContext *) newContext -{ - ASSIGN (context, newContext); - if (newContext) - [self setupAuxiliaryObjects]; -} - -- (MAPIStoreContext *) context -{ - if (!context) - [self setContext: (MAPIStoreContext *) [container context]]; - - return context; -} - -- (void) dealloc -{ - //[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__]; - - // [messageKeys release]; - // [faiMessageKeys release]; - // [folderKeys release]; - // [propsMessage release]; - [dbFolder release]; - [context release]; - - [super dealloc]; -} - -- (SOGoCacheGCSFolder *) dbFolder -{ - return dbFolder; -} - -/* backend interface */ - -// - (SOGoMAPIDBMessage *) propertiesMessage -// { -// return propsMessage; -// } - -- (uint64_t) objectVersion -{ - NSNumber *value; - uint64_t cn; - - value = [properties objectForKey: MAPIPropertyKey (PidTagChangeNumber)]; - if (value) - cn = [value unsignedLongLongValue]; - else - { - [self logWithFormat: @"no value for PidTagChangeNumber, adding one now"]; - cn = [[self context] getNewChangeNumber]; - value = [NSNumber numberWithUnsignedLongLong: cn]; - - [properties setObject: value - forKey: MAPIPropertyKey (PidTagChangeNumber)]; - [dbFolder save]; - } - - return cn >> 16; -} - -- (id) lookupFolder: (NSString *) folderKey -{ - MAPIStoreFolder *childFolder = nil; - SOGoFolder *sogoFolder; - - if ([[self folderKeys] containsObject: folderKey]) - { - [[self userContext] activate]; - sogoFolder = [sogoObject lookupName: folderKey - inContext: nil - acquire: NO]; - if (sogoFolder && ![sogoFolder isKindOfClass: NSExceptionK]) - childFolder = [isa mapiStoreObjectWithSOGoObject: sogoFolder - inContainer: self]; - } - - return childFolder; -} - -- (id) lookupFolderByURL: (NSString *) childURL -{ - MAPIStoreObject *foundObject; - NSString *key, *slashLessURL; - - if ([childURL hasSuffix: @"/"]) - slashLessURL = [childURL substringToIndex: [childURL length] - 1]; - else - slashLessURL = childURL; - key = [self childKeyFromURL: slashLessURL]; - if (key) - foundObject = [self lookupFolder: key]; - else - foundObject = nil; - - return foundObject; -} - -- (id) lookupMessage: (NSString *) messageKey -{ - MAPIStoreObject *childMessage = nil; - Class messageClass; - SOGoObject *msgObject; - - if (messageKey) - { - [[self userContext] activate]; - msgObject = [sogoObject lookupName: messageKey - inContext: nil - acquire: NO]; - /* If the lookup in the indexing table works, but the IMAP does - not have the message, then the message does not exist in this - folder */ - if (msgObject && [msgObject isKindOfClass: [SOGoMailObject class]] - && ! [(SOGoMailObject *)msgObject doesMailExist]) - return nil; - if (msgObject && ![msgObject isKindOfClass: NSExceptionK]) - { - [msgObject setContext: [[self userContext] woContext]]; - messageClass = [msgObject mapistoreMessageClass]; - childMessage - = [messageClass mapiStoreObjectWithSOGoObject: msgObject - inContainer: self]; - } - } - - return childMessage; -} - -- (id) lookupFAIMessage: (NSString *) messageKey -{ - MAPIStoreObject *childMessage = nil; - SOGoObject *msgObject; - - if (messageKey) - { - [[self userContext] activate]; - if ([[self faiMessageKeys] containsObject: messageKey]) - { - msgObject = [dbFolder lookupName: messageKey - inContext: nil - acquire: NO]; - childMessage - = [MAPIStoreFAIMessageK mapiStoreObjectWithSOGoObject: msgObject - inContainer: self]; - } - } - - return childMessage; -} - -- (NSString *) childKeyFromURL: (NSString *) childURL -{ - NSString *baseURL, *subURL, *key = nil; - NSArray *parts; - NSUInteger partsCount; - - baseURL = [self url]; - if (![baseURL hasSuffix: @"/"]) - baseURL = [NSString stringWithFormat: @"%@/", baseURL]; - if ([childURL hasPrefix: baseURL]) - { - subURL = [childURL substringFromIndex: [baseURL length]]; - if ([subURL length] > 0) - { - parts = [subURL componentsSeparatedByString: @"/"]; - partsCount = [parts count]; - if (partsCount == 1) - { - key = [[parts objectAtIndex: 0] - stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding]; - } - } - } - - return key; -} - -- (id) lookupMessageByURL: (NSString *) childURL -{ - MAPIStoreObject *foundObject; - NSString *key; - - key = [self childKeyFromURL: childURL]; - if (key) - { - foundObject = [self lookupFAIMessage: key]; - if (!foundObject) - foundObject = [self lookupMessage: key]; - } - else - foundObject = nil; - - return foundObject; -} - -- (enum mapistore_error) openFolder: (MAPIStoreFolder **) childFolderPtr - withFID: (uint64_t) fid -{ - enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND; - MAPIStoreFolder *childFolder; - MAPIStoreMapping *mapping; - NSString *childURL; - - //[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__]; - - mapping = [self mapping]; - childURL = [mapping urlFromID: fid]; - if (childURL) - { - childFolder = [self lookupFolderByURL: childURL]; - if (childFolder) - { - *childFolderPtr = childFolder; - rc = MAPISTORE_SUCCESS; - } - } - - return rc; -} - -- (enum mapistore_error) createFolder: (MAPIStoreFolder **) childFolderPtr - withRow: (struct SRow *) aRow - andFID: (uint64_t) fid -{ - BOOL mapped; - enum mapistore_error rc = MAPISTORE_SUCCESS; - MAPIStoreMapping *mapping; - NSString *baseURL, *childURL, *folderKey; - MAPIStoreFolder *childFolder; - SOGoUser *ownerUser; - - //[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__]; - - ownerUser = [[self userContext] sogoUser]; - if ([[context activeUser] isEqual: ownerUser] - || [self subscriberCanCreateSubFolders]) - { - mapping = [self mapping]; - childURL = [mapping urlFromID: fid]; - if (childURL) - rc = MAPISTORE_ERR_EXIST; - else - { - rc = [self createFolder: aRow withFID: fid andKey: &folderKey]; - if (rc == MAPISTORE_SUCCESS) - { - [self cleanupCaches]; - baseURL = [self url]; - if (![baseURL hasSuffix: @"/"]) - baseURL = [NSString stringWithFormat: @"%@/", baseURL]; - childURL = [NSString stringWithFormat: @"%@%@/", - baseURL, - [folderKey stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]]; - - mapped = [mapping registerURL: childURL withID: fid]; - if (!mapped) - /* Enforce the creation if the backend does know the fid */ - [mapping updateURL: childURL withID: fid]; - - childFolder = [self lookupFolder: folderKey]; - if (childFolder) - { - [childFolder addPropertiesFromRow: aRow]; - *childFolderPtr = childFolder; - } - else - [NSException raise: @"MAPIStoreIOException" - format: @"unable to fetch created folder"]; - } - } - } - else - rc = MAPISTORE_ERR_DENIED; - - return rc; -} - -- (enum mapistore_error) deleteFolder -{ - // TODO: raise exception in case underlying delete fails? - // [propsMessage delete]; - [dbFolder delete]; - - [self cleanupCaches]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getChildCount: (uint32_t *) rowCount - ofTableType: (enum mapistore_table_type) tableType -{ - NSArray *keys; - enum mapistore_error rc = MAPISTORE_SUCCESS; - - //[self logWithFormat: @"METHOD '%s' (%d) -- tableType: %d", - //__FUNCTION__, __LINE__, tableType]; - - if (tableType == MAPISTORE_MESSAGE_TABLE) - keys = [self messageKeys]; - else if (tableType == MAPISTORE_FOLDER_TABLE) - keys = [self folderKeys]; - else if (tableType == MAPISTORE_FAI_TABLE) - keys = [self faiMessageKeys]; - else - { - keys = nil; - rc = MAPISTORE_ERR_NOT_FOUND; - } - *rowCount = [keys count]; - - return rc; -} - -- (enum mapistore_error) openMessage: (MAPIStoreMessage **) messagePtr - withMID: (uint64_t) mid - forWriting: (BOOL) readWrite - inMemCtx: (TALLOC_CTX *) memCtx; -{ - NSString *messageURL; - MAPIStoreMapping *mapping; - MAPIStoreMessage *message; - SOGoUser *ownerUser; - enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND; - - mapping = [self mapping]; - messageURL = [mapping urlFromID: mid]; - if (messageURL) - { - message = [self lookupMessageByURL: messageURL]; - if (message) - { - ownerUser = [[self userContext] sogoUser]; - if ([[context activeUser] isEqual: ownerUser] - || (readWrite && [message subscriberCanModifyMessage]) - || (!readWrite && [message subscriberCanReadMessage])) - { - *messagePtr = message; - rc = MAPISTORE_SUCCESS; - } - else - rc = MAPISTORE_ERR_DENIED; - } - else - { - /* Unregistering from indexing table as the backend says the - object was not found */ - [mapping unregisterURLWithID: mid]; - } - } - - return rc; -} - -- (enum mapistore_error) createMessage: (MAPIStoreMessage **) messagePtr - withMID: (uint64_t) mid - isAssociated: (BOOL) isAssociated -{ - enum mapistore_error rc; - MAPIStoreMessage *message; - NSString *baseURL, *childURL; - MAPIStoreMapping *mapping; - SOGoUser *ownerUser; - - //[self logWithFormat: @"METHOD '%s' -- mid: 0x%.16llx associated: %d", - // __FUNCTION__, mid, isAssociated]; - - context = [self context]; - ownerUser = [[self userContext] sogoUser]; - [[self userContext] activate]; - - if ([[context activeUser] isEqual: ownerUser] - || (!isAssociated && [self subscriberCanCreateMessages])) - { - mapping = [self mapping]; - if ([mapping urlFromID: mid]) - rc = MAPISTORE_ERR_EXIST; - else - { - message = [self createMessage: isAssociated]; - if (message) - { - baseURL = [self url]; - if (![baseURL hasSuffix: @"/"]) - baseURL = [NSString stringWithFormat: @"%@/", baseURL]; - childURL = [NSString stringWithFormat: @"%@%@", - baseURL, [message nameInContainer]]; - [mapping registerURL: childURL withID: mid]; - *messagePtr = message; - rc = MAPISTORE_SUCCESS; - } - else - rc = MAPISTORE_ERROR; - } - } - else - rc = MAPISTORE_ERR_DENIED; - - return rc; -} - -- (enum mapistore_error) deleteMessageWithMID: (uint64_t) mid - andFlags: (uint8_t) flags -{ - NSString *childURL; - MAPIStoreMapping *mapping; - MAPIStoreMessage *message; - NSArray *activeTables; - NSUInteger count, max; - id msgObject; - SOGoUser *ownerUser; - enum mapistore_error rc; - - /* flags that control the behaviour of the operation - (MAPISTORE_SOFT_DELETE or MAPISTORE_PERMANENT_DELETE) */ - [self logWithFormat: @"-deleteMessageWithMID: mid: 0x%.16llx flags: %d", mid, flags]; - - mapping = [self mapping]; - childURL = [mapping urlFromID: mid]; - if (childURL) - { - message = [self lookupMessageByURL: childURL]; - if (message) - { - ownerUser = [[self userContext] sogoUser]; - - if ([[context activeUser] isEqual: ownerUser] - || (![message isKindOfClass: MAPIStoreFAIMessageK] - && ([self subscriberCanDeleteMessages] || [message subscriberCanDeleteMessage]))) - { - /* we ensure the table caches are loaded so that old and new state - can be compared */ - activeTables = ([message isKindOfClass: MAPIStoreFAIMessageK] - ? [self activeFAIMessageTables] - : [self activeMessageTables]); - max = [activeTables count]; - for (count = 0; count < max; count++) - [[activeTables objectAtIndex: count] restrictedChildKeys]; - - msgObject = [message sogoObject]; - if (([msgObject respondsToSelector: @selector (prepareDelete)] - && [msgObject prepareDelete]) - || [msgObject delete]) - { - rc = MAPISTORE_ERROR; - [self logWithFormat: @"ERROR deleting object at URL: %@", childURL]; - } - else - { - [self logWithFormat: @"successfully deleted object at URL: %@", childURL]; - /* Ensure we are respecting flags parameter */ - [mapping unregisterURLWithID: mid andFlags: flags]; - [self cleanupCaches]; - rc = MAPISTORE_SUCCESS; - } - } - else - rc = MAPISTORE_ERR_DENIED; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -// private method -- (enum mapistore_error) _moveCopyMessageWithMID: (uint64_t) srcMid - fromFolder: (MAPIStoreFolder *) sourceFolder - withMID: (uint64_t) targetMid - andChangeKey: (struct Binary_r *) targetChangeKey - andPredecessorChangeList: (struct Binary_r *) targetPredecessorChangeList - wantCopy: (uint8_t) wantCopy - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - MAPIStoreMessage *sourceMsg, *destMsg; - //TALLOC_CTX *memCtx; - struct SRow aRow; - struct SPropValue property; - uint8_t deleteFlags; - - [self logWithFormat: @"-moveCopyMessageWithMID: 0x%.16llx .. withMID: 0x%.16llx .. wantCopy: %d", srcMid, targetMid, wantCopy]; - - //memCtx = talloc_zero (NULL, TALLOC_CTX); - rc = [sourceFolder openMessage: &sourceMsg - withMID: srcMid - forWriting: NO - inMemCtx: memCtx]; - if (rc != MAPISTORE_SUCCESS) - goto end; - - rc = [self createMessage: &destMsg withMID: targetMid - isAssociated: [sourceMsg isKindOfClass: MAPIStoreFAIMessageK]]; - if (rc != MAPISTORE_SUCCESS) - goto end; - - [sourceMsg copyToMessage: destMsg inMemCtx: memCtx]; - - if (targetPredecessorChangeList) - { - property.ulPropTag = PidTagPredecessorChangeList; - property.value.bin = *targetPredecessorChangeList; - aRow.cValues = 1; - aRow.lpProps = &property; - rc = [destMsg addPropertiesFromRow: &aRow]; - if (rc != MAPISTORE_SUCCESS) - { - [self errorWithFormat: @"Cannot add PredecessorChangeList on move"]; - goto end; - } - } - [destMsg save: memCtx]; - if (!wantCopy) - /* We want to keep mid for restoring/shared data to work if mids are different. */ - deleteFlags = (srcMid == targetMid) ? MAPISTORE_PERMANENT_DELETE : MAPISTORE_SOFT_DELETE; - rc = [sourceFolder deleteMessageWithMID: srcMid andFlags: deleteFlags]; - - end: - //talloc_free (memCtx); - - return rc; -} - -- (enum mapistore_error) moveCopyMessagesWithMIDs: (uint64_t *) srcMids - andCount: (uint32_t) midCount - fromFolder: (MAPIStoreFolder *) sourceFolder - withMIDs: (uint64_t *) targetMids - andChangeKeys: (struct Binary_r **) targetChangeKeys - andPredecessorChangeLists: (struct Binary_r **) targetPredecessorChangeLists - wantCopy: (uint8_t) wantCopy - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_SUCCESS; - NSUInteger count; - NSMutableArray *oldMessageURLs; - NSString *oldMessageURL; - MAPIStoreMapping *mapping; - SOGoUser *ownerUser; - struct Binary_r *targetChangeKey, *targetPredecessorChangeList; - //TALLOC_CTX *memCtx; - - //memCtx = talloc_zero (NULL, TALLOC_CTX); - - ownerUser = [[self userContext] sogoUser]; - - if (wantCopy || [[context activeUser] isEqual: ownerUser]) - { - if ([sourceFolder isKindOfClass: isa] - || [self isKindOfClass: [sourceFolder class]]) - [self logWithFormat: @"%s: this class could probably implement" - @" a specialized/optimized version", __FUNCTION__]; - oldMessageURLs = [NSMutableArray arrayWithCapacity: midCount]; - mapping = [self mapping]; - for (count = 0; rc == MAPISTORE_SUCCESS && count < midCount; count++) - { - oldMessageURL = [mapping urlFromID: srcMids[count]]; - if (oldMessageURL) - { - [oldMessageURLs addObject: oldMessageURL]; - if (targetChangeKeys && targetPredecessorChangeList) - { - targetChangeKey = targetChangeKeys[count]; - targetPredecessorChangeList = targetPredecessorChangeLists[count]; - } - else - { - targetChangeKey = NULL; - targetPredecessorChangeList = NULL; - } - rc = [self _moveCopyMessageWithMID: srcMids[count] - fromFolder: sourceFolder - withMID: targetMids[count] - andChangeKey: targetChangeKey - andPredecessorChangeList: targetPredecessorChangeList - wantCopy: wantCopy - inMemCtx: memCtx]; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - } - - /* Notifications */ - if (rc == MAPISTORE_SUCCESS) - { - // We cleanup cache of our source and destination folders - [self cleanupCaches]; - [sourceFolder cleanupCaches]; - } - } - else - rc = MAPISTORE_ERR_DENIED; - - //talloc_free (memCtx); - - return rc; -} - -- (enum mapistore_error) moveCopyToFolder: (MAPIStoreFolder *) targetFolder - withNewName: (NSString *) newFolderName - isMove: (BOOL) isMove - isRecursive: (BOOL) isRecursive - inMemCtx: (TALLOC_CTX *) memCtx - -{ - enum mapistore_error rc; - NSAutoreleasePool *pool; - struct SRow folderRow; - struct SPropValue nameProperty; - MAPIStoreFolder *subFolder, *newFolder; - NSArray *children; - MAPIStoreMapping *mapping; - MAPIStoreMessage *message, *targetMessage; - NSUInteger count, max; - NSString *childKey; - uint64_t fmid; - //TALLOC_CTX *memCtx; - - //memCtx = talloc_zero (NULL, TALLOC_CTX); - - /* TODO: one possible issue with this algorithm is that moved messages will - lack a version number and will all be assigned a new one, even though - they have not changed. This also means that they will be transferred - again to the client during a sync operation. */ - - if ([targetFolder supportsSubFolders]) - { - mapping = [self mapping]; - - if (!newFolderName) - newFolderName = [sogoObject displayName]; - nameProperty.ulPropTag = PidTagDisplayName; - nameProperty.value.lpszW = [newFolderName UTF8String]; - folderRow.lpProps = &nameProperty; - folderRow.cValues = 1; - rc = [targetFolder createFolder: &folderRow - withFID: [self objectId] - andKey: &childKey]; - if (rc == MAPISTORE_SUCCESS) - { - newFolder = [targetFolder lookupFolder: childKey]; - [self copyPropertiesToObject: newFolder inMemCtx: memCtx]; - - pool = [NSAutoreleasePool new]; - children = [self messageKeys]; - max = [children count]; - for (count = 0; count < max; count++) - { - childKey = [children objectAtIndex: count]; - message = [self lookupMessage: childKey]; - targetMessage = [newFolder createMessage: NO]; - [targetMessage setIsNew: YES]; - [message copyToMessage: targetMessage inMemCtx: memCtx]; - if (isMove) - { - fmid = [mapping idFromURL: [message url]]; - [self deleteMessageWithMID: fmid andFlags: MAPISTORE_PERMANENT_DELETE]; - [mapping registerURL: [targetMessage url] - withID: fmid]; - } - [targetMessage save: memCtx]; - } - [pool release]; - - pool = [NSAutoreleasePool new]; - children = [self faiMessageKeys]; - max = [children count]; - for (count = 0; count < max; count++) - { - childKey = [children objectAtIndex: count]; - message = [self lookupFAIMessage: childKey]; - targetMessage = [newFolder createMessage: YES]; - [targetMessage setIsNew: YES]; - [message copyToMessage: targetMessage inMemCtx: memCtx]; - if (isMove) - { - fmid = [mapping idFromURL: [message url]]; - [self deleteMessageWithMID: fmid andFlags: MAPISTORE_PERMANENT_DELETE]; - [mapping registerURL: [targetMessage url] - withID: fmid]; - } - [targetMessage save: memCtx]; - } - [pool release]; - - if (isRecursive) - { - pool = [NSAutoreleasePool new]; - children = [self folderKeys]; - max = [children count]; - for (count = 0; count < max; count++) - { - childKey = [children objectAtIndex: count]; - subFolder = [self lookupFolder: childKey]; - [subFolder moveCopyToFolder: newFolder withNewName: nil - isMove: isMove - isRecursive: isRecursive - inMemCtx: memCtx]; - - } - [pool release]; - } - - if (isMove) - [self deleteFolder]; - - [targetFolder cleanupCaches]; - } - [self cleanupCaches]; - - /* We perform the mapping operations at the - end as objectId is required to be available - until the caches are cleaned up */ - if (isMove && rc == MAPISTORE_SUCCESS) - { - fmid = [mapping idFromURL: [self url]]; - [mapping unregisterURLWithID: fmid]; - [mapping registerURL: [newFolder url] - withID: fmid]; - } - - } - else - rc = MAPISTORE_ERR_DENIED; - - //talloc_free (memCtx); - - return rc; -} - -- (SOGoFolder *) aclFolder -{ - [self subclassResponsibility: _cmd]; - - return nil; -} - -- (NSArray *) expandRoles: (NSArray *) roles -{ - return roles; -} - -- (void) _modifyPermissionEntryForUser: (NSString *) user - withRoles: (NSArray *) roles - isAddition: (BOOL) isAddition - withACLFolder: (SOGoFolder *) aclFolder -{ - if (user) - { - if (isAddition) - [aclFolder addUserInAcls: user]; - [aclFolder setRoles: roles forUser: user]; - } - else - [self logWithFormat: @"user is nil, keeping intended entry intact"]; -} - -- (void) setupVersionsMessage -{ -} - -- (void) ensureIDsForChildKeys: (NSArray *) keys -{ - NSMutableArray *missingURLs; - MAPIStoreMapping *mapping; - NSUInteger count, max; - NSString *baseURL, *URL, *key; - NSArray *newIDs; - uint64_t idNbr; - bool softDeleted; - - baseURL = [self url]; - - mapping = [self mapping]; - max = [keys count]; - missingURLs = [NSMutableArray arrayWithCapacity: max]; - for (count = 0; count < max; count++) - { - key = [keys objectAtIndex: count]; - URL = [NSString stringWithFormat: @"%@%@", baseURL, key]; - idNbr = [mapping idFromURL: URL isSoftDeleted: &softDeleted]; - if (idNbr == NSNotFound && !softDeleted) - [missingURLs addObject: URL]; - } - - max = [missingURLs count]; - newIDs = [[self context] getNewFMIDs: max]; - [mapping registerURLs: missingURLs - withIDs: newIDs]; -} - -- (enum mapistore_error) getDeletedFMIDs: (struct UI8Array_r **) fmidsPtr - andCN: (uint64_t *) cnPtr - fromChangeNumber: (uint64_t) changeNum - inTableType: (enum mapistore_table_type) tableType - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - NSString *baseURL, *format, *url; - NSArray *keys; - NSNumber *cnNbr; - NSUInteger count, max; - MAPIStoreMapping *mapping; - struct UI8Array_r *fmids; - uint64_t fmid; - bool softDeleted; - - keys = [self getDeletedKeysFromChangeNumber: changeNum andCN: &cnNbr - inTableType: tableType]; - if (keys) - { - mapping = [self mapping]; - - max = [keys count]; - - fmids = talloc_zero (memCtx, struct UI8Array_r); - fmids->cValues = 0; - fmids->lpui8 = talloc_array (fmids, uint64_t, max); - *fmidsPtr = fmids; - if (max > 0) - *cnPtr = [cnNbr unsignedLongLongValue]; - - baseURL = [self url]; - if ([baseURL hasSuffix: @"/"]) - format = @"%@%@"; - else - format = @"%@/%@"; - - for (count = 0; count < max; count++) - { - url = [NSString stringWithFormat: format, - baseURL, [keys objectAtIndex: count]]; - fmid = [mapping idFromURL: url isSoftDeleted: &softDeleted]; - if (fmid != NSNotFound) /* if no fmid is returned, then the object - "never existed" in the OpenChange - databases. Soft-deleted messages are returned back */ - { - fmids->lpui8[fmids->cValues] = fmid; - fmids->cValues++; - } - } - - rc = MAPISTORE_SUCCESS; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getTable: (MAPIStoreTable **) tablePtr - andRowCount: (uint32_t *) countPtr - tableType: (enum mapistore_table_type) tableType - andHandleId: (uint32_t) handleId -{ - BOOL access; - enum mapistore_error rc = MAPISTORE_SUCCESS; - MAPIStoreTable *table; - SOGoUser *activeUser, *ownerUser; - - if (tableType == MAPISTORE_MESSAGE_TABLE) - table = [self messageTable]; - else if (tableType == MAPISTORE_FAI_TABLE) - table = [self faiMessageTable]; - else if (tableType == MAPISTORE_FOLDER_TABLE) - table = [self folderTable]; - else if (tableType == MAPISTORE_PERMISSIONS_TABLE) - { - ownerUser = [[self userContext] sogoUser]; - activeUser = [context activeUser]; - access = [activeUser isEqual: ownerUser]; - if (!access) - { - NSArray *roles; - - roles = [[self aclFolder] aclsForUser: [activeUser login]]; - roles = [self expandRoles: roles]; // Not required here - /* Check FolderVisible right to return the table */ - access = ([self exchangeRightsForRoles: roles] & RoleNone) != 0; - } - - if (access) - table = [self permissionsTable]; - else - rc = MAPISTORE_ERR_DENIED; - } - else - { - table = nil; - [NSException raise: @"MAPIStoreIOException" - format: @"unsupported table type: %d", tableType]; - } - - if (rc == MAPISTORE_SUCCESS) - { - if (table) - { - [table setHandleId: handleId]; - *tablePtr = table; - *countPtr = [[table childKeys] count]; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - } - - return rc; -} - -- (void) addProperties: (NSDictionary *) newProperties -{ - static enum MAPITAGS bannedProps[] = { PR_MID, PR_FID, PR_PARENT_FID, - PR_SOURCE_KEY, PR_PARENT_SOURCE_KEY, - PR_CHANGE_KEY, PidTagChangeNumber, 0x00000000 }; - enum MAPITAGS *currentProp; - NSMutableDictionary *propsCopy; - uint64_t cn; - - /* TODO: this should no longer be required once mapistore v2 API is in - place, when we can then do this from -dealloc below */ - - [dbFolder reloadIfNeeded]; - - propsCopy = [newProperties mutableCopy]; - [propsCopy autorelease]; - - currentProp = bannedProps; - while (*currentProp) - { - [propsCopy removeObjectForKey: MAPIPropertyKey (*currentProp)]; - currentProp++; - } - - [properties addEntriesFromDictionary: propsCopy]; - - /* Update change number after setting the properties */ - cn = [[self context] getNewChangeNumber]; - [properties setObject: [NSNumber numberWithUnsignedLongLong: cn] - forKey: MAPIPropertyKey (PidTagChangeNumber)]; - - [dbFolder save]; -} - -- (NSArray *) messageKeys -{ - return [self messageKeysMatchingQualifier: nil - andSortOrderings: nil]; - // if (!messageKeys) - // { - // messageKeys = [self messageKeysMatchingQualifier: nil - // andSortOrderings: nil]; - // [messageKeys retain]; - // } - - // return messageKeys; -} - -- (MAPIStoreFAIMessageTable *) faiMessageTable -{ - return [MAPIStoreFAIMessageTable tableForContainer: self]; -} - -- (NSArray *) faiMessageKeysMatchingQualifier: (EOQualifier *) qualifier - andSortOrderings: (NSArray *) sortOrderings -{ - [[self userContext] activate]; - return [dbFolder childKeysOfType: MAPIFAICacheObject - includeDeleted: NO - matchingQualifier: qualifier - andSortOrderings: sortOrderings]; -} - -- (NSArray *) faiMessageKeys -{ - return [self faiMessageKeysMatchingQualifier: nil - andSortOrderings: nil]; - // if (!faiMessageKeys) - // { - // faiMessageKeys = [self faiMessageKeysMatchingQualifier: nil - // andSortOrderings: nil]; - // [faiMessageKeys retain]; - // } - - // return faiMessageKeys; -} - -- (MAPIStoreFolderTable *) folderTable -{ - return [MAPIStoreFolderTable tableForContainer: self]; -} - -- (NSArray *) folderKeys -{ - return [self folderKeysMatchingQualifier: nil - andSortOrderings: nil]; - // if (!folderKeys) - // { - // folderKeys = [self folderKeysMatchingQualifier: nil - // andSortOrderings: nil]; - // [folderKeys retain]; - // } - - // return folderKeys; -} - -- (NSArray *) folderKeysMatchingQualifier: (EOQualifier *) qualifier - andSortOrderings: (NSArray *) sortOrderings -{ - if (qualifier) - [self errorWithFormat: @"qualifier is not used for folders"]; - if (sortOrderings) - [self errorWithFormat: @"sort orderings are not used for folders"]; - - return [sogoObject toManyRelationshipKeys]; -} - -- (NSArray *) activeMessageTables -{ - return [[MAPIStoreActiveTables activeTables] - activeTablesForFMID: [self objectId] - andType: MAPISTORE_MESSAGE_TABLE]; -} - -- (NSArray *) activeFAIMessageTables -{ - return [[MAPIStoreActiveTables activeTables] - activeTablesForFMID: [self objectId] - andType: MAPISTORE_FAI_TABLE]; -} - -- (void) _cleanupTableCaches: (enum mapistore_table_type) tableType -{ - NSArray *tables; - NSUInteger count, max; - - tables = [[MAPIStoreActiveTables activeTables] - activeTablesForFMID: [self objectId] - andType: tableType]; - max = [tables count]; - for (count = 0; count < max; count++) - [[tables objectAtIndex: count] cleanupCaches]; -} - -- (void) cleanupCaches -{ - [self _cleanupTableCaches: MAPISTORE_MESSAGE_TABLE]; - [self _cleanupTableCaches: MAPISTORE_FAI_TABLE]; - [self _cleanupTableCaches: MAPISTORE_FOLDER_TABLE]; - // [faiMessageKeys release]; - // faiMessageKeys = nil; - // [messageKeys release]; - // messageKeys = nil; - // [folderKeys release]; - // folderKeys = nil; -} - -- (enum mapistore_error) getPidTagParentFolderId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongLongValue (memCtx, [container objectId]); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagFolderId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongLongValue (memCtx, [self objectId]); - - return MAPISTORE_SUCCESS; -} - -/* - Possible values are: - - 0x00000001 Modify - 0x00000002 Read - 0x00000004 Delete - 0x00000008 Create Hierarchy Table - 0x00000010 Create Contents Table - 0x00000020 Create Associated Contents Table -*/ -- (enum mapistore_error) getPidTagAccess: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - uint32_t access = 0; - SOGoUser *ownerUser; - BOOL userIsOwner; - - ownerUser = [[self userContext] sogoUser]; - - userIsOwner = [[context activeUser] isEqual: ownerUser]; - if (userIsOwner || [self subscriberCanModifyMessages]) - access |= 0x01; - if (userIsOwner || [self subscriberCanReadMessages]) - access |= 0x02; - if (userIsOwner || [self subscriberCanDeleteMessages]) - access |= 0x04; - if ((userIsOwner || [self subscriberCanCreateSubFolders]) - && [self supportsSubFolders]) - access |= 0x08; - if (userIsOwner || [self subscriberCanCreateMessages]) - access |= 0x10; - if (userIsOwner) - access |= 0x20; - - *data = MAPILongValue (memCtx, access); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagRights: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - uint32_t rights = 0; - SOGoUser *activeUser, *ownerUser; - - ownerUser = [[self userContext] sogoUser]; - activeUser = [context activeUser]; - - if ([activeUser isEqual: ownerUser]) - { - rights = RightsReadItems | RightsCreateItems | RightsEditOwn | RightsEditAll - | RightsDeleteOwn | RightsDeleteAll | RightsFolderOwner | RightsFolderContact | RoleNone; - if ([self supportsSubFolders]) - rights |= RightsCreateSubfolders; - } - else - { - NSArray *roles; - - roles = [[self aclFolder] aclsForUser: [activeUser login]]; - roles = [self expandRoles: roles]; - rights = [self exchangeRightsForRoles: roles]; - /* FreeBusySimple and FreeBusyDetailed does not apply here - [MS-OXCFOLD] Section 2.2.2.2.2.8 */ - rights &= ~RightsFreeBusySimple & ~RightsFreeBusyDetailed; - } - - *data = MAPILongValue (memCtx, rights); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAccessControlListData: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [[NSData data] asBinaryInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAttributeHidden: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getNo: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagAttributeSystem: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getNo: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagAttributeReadOnly: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getNo: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagSubfolders: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPIBoolValue (memCtx, [self supportsSubFolders] && [[self folderKeys] count] > 0); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagFolderChildCount: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, [[self folderKeys] count]); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagContentCount: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, [[self messageKeys] count]); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagContentUnreadCount: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, 0); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAssociatedContentCount: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, [[self faiMessageKeys] count]); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagDeletedCountTotal: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - /* TODO */ - *data = MAPILongValue (memCtx, 0); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagLocalCommitTimeMax: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_SUCCESS; - NSDate *date; - - date = [self lastMessageModificationTime]; - if (date) - *data = [date asFileTimeInMemCtx: memCtx]; - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidTagDefaultPostMessageClass: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [@"IPM.Note" asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getProperties: (struct mapistore_property_data *) data - withTags: (enum MAPITAGS *) tags - andCount: (uint16_t) columnCount - inMemCtx: (TALLOC_CTX *) memCtx -{ - [dbFolder reloadIfNeeded]; - - return [super getProperties: data - withTags: tags - andCount: columnCount - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getProperty: (void **) data - withTag: (enum MAPITAGS) propTag - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - id value; - - value = [properties objectForKey: MAPIPropertyKey (propTag)]; - if (value) - rc = [value getValue: data forTag: propTag inMemCtx: memCtx]; - else - rc = [super getProperty: data withTag: propTag inMemCtx: memCtx]; - - return rc; -} - -- (MAPIStoreMessage *) _createAssociatedMessage -{ - MAPIStoreMessage *newMessage; - SOGoMAPIDBMessage *dbObject; - NSString *newKey; - - newKey = [NSString stringWithFormat: @"%@.plist", - [SOGoObject globallyUniqueObjectId]]; - dbObject = [SOGoMAPIDBMessage objectWithName: newKey inContainer: dbFolder]; - [dbObject setObjectType: MAPIFAICacheObject]; - [dbObject setIsNew: YES]; - newMessage = [MAPIStoreFAIMessageK mapiStoreObjectWithSOGoObject: dbObject - inContainer: self]; - - return newMessage; -} - -- (MAPIStoreMessage *) createMessage: (BOOL) isAssociated -{ - MAPIStoreMessage *newMessage; - WOContext *woContext; - - [[self userContext] activate]; - - if (isAssociated) - newMessage = [self _createAssociatedMessage]; - else - newMessage = [self createMessage]; - /* FIXME: this is ugly as the specifics of message creation should all be - delegated to subclasses */ - if ([newMessage respondsToSelector: @selector (setIsNew:)]) - [newMessage setIsNew: YES]; - woContext = [[self userContext] woContext]; - /* FIXME: this is ugly too as the specifics of message creation should all - be delegated to subclasses */ - if ([newMessage respondsToSelector: @selector (sogoObject:)]) - [[newMessage sogoObject] setContext: woContext]; - - return newMessage; -} - -- (enum mapistore_error) createFolder: (struct SRow *) aRow - withFID: (uint64_t) newFID - andKey: (NSString **) newKeyP -{ - [self errorWithFormat: @"new folders cannot be created in this context"]; - - return MAPISTORE_ERR_DENIED; -} - -/* helpers */ - -- (NSString *) url -{ - NSString *url; - - if (container) - url = [NSString stringWithFormat: @"%@/", [super url]]; - else - { - url = [[context url] absoluteString]; - if (![url hasSuffix: @"/"]) - url = [NSString stringWithFormat: @"%@/", url]; - } - - return url; -} - -- (MAPIStorePermissionsTable *) permissionsTable -{ - return [MAPIStorePermissionsTable tableForContainer: self]; -} - -- (NSArray *) permissionEntries -{ - NSMutableArray *permissionEntries; - MAPIStorePermissionEntry *entry; - NSArray *aclUsers; - uint64_t memberId, regularMemberId = 1; - NSUInteger count, max; - NSString *username, *defaultUserId; - SOGoFolder *aclFolder; - - aclFolder = [self aclFolder]; - - defaultUserId = [aclFolder defaultUserID]; - aclUsers = [aclFolder aclUsers]; - max = [aclUsers count]; - permissionEntries = [NSMutableArray arrayWithCapacity: max]; - for (count = 0; count < max; count++) - { - username = [aclUsers objectAtIndex: count]; - if (![username hasPrefix: @"@"]) - { - if ([username isEqualToString: defaultUserId]) - memberId = 0; - else if ([username isEqualToString: @"anonymous"]) - memberId = ULLONG_MAX; - else - { - memberId = regularMemberId; - regularMemberId++; - } - entry = [MAPIStorePermissionEntry entryWithUserId: username - andMemberId: memberId - forFolder: self]; - [permissionEntries addObject: entry]; - } - } - - return permissionEntries; -} - -- (NSArray *) rolesForExchangeRights: (uint32_t) rights -{ - [self subclassResponsibility: _cmd]; - return nil; -} - -- (uint32_t) exchangeRightsForRoles: (NSArray *) roles -{ - [self subclassResponsibility: _cmd]; - return 0; -} - -- (NSString *) _usernameFromEntryId: (struct SBinary_short *) bin -{ - struct Binary_r bin32; - struct AddressBookEntryId *entryId; - NSString *username; - - if (bin && bin->cb) - { - bin32.cb = bin->cb; - bin32.lpb = bin->lpb; - - entryId = get_AddressBookEntryId (NULL, &bin32); - if (entryId) - { - username = MAPIStoreSamDBUserAttribute ([[self context] connectionInfo], - @"legacyExchangeDN", - [NSString stringWithUTF8String: entryId->X500DN], - @"sAMAccountName"); - } - else - username = nil; - talloc_free (entryId); - } - else - username = nil; - - return username; -} - -- (NSString *) _usernameFromMemberId: (uint64_t) memberId - inEntries: (NSArray *) entries -{ - NSString *username = nil; - NSUInteger count, max; - MAPIStorePermissionEntry *entry; - - if (memberId == 0) - username = [[self aclFolder] defaultUserID]; - else if (memberId == ULLONG_MAX) - username = @"anonymous"; - else - { - max = [entries count]; - for (count = 0; !username && count < max; count++) - { - entry = [entries objectAtIndex: count]; - if ([entry memberId] == memberId) - username = [entry userId]; - } - } - - return username; -} - -- (void) _emptyACL -{ - NSUInteger count, max; - NSArray *users; - SOGoFolder *aclFolder; - - aclFolder = [self aclFolder]; - - users = [[aclFolder aclUsers] copy]; - max = [users count]; - for (count = 0; count < max; count++) - [aclFolder removeUserFromAcls: [users objectAtIndex: count]]; - - [users release]; -} - -- (enum mapistore_error) modifyPermissions: (struct PermissionData *) permissions - withCount: (uint16_t) pcount - andFlags: (int8_t) flags -{ - NSUInteger count, propCount; - struct PermissionData *currentPermission; - struct mapi_SPropValue *mapiValue; - NSString *permissionUser; - NSArray *entries; - NSArray *permissionRoles; - BOOL reset, isAdd = NO, isDelete = NO, isModify = NO; - SOGoFolder *aclFolder; - SOGoUser *activeUser, *ownerUser; - - /* Check if we have permissions to modify the permissions. - See [MS-OXCPERM] Section 3.2.5.2 for details */ - ownerUser = [[self userContext] sogoUser]; - activeUser = [context activeUser]; - if (![activeUser isEqual: ownerUser]) - { - /* Check if we have FolderOwner right */ - NSArray *roles; - - roles = [[self aclFolder] aclsForUser: [activeUser login]]; - roles = [self expandRoles: roles]; // Not required - if (([self exchangeRightsForRoles: roles] & RightsFolderOwner) == 0) - return MAPISTORE_ERR_DENIED; - } - - aclFolder = [self aclFolder]; - - reset = ((flags & ModifyPerms_ReplaceRows) != 0); - if (reset) - [self _emptyACL]; - - entries = [self permissionEntries]; - - for (count = 0; count < pcount; count++) - { - currentPermission = permissions + count; - - permissionUser = nil; - permissionRoles = nil; - - if (currentPermission->PermissionDataFlags == ROW_ADD) - isAdd = YES; - else if (currentPermission->PermissionDataFlags == ROW_MODIFY) - isModify = YES; - else - isDelete = YES; - - for (propCount = 0; - propCount < currentPermission->lpProps.cValues; - propCount++) - { - mapiValue = currentPermission->lpProps.lpProps + propCount; - switch (mapiValue->ulPropTag) - { - case PR_ENTRYID: - if (isAdd) - permissionUser - = [self _usernameFromEntryId: &mapiValue->value.bin]; - break; - case PR_MEMBER_ID: - if (isModify || isDelete) - permissionUser = [self _usernameFromMemberId: mapiValue->value.d - inEntries: entries]; - break; - case PR_MEMBER_RIGHTS: - if (isAdd || isModify) - permissionRoles - = [self rolesForExchangeRights: mapiValue->value.l]; - break; - default: - if (mapiValue->ulPropTag != PR_MEMBER_NAME) - [self warnWithFormat: @"unhandled permission property: %.8x", - mapiValue->ulPropTag]; - } - } - - if (reset) - { - if (isAdd) - [self _modifyPermissionEntryForUser: permissionUser - withRoles: permissionRoles - isAddition: YES - withACLFolder: aclFolder]; - } - else - { - if (isAdd || currentPermission->PermissionDataFlags == ROW_MODIFY) - [self _modifyPermissionEntryForUser: permissionUser - withRoles: permissionRoles - isAddition: isAdd - withACLFolder: aclFolder]; - else if (currentPermission->PermissionDataFlags == ROW_REMOVE) - [aclFolder removeUserFromAcls: permissionUser]; - else - [self errorWithFormat: @"unhandled permission action flag: %d", - currentPermission->PermissionDataFlags]; - } - } - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) preloadMessageBodiesWithMIDs: (const struct UI8Array_r *) mids - ofTableType: (enum mapistore_table_type) tableType -{ - uint32_t count; - NSMutableArray *messageKeys; - MAPIStoreMapping *mapping; - NSString *messageURL, *messageKey; - - messageKeys = [NSMutableArray arrayWithCapacity: mids->cValues]; - - mapping = [self mapping]; - for (count = 0; count < mids->cValues; count++) - { - messageURL = [mapping urlFromID: mids->lpui8[count]]; - if (messageURL) - { - messageKey = [self childKeyFromURL: messageURL]; - if (messageKey) - [messageKeys addObject: messageKey]; - } - } - - return [self preloadMessageBodiesWithKeys: messageKeys - ofTableType: tableType]; -} - -- (enum mapistore_error) preloadMessageBodiesWithKeys: (NSArray *) keys - ofTableType: (enum mapistore_table_type) tableType -{ - return MAPISTORE_SUCCESS; -} - -- (uint64_t) objectId -{ - uint64_t objectId; - NSString *folderKey; - - if (container) - { - folderKey = [NSString stringWithFormat: @"%@/", - [sogoObject nameInContainer]]; - objectId = [container idForObjectWithKey: folderKey]; - } - else - objectId = [self idForObjectWithKey: nil]; - - return objectId; -} - -- (uint64_t) idForObjectWithKey: (NSString *) childKey -{ - return [[self context] idForObjectWithKey: childKey - inFolderURL: [self url]]; -} - -- (MAPIStoreFolder *) rootContainer -{ - /* Return the oldest ancestor, which does not have - container. If there is not container, it returns itself. - */ - if (container) - return [container rootContainer]; - else - return self; -} - -- (NSDate *) creationTime -{ - return [dbFolder creationDate]; -} - -- (NSDate *) lastModificationTime -{ - return [dbFolder lastModified]; -} - -/* subclasses */ - -- (MAPIStoreMessageTable *) messageTable -{ - return nil; -} - -- (NSArray *) messageKeysMatchingQualifier: (EOQualifier *) qualifier - andSortOrderings: (NSArray *) sortOrderings -{ - [self subclassResponsibility: _cmd]; - - return nil; -} - -- (NSArray *) getDeletedKeysFromChangeNumber: (uint64_t) changeNum - andCN: (NSNumber **) cnNbrs - inTableType: (enum mapistore_table_type) tableType -{ - return nil; -} - -- (MAPIStoreMessage *) createMessage -{ - [self logWithFormat: @"ignored method: %s", __PRETTY_FUNCTION__]; - return nil; -} - -- (NSCalendarDate *) lastMessageModificationTime -{ - [self subclassResponsibility: _cmd]; - - return nil; -} - -- (BOOL) subscriberCanCreateMessages -{ - return NO; -} - -- (BOOL) subscriberCanModifyMessages -{ - return NO; -} - -- (BOOL) subscriberCanReadMessages -{ - return NO; -} - -- (BOOL) subscriberCanDeleteMessages -{ - return NO; -} - -- (BOOL) subscriberCanCreateSubFolders -{ - return NO; -} - -- (BOOL) supportsSubFolders -{ - return NO; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreFolderTable.h b/Attic/OpenChange/MAPIStoreFolderTable.h deleted file mode 100644 index b584c6084..000000000 --- a/Attic/OpenChange/MAPIStoreFolderTable.h +++ /dev/null @@ -1,31 +0,0 @@ -/* MAPIStoreFolderTable.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 MAPISTOREFOLDERTABLE_H -#define MAPISTOREFOLDERTABLE_H - -#import "MAPIStoreTable.h" - -@interface MAPIStoreFolderTable : MAPIStoreTable -@end - -#endif /* MAPISTOREFOLDERTABLE_H */ diff --git a/Attic/OpenChange/MAPIStoreFolderTable.m b/Attic/OpenChange/MAPIStoreFolderTable.m deleted file mode 100644 index d76c9890e..000000000 --- a/Attic/OpenChange/MAPIStoreFolderTable.m +++ /dev/null @@ -1,118 +0,0 @@ -/* MAPIStoreFolderTable.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -#import - -#import - -#import "MAPIStoreFolder.h" -#import "MAPIStoreTypes.h" - -#import "MAPIStoreFolderTable.h" - -#undef DEBUG -#include -#include -#include - -@implementation MAPIStoreFolderTable - -- (id) init -{ - if ((self = [super init])) - { - tableType = MAPISTORE_FOLDER_TABLE; - } - - return self; -} - -- (NSArray *) childKeys -{ - if (!childKeys) - { - childKeys = [(MAPIStoreFolder *) - container folderKeysMatchingQualifier: nil - andSortOrderings: sortOrderings]; - [childKeys retain]; - } - - return childKeys; -} - -- (NSArray *) restrictedChildKeys -{ - NSArray *keys; - - /* FIXME: restrictions are ignored on folder tables */ - - if (!restrictedChildKeys) - { - if (restrictionState != MAPIRestrictionStateAlwaysTrue) - { - if (restrictionState == MAPIRestrictionStateNeedsEval) - keys = [(MAPIStoreFolder *) - container folderKeysMatchingQualifier: restriction - andSortOrderings: sortOrderings]; - else - keys = [NSArray array]; - } - else - keys = [self childKeys]; - - ASSIGN (restrictedChildKeys, keys); - } - - return restrictedChildKeys; -} - -- (MAPIRestrictionState) evaluatePropertyRestriction: (struct mapi_SPropertyRestriction *) res - intoQualifier: (EOQualifier **) qualifier -{ - MAPIRestrictionState rc; - - switch ((uint32_t) res->ulPropTag) - { - /* HACK: we cheat here as we current have no mechanism for searching - folders based on PR_CHANGE_NUM, which is used by the oxcfxics - mechanism... */ - case PidTagChangeNumber: - rc = MAPIRestrictionStateAlwaysTrue; - break; - default: - rc = [super evaluatePropertyRestriction: res intoQualifier: qualifier]; - } - - return rc; -} - -- (id) lookupChild: (NSString *) childKey -{ - return [(MAPIStoreFolder *) container lookupFolder: childKey]; -} - -- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property -{ - return nil; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreGCSBaseContext.h b/Attic/OpenChange/MAPIStoreGCSBaseContext.h deleted file mode 100644 index 8d9e57f5d..000000000 --- a/Attic/OpenChange/MAPIStoreGCSBaseContext.h +++ /dev/null @@ -1,37 +0,0 @@ -/* MAPIStoreGCSBaseContext.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 MAPISTOREGCSBASECONTEXT_H -#define MAPISTOREGCSBASECONTEXT_H - -#import "MAPIStoreContext.h" - -@class EOQualifier; - -@interface MAPIStoreGCSBaseContext : MAPIStoreContext - -+ (NSString *) folderNameSuffix; -+ (NSString *) getFolderDisplayName: (NSString *) sogoDisplayName; - -@end - -#endif /* MAPISTOREGCSBASECONTEXT_H */ diff --git a/Attic/OpenChange/MAPIStoreGCSBaseContext.m b/Attic/OpenChange/MAPIStoreGCSBaseContext.m deleted file mode 100644 index e0f06482d..000000000 --- a/Attic/OpenChange/MAPIStoreGCSBaseContext.m +++ /dev/null @@ -1,145 +0,0 @@ -/* MAPIStoreGCSBaseContext.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -#import -#import -#import - -#import -#import - -#import "MAPIApplication.h" -#import "MAPIStoreUserContext.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreGCSBaseContext.h" - -#undef DEBUG -#include -#include - -@implementation MAPIStoreGCSBaseContext - -+ (NSString *) MAPIModuleName -{ - return nil; -} - -+ (NSString *) folderNameSuffix -{ - return @""; -} - -+ (NSString *) getFolderDisplayName: (NSString *) sogoDisplayName -{ - NSString *suffix, *displayName; - - suffix = [self folderNameSuffix]; - if ([suffix length] > 0 && ![sogoDisplayName hasSuffix: suffix]) - displayName = [NSString stringWithFormat: @"%@ (%@)", - sogoDisplayName, suffix]; - else - displayName = sogoDisplayName; - - return displayName; -} - -+ (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName - withIndexing: (struct indexing_context *) indexing - inMemCtx: (TALLOC_CTX *) memCtx -{ - struct mapistore_contexts_list *firstContext = NULL, *context; - NSString *moduleName, *baseUrl, *url, *nameInContainer, *displayName; - NSArray *subfolders; - MAPIStoreUserContext *userContext; - SOGoParentFolder *parentFolder; - NSUInteger count, max; - SOGoGCSFolder *currentFolder; - - moduleName = [self MAPIModuleName]; - if (moduleName) - { - userContext = [MAPIStoreUserContext userContextWithUsername: userName - andTDBIndexing: indexing]; - parentFolder = [[userContext rootFolders] objectForKey: moduleName]; - baseUrl = [NSString stringWithFormat: @"sogo://%@@%@/", - [userName stringByReplacingOccurrencesOfString: @"@" - withString: @"%40"], - moduleName]; - - subfolders = [parentFolder subFolders]; - max = [subfolders count]; - for (count = 0; count < max; count++) - { - currentFolder = [subfolders objectAtIndex: count]; - if ([[currentFolder ownerInContext: nil] isEqualToString: userName]) - { - context = talloc_zero (memCtx, struct mapistore_contexts_list); - nameInContainer = [currentFolder nameInContainer]; - url = [NSString stringWithFormat: @"%@%@", baseUrl, nameInContainer]; - context->url = [url asUnicodeInMemCtx: context]; - displayName = [self getFolderDisplayName: [currentFolder displayName]]; - context->name = [displayName asUnicodeInMemCtx: context]; - context->main_folder = [nameInContainer isEqualToString: @"personal"]; - context->role = [self MAPIContextRole]; - context->tag = "tag"; - DLIST_ADD_END (firstContext, context, void); - } - } - } - - return firstContext; -} - -+ (NSString *) - createRootSecondaryFolderWithFID: (uint64_t) fid - andName: (NSString *) folderName - forUser: (NSString *) userName -{ - NSString *mapistoreURI, *nameInContainer, *moduleName; - MAPIStoreUserContext *userContext; - SOGoParentFolder *parentFolder; - - userContext = [MAPIStoreUserContext userContextWithUsername: userName - andTDBIndexing: NULL]; - moduleName = [self MAPIModuleName]; - parentFolder = [[userContext rootFolders] objectForKey: moduleName]; - nameInContainer = nil; - - if (![parentFolder newFolderWithName: folderName - nameInContainer: &nameInContainer]) - mapistoreURI = [NSString stringWithFormat: @"sogo://%@@%@/%@/", - [userName stringByReplacingOccurrencesOfString: @"@" - withString: @"%40"], - moduleName, nameInContainer]; - else - mapistoreURI = nil; - - return mapistoreURI; -} - -- (id) rootSOGoFolder -{ - return [[userContext rootFolders] objectForKey: [isa MAPIModuleName]]; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreGCSFolder.h b/Attic/OpenChange/MAPIStoreGCSFolder.h deleted file mode 100644 index de2b9692b..000000000 --- a/Attic/OpenChange/MAPIStoreGCSFolder.h +++ /dev/null @@ -1,64 +0,0 @@ -/* MAPIStoreGCSFolder.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTOREGCSFOLDER_H -#define MAPISTOREGCSFOLDER_H - -#import "MAPIStoreFolder.h" - -@class NSArray; -@class NSCalendarDate; -@class NSData; -@class NSMutableDictionary; -@class NSNumber; -@class NSString; - -@interface MAPIStoreGCSFolder : MAPIStoreFolder -{ - SOGoMAPIDBMessage *versionsMessage; - NSArray *activeUserRoles; - EOQualifier *componentQualifier; -} - -/* synchronisation */ -- (BOOL) synchroniseCache; -- (BOOL) synchroniseCacheFor: (NSString *) nameInContainer; -- (void) updateVersionsForMessageWithKey: (NSString *) messageKey - withChangeKey: (NSData *) oldChangeKey - andPredecessorChangeList: (NSData *) pcl; -- (NSNumber *) lastModifiedFromMessageChangeNumber: (NSString *) changeNumber; -- (NSString *) changeNumberForMessageWithKey: (NSString *) messageKey; -- (NSData *) changeKeyForMessageWithKey: (NSString *) messageKey; -- (NSData *) predecessorChangeListForMessageWithKey: (NSString *) messageKey; - -- (NSArray *) activeUserRoles; - -- (EOQualifier *) componentQualifier; -- (EOQualifier *) contentComponentQualifier; - -/* subclasses */ -- (EOQualifier *) aclQualifier; -- (NSString *) component; - -@end - -#endif /* MAPISTOREGCSFOLDER_H */ diff --git a/Attic/OpenChange/MAPIStoreGCSFolder.m b/Attic/OpenChange/MAPIStoreGCSFolder.m deleted file mode 100644 index 9b269df35..000000000 --- a/Attic/OpenChange/MAPIStoreGCSFolder.m +++ /dev/null @@ -1,893 +0,0 @@ -/* MAPIStoreGCSFolder.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#import "MAPIStoreGCSBaseContext.h" -#import "MAPIStoreTypes.h" -#import "MAPIStoreUserContext.h" -#import "NSData+MAPIStore.h" -#import "NSDate+MAPIStore.h" -#import "NSString+MAPIStore.h" -#import "SOGoMAPIDBMessage.h" - -#import "MAPIStoreGCSFolder.h" - -#undef DEBUG -#include -#include - -static Class NSNumberK; - -@implementation MAPIStoreGCSFolder - -+ (void) initialize -{ - NSNumberK = [NSNumber class]; -} - -- (id) initWithSOGoObject: (id) newSOGoObject - inContainer: (MAPIStoreObject *) newContainer -{ - if ((self = [super initWithSOGoObject: newSOGoObject inContainer: newContainer])) - { - activeUserRoles = nil; - } - - return self; -} - -- (void) setupVersionsMessage -{ - ASSIGN (versionsMessage, - [SOGoMAPIDBMessage objectWithName: @"versions.plist" - inContainer: dbFolder]); - [versionsMessage setObjectType: MAPIInternalCacheObject]; - [versionsMessage reloadIfNeeded]; -} - -- (void) dealloc -{ - [versionsMessage release]; - [activeUserRoles release]; - [componentQualifier release]; - [super dealloc]; -} - -- (enum mapistore_error) deleteFolder -{ - enum mapistore_error rc; - NSException *error; - NSString *name; - - name = [self nameInContainer]; - if ([name isEqualToString: @"personal"]) - rc = MAPISTORE_ERR_DENIED; - else - { - [[sogoObject container] removeSubFolder: name]; - error = [(SOGoGCSFolder *) sogoObject delete]; - if (error) - rc = MAPISTORE_ERROR; - else - { - if (![versionsMessage delete]) - rc = MAPISTORE_SUCCESS; - else - rc = MAPISTORE_ERROR; - } - } - - return (rc == MAPISTORE_SUCCESS) ? [super deleteFolder] : rc; -} - -- (void) setDisplayName: (NSString *) newDisplayName -{ - NSString *suffix, *fullSuffix; - Class cClass; - - cClass = [(MAPIStoreGCSBaseContext *) [self context] class]; - - /* if a suffix exists, we strip it from the final name */ - suffix = [cClass folderNameSuffix]; - if ([suffix length] > 0) - { - fullSuffix = [NSString stringWithFormat: @"(%@)", suffix]; - if ([newDisplayName hasSuffix: fullSuffix]) - { - newDisplayName = [newDisplayName substringToIndex: - [newDisplayName length] - - [fullSuffix length]]; - newDisplayName = [newDisplayName stringByTrimmingSpaces]; - } - } - - if (![[sogoObject displayName] isEqualToString: newDisplayName]) - [sogoObject renameTo: newDisplayName]; -} - -- (enum mapistore_error) getPidTagDisplayName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *displayName; - Class cClass; - - cClass = [(MAPIStoreGCSBaseContext *) [self context] class]; - displayName = [cClass getFolderDisplayName: [sogoObject displayName]]; - *data = [displayName asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (void) addProperties: (NSDictionary *) newProperties -{ - NSString *newDisplayName; - NSMutableDictionary *propsCopy; - NSNumber *key; - - key = MAPIPropertyKey (PR_DISPLAY_NAME_UNICODE); - newDisplayName = [newProperties objectForKey: key]; - if (newDisplayName) - { - [self setDisplayName: newDisplayName]; - propsCopy = [newProperties mutableCopy]; - [propsCopy removeObjectForKey: key]; - [propsCopy autorelease]; - newProperties = propsCopy; - } - - [super addProperties: newProperties]; -} - -- (NSArray *) messageKeysMatchingQualifier: (EOQualifier *) qualifier - andSortOrderings: (NSArray *) sortOrderings -{ - static NSArray *fields = nil; - SOGoUser *ownerUser; - NSArray *records; - NSMutableArray *qualifierArray; - EOQualifier *fetchQualifier, *aclQualifier; - GCSFolder *ocsFolder; - EOFetchSpecification *fs; - NSArray *keys; - - if (!fields) - fields = [[NSArray alloc] - initWithObjects: @"c_name", @"c_version", nil]; - - qualifierArray = [NSMutableArray new]; - ownerUser = [[self userContext] sogoUser]; - if (![[context activeUser] isEqual: ownerUser]) - { - aclQualifier = [self aclQualifier]; - if (aclQualifier) - [qualifierArray addObject: aclQualifier]; - } - [qualifierArray addObject: [self componentQualifier]]; - if (qualifier) - [qualifierArray addObject: qualifier]; - - fetchQualifier = [[EOAndQualifier alloc] - initWithQualifierArray: qualifierArray]; - - ocsFolder = [sogoObject ocsFolder]; - fs = [EOFetchSpecification - fetchSpecificationWithEntityName: [ocsFolder folderName] - qualifier: fetchQualifier - sortOrderings: sortOrderings]; - [fetchQualifier release]; - [qualifierArray release]; - records = [ocsFolder fetchFields: fields fetchSpecification: fs]; - keys = [records objectsForKey: @"c_name" - notFoundMarker: nil]; - - return keys; -} - -- (NSDate *) lastMessageModificationTime -{ - NSDate *value; - NSNumber *ti; - - [self synchroniseCache]; - - ti = [[versionsMessage properties] - objectForKey: @"SyncLastModificationDate"]; - if (ti) - value = [NSDate dateWithTimeIntervalSince1970: [ti doubleValue]]; - else - value = nil; - - return value; -} - -- (SOGoFolder *) aclFolder -{ - return (SOGoFolder *) sogoObject; -} - -/* synchronisation */ - -/* Tree -{ - SyncLastModseq = x; - SyncLastSynchronisationDate = x; ** not updated until something changed - Messages = { - MessageKey = { - Version = x; - Modseq = x; - Deleted = b; - ChangeKey = d; - PredecessorChangeList = { guid1 = globcnt1, guid2 ... }; - }; - ... - }; - VersionMapping = { - Version = last-modified; - ... - } -} - */ -- (void) _setChangeKey: (NSData *) changeKey - forMessageEntry: (NSMutableDictionary *) messageEntry -{ - struct XID *xid; - NSString *guid; - NSData *globCnt; - NSDictionary *changeKeyDict; - NSMutableDictionary *changeList; - - xid = [changeKey asXIDInMemCtx: NULL]; - guid = [NSString stringWithGUID: &xid->NameSpaceGuid]; - globCnt = [NSData dataWithBytes: xid->LocalId.data length: xid->LocalId.length]; - talloc_free (xid); - - /* 1. set change key association */ - changeKeyDict = [NSDictionary dictionaryWithObjectsAndKeys: guid, @"GUID", - globCnt, @"LocalId", - nil]; - [messageEntry setObject: changeKeyDict forKey: @"ChangeKey"]; - - /* 2. append/update predecessor change list */ - changeList = [messageEntry objectForKey: @"PredecessorChangeList"]; - if (!changeList) - { - changeList = [NSMutableDictionary new]; - [messageEntry setObject: changeList - forKey: @"PredecessorChangeList"]; - [changeList release]; - } - [changeList setObject: globCnt forKey: guid]; -} - -- (void) _updatePredecessorChangeList: (NSData *) predecessorChangeList - forMessageEntry: (NSMutableDictionary *) messageEntry - withOldChangeKey: (NSData *) oldChangeKey -{ - NSData *globCnt, *oldGlobCnt; - NSDictionary *changeKeyDict; - NSString *guid; - NSMutableDictionary *changeList; - struct SizedXid *sizedXIDList; - struct XID xid, *givenChangeKey; - TALLOC_CTX *localMemCtx; - uint32_t i, length; - - localMemCtx = talloc_new (NULL); - if (!localMemCtx) - { - [self errorWithFormat: @"No more memory"]; - return; - } - - if (predecessorChangeList) - { - sizedXIDList = [predecessorChangeList asSizedXidArrayInMemCtx: localMemCtx with: &length]; - - changeList = [messageEntry objectForKey: @"PredecessorChangeList"]; - if (!changeList) - { - changeList = [NSMutableDictionary new]; - [messageEntry setObject: changeList - forKey: @"PredecessorChangeList"]; - [changeList release]; - } - - if (sizedXIDList) { - for (i = 0; i < length; i++) - { - xid = sizedXIDList[i].XID; - guid = [NSString stringWithGUID: &xid.NameSpaceGuid]; - globCnt = [NSData dataWithBytes: xid.LocalId.data length: xid.LocalId.length]; - oldGlobCnt = [changeList objectForKey: guid]; - if (!oldGlobCnt || ([globCnt compare: oldGlobCnt] == NSOrderedDescending)) - [changeList setObject: globCnt forKey: guid]; - } - } - } - - if (oldChangeKey) - { - givenChangeKey = [oldChangeKey asXIDInMemCtx: localMemCtx]; - if (givenChangeKey) { - guid = [NSString stringWithGUID: &givenChangeKey->NameSpaceGuid]; - globCnt = [NSData dataWithBytes: givenChangeKey->LocalId.data length: givenChangeKey->LocalId.length]; - - changeKeyDict = [messageEntry objectForKey: @"ChangeKey"]; - if (!changeKeyDict || - ([guid isEqualToString: [changeKeyDict objectForKey: @"GUID"]] - && ([globCnt compare: [changeKeyDict objectForKey: @"LocalId"]] == NSOrderedDescending))) - { - /* The given change key is greater than current one stored in - metadata or it does not exist */ - [messageEntry setObject: [NSDictionary dictionaryWithObjectsAndKeys: guid, @"GUID", - globCnt, @"LocalId", - nil] - forKey: @"ChangeKey"]; - } - } - } - - talloc_free (localMemCtx); -} - -- (EOQualifier *) componentQualifier -{ - if (!componentQualifier) - componentQualifier - = [[EOKeyValueQualifier alloc] initWithKey: @"c_component" - operatorSelector: EOQualifierOperatorEqual - value: [self component]]; - - return componentQualifier; -} - -- (EOQualifier *) contentComponentQualifier -{ - EOQualifier *contentComponentQualifier; - NSString *likeString; - - likeString = [NSString stringWithFormat: @"%%BEGIN:%@%%", - [[self component] uppercaseString]]; - contentComponentQualifier = [[EOKeyValueQualifier alloc] - initWithKey: @"c_content" - operatorSelector: EOQualifierOperatorLike - value: likeString]; - [contentComponentQualifier autorelease]; - - return contentComponentQualifier; -} - -- (BOOL) synchroniseCache -{ - BOOL rc = YES; - uint64_t newChangeNum; - NSData *changeKey; - NSString *cName, *changeNumber; - NSNumber *ti, *lastModificationDate, *cVersion, *cLastModified, *cDeleted; - EOFetchSpecification *fs; - EOQualifier *searchQualifier, *fetchQualifier; - NSUInteger count, max; - NSArray *fetchResults, *changeNumbers; - NSMutableArray *keys, *modifiedEntries; - NSDictionary *result; - NSMutableDictionary *currentProperties, *messages, *mapping, *messageEntry; - NSCalendarDate *now; - GCSFolder *ocsFolder; - static NSArray *fields = nil; - static EOSortOrdering *sortOrdering = nil; - - /* NOTE: we are using NSString instance for "changeNumber" because - NSNumber proved to give very bad performances when used as NSDictionary - keys with GNUstep 1.22.1. The bug seems to be solved with 1.24 but many - distros still ship an older version. */ - - if (!fields) - fields = [[NSArray alloc] - initWithObjects: @"c_name", @"c_version", @"c_lastmodified", - @"c_deleted", nil]; - - if (!sortOrdering) - { - sortOrdering = [EOSortOrdering sortOrderingWithKey: @"c_lastmodified" - selector: EOCompareAscending]; - [sortOrdering retain]; - } - - [versionsMessage reloadIfNeeded]; - currentProperties = [versionsMessage properties]; - - lastModificationDate = [currentProperties objectForKey: @"SyncLastModificationDate"]; - if (lastModificationDate) - { - searchQualifier = [[EOKeyValueQualifier alloc] - initWithKey: @"c_lastmodified" - operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo - value: lastModificationDate]; - fetchQualifier = [[EOAndQualifier alloc] - initWithQualifiers: searchQualifier, - [self contentComponentQualifier], - nil]; - [fetchQualifier autorelease]; - [searchQualifier release]; - } - else - fetchQualifier = [self componentQualifier]; - - ocsFolder = [sogoObject ocsFolder]; - fs = [EOFetchSpecification - fetchSpecificationWithEntityName: [ocsFolder folderName] - qualifier: fetchQualifier - sortOrderings: [NSArray arrayWithObject: sortOrdering]]; - fetchResults = [ocsFolder fetchFields: fields - fetchSpecification: fs - ignoreDeleted: NO]; - max = [fetchResults count]; - if (max > 0) - { - messages = [currentProperties objectForKey: @"Messages"]; - if (!messages) - { - messages = [NSMutableDictionary new]; - [currentProperties setObject: messages forKey: @"Messages"]; - [messages release]; - } - mapping = [currentProperties objectForKey: @"VersionMapping"]; - if (!mapping) - { - mapping = [NSMutableDictionary new]; - [currentProperties setObject: mapping forKey: @"VersionMapping"]; - [mapping release]; - } - - keys = [NSMutableArray arrayWithCapacity: max]; - modifiedEntries = [NSMutableArray arrayWithCapacity: max]; - for (count = 0; count < max; count++) - { - result = [fetchResults objectAtIndex: count]; - cName = [result objectForKey: @"c_name"]; - [keys addObject: cName]; - cDeleted = [result objectForKey: @"c_deleted"]; - if ([cDeleted isKindOfClass: NSNumberK] && [cDeleted intValue]) - cVersion = [NSNumber numberWithInt: -1]; - else - cVersion = [result objectForKey: @"c_version"]; - cLastModified = [result objectForKey: @"c_lastmodified"]; - - messageEntry = [messages objectForKey: cName]; - if (!messageEntry) - { - messageEntry = [NSMutableDictionary new]; - [messages setObject: messageEntry forKey: cName]; - [messageEntry release]; - } - - if (![[messageEntry objectForKey: @"c_version"] - isEqual: cVersion]) - { - [sogoObject removeChildRecordWithName: cName]; - - [modifiedEntries addObject: messageEntry]; - - [messageEntry setObject: cLastModified forKey: @"c_lastmodified"]; - [messageEntry setObject: cVersion forKey: @"c_version"]; - - if (!lastModificationDate - || ([lastModificationDate compare: cLastModified] - == NSOrderedAscending)) - lastModificationDate = cLastModified; - } - } - - /* make sure all returned objects have a corresponding mid */ - [self ensureIDsForChildKeys: keys]; - - max = [modifiedEntries count]; - if (max > 0) - { - changeNumbers = [[self context] getNewChangeNumbers: max]; - for (count = 0; count < max; count++) - { - messageEntry = [modifiedEntries objectAtIndex: count]; - - changeNumber = [changeNumbers objectAtIndex: count]; - cLastModified = [messageEntry objectForKey: @"c_lastmodified"]; - [mapping setObject: cLastModified forKey: changeNumber]; - [messageEntry setObject: changeNumber forKey: @"version"]; - - newChangeNum = [changeNumber unsignedLongLongValue]; - - // A GLOBCNT structure is a 6-byte global namespace counter, - // we strip the first 2 bytes. The first two bytes is the ReplicaId - changeKey = [self getReplicaKeyFromGlobCnt: newChangeNum >> 16]; - [self _setChangeKey: changeKey forMessageEntry: messageEntry]; - } - - now = [NSCalendarDate date]; - ti = [NSNumber numberWithDouble: [now timeIntervalSince1970]]; - [currentProperties setObject: ti - forKey: @"SyncLastSynchronisationDate"]; - [currentProperties setObject: lastModificationDate - forKey: @"SyncLastModificationDate"]; - [versionsMessage save]; - } - } - - return rc; -} - -- (BOOL) synchroniseCacheFor: (NSString *) nameInContainer -{ - /* Try to synchronise old messages in versions.plist cache using an - specific c_name. It returns a boolean indicating if the - synchronisation was carried out succesfully. - - It should be used as last resort, keeping synchroniseCache as the - main sync entry point. */ - - uint64_t changeNumber; - NSString *changeNumberStr; - NSData *changeKey; - NSNumber *cLastModified, *cDeleted, *cVersion; - EOFetchSpecification *fs; - EOQualifier *searchQualifier, *fetchQualifier; - NSArray *fetchResults; - NSDictionary *result; - NSMutableDictionary *currentProperties, *messages, *mapping, *messageEntry; - GCSFolder *ocsFolder; - static NSArray *fields; - - [versionsMessage reloadIfNeeded]; - currentProperties = [versionsMessage properties]; - - messages = [currentProperties objectForKey: @"Messages"]; - if (!messages) - { - messages = [NSMutableDictionary new]; - [currentProperties setObject: messages forKey: @"Messages"]; - [messages release]; - } - - messageEntry = [messages objectForKey: nameInContainer]; - if (!messageEntry) - { - /* Fetch the message by its name */ - if (!fields) - fields = [[NSArray alloc] - initWithObjects: @"c_name", @"c_version", @"c_lastmodified", - @"c_deleted", nil]; - - searchQualifier = [[EOKeyValueQualifier alloc] initWithKey: @"c_name" - operatorSelector: EOQualifierOperatorEqual - value: nameInContainer]; - fetchQualifier = [[EOAndQualifier alloc] - initWithQualifiers: searchQualifier, - [self contentComponentQualifier], - nil]; - [fetchQualifier autorelease]; - [searchQualifier release]; - - ocsFolder = [sogoObject ocsFolder]; - fs = [EOFetchSpecification - fetchSpecificationWithEntityName: [ocsFolder folderName] - qualifier: fetchQualifier - sortOrderings: nil]; - fetchResults = [ocsFolder fetchFields: fields - fetchSpecification: fs - ignoreDeleted: NO]; - - if ([fetchResults count] == 1) - { - result = [fetchResults objectAtIndex: 0]; - cLastModified = [result objectForKey: @"c_lastmodified"]; - cDeleted = [result objectForKey: @"c_deleted"]; - if ([cDeleted isKindOfClass: NSNumberK] && [cDeleted intValue]) - cVersion = [NSNumber numberWithInt: -1]; - else - cVersion = [result objectForKey: @"c_version"]; - - changeNumber = [[self context] getNewChangeNumber]; - changeNumberStr = [NSString stringWithUnsignedLongLong: changeNumber]; - - /* Create new message entry in Messages dict */ - messageEntry = [NSMutableDictionary new]; - [messages setObject: messageEntry forKey: nameInContainer]; - [messageEntry release]; - - /* Store cLastModified, cVersion and the change number */ - [messageEntry setObject: cLastModified forKey: @"c_lastmodified"]; - [messageEntry setObject: cVersion forKey: @"c_version"]; - [messageEntry setObject: changeNumberStr forKey: @"version"]; - - /* Store the change key */ - changeKey = [self getReplicaKeyFromGlobCnt: changeNumber >> 16]; - [self _setChangeKey: changeKey forMessageEntry: messageEntry]; - - /* Store the changeNumber -> cLastModified mapping */ - mapping = [currentProperties objectForKey: @"VersionMapping"]; - if (!mapping) - { - mapping = [NSMutableDictionary new]; - [currentProperties setObject: mapping forKey: @"VersionMapping"]; - [mapping release]; - } - [mapping setObject: cLastModified forKey: changeNumberStr]; - - /* Save the message */ - [versionsMessage save]; - return YES; - } - else - return NO; - } - - /* If message entry exists, then synchroniseCache did its job */ - return YES; -} - -- (void) updateVersionsForMessageWithKey: (NSString *) messageKey - withChangeKey: (NSData *) oldChangeKey - andPredecessorChangeList: (NSData *) pcl -{ - NSMutableDictionary *messages, *messageEntry; - - [self synchroniseCache]; - if (oldChangeKey || pcl) - { - messages = [[versionsMessage properties] objectForKey: @"Messages"]; - messageEntry = [messages objectForKey: messageKey]; - if (!messageEntry) - [NSException raise: @"MAPIStoreIOException" - format: @"no version record found for message '%@'", - messageKey]; - [self _updatePredecessorChangeList: pcl forMessageEntry: messageEntry - withOldChangeKey: oldChangeKey]; - [versionsMessage save]; - } -} - -- (NSNumber *) lastModifiedFromMessageChangeNumber: (NSString *) changeNumber -{ - NSDictionary *mapping; - NSNumber *lastModified; - - mapping = [[versionsMessage properties] objectForKey: @"VersionMapping"]; - lastModified = [mapping objectForKey: changeNumber]; - - return lastModified; -} - -- (NSString *) changeNumberForMessageWithKey: (NSString *) messageKey -{ - NSDictionary *messages; - NSString *changeNumber; - - messages = [[versionsMessage properties] objectForKey: @"Messages"]; - changeNumber = [[messages objectForKey: messageKey] - objectForKey: @"version"]; - - return changeNumber; -} - -- (NSData *) changeKeyForMessageWithKey: (NSString *) messageKey -{ - NSDictionary *messages, *changeKeyDict; - NSString *guid; - NSData *globCnt, *changeKey = nil; - - messages = [[versionsMessage properties] objectForKey: @"Messages"]; - changeKeyDict = [[messages objectForKey: messageKey] - objectForKey: @"ChangeKey"]; - if (changeKeyDict) - { - guid = [changeKeyDict objectForKey: @"GUID"]; - globCnt = [changeKeyDict objectForKey: @"LocalId"]; - changeKey = [NSData dataWithChangeKeyGUID: guid andCnt: globCnt]; - } - - return changeKey; -} - -- (NSData *) predecessorChangeListForMessageWithKey: (NSString *) messageKey -{ - NSMutableData *list = nil; - NSDictionary *messages, *changeListDict; - NSArray *keys; - NSMutableArray *changeKeys; - NSUInteger count, max; - NSData *changeKey; - NSString *guid; - NSData *globCnt; - - messages = [[versionsMessage properties] objectForKey: @"Messages"]; - changeListDict = [[messages objectForKey: messageKey] - objectForKey: @"PredecessorChangeList"]; - if (changeListDict) - { - keys = [changeListDict allKeys]; - max = [keys count]; - - changeKeys = [NSMutableArray arrayWithCapacity: max]; - for (count = 0; count < max; count++) - { - guid = [keys objectAtIndex: count]; - globCnt = [changeListDict objectForKey: guid]; - changeKey = [NSData dataWithChangeKeyGUID: guid andCnt: globCnt]; - [changeKeys addObject: changeKey]; - } - [changeKeys sortUsingFunction: MAPIChangeKeyGUIDCompare - context: nil]; - - list = [NSMutableData data]; - for (count = 0; count < max; count++) - { - changeKey = [changeKeys objectAtIndex: count]; - [list appendUInt8: [changeKey length]]; - [list appendData: changeKey]; - } - } - - return list; -} - -- (NSArray *) getDeletedKeysFromChangeNumber: (uint64_t) changeNum - andCN: (NSNumber **) cnNbr - inTableType: (uint8_t) tableType -{ - NSArray *deletedKeys, *deletedCNames, *records; - NSNumber *lastModified; - NSString *cName, *changeNumber; - NSDictionary *versionProperties, *messageEntry; - NSMutableDictionary *messages; - uint64_t maxChangeNum = changeNum, currentChangeNum; - EOAndQualifier *fetchQualifier; - EOKeyValueQualifier *cDeletedQualifier, *cLastModifiedQualifier; - EOFetchSpecification *fs; - GCSFolder *ocsFolder; - NSUInteger count, max; - - if (tableType == MAPISTORE_MESSAGE_TABLE) - { - deletedKeys = [NSMutableArray array]; - - changeNumber = [NSString stringWithUnsignedLongLong: changeNum]; - lastModified = [self lastModifiedFromMessageChangeNumber: changeNumber]; - if (lastModified) - { - versionProperties = [versionsMessage properties]; - messages = [versionProperties objectForKey: @"Messages"]; - - ocsFolder = [sogoObject ocsFolder]; - cLastModifiedQualifier = [[EOKeyValueQualifier alloc] - initWithKey: @"c_lastmodified" - operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo - value: lastModified]; - cDeletedQualifier = [[EOKeyValueQualifier alloc] - initWithKey: @"c_deleted" - operatorSelector: EOQualifierOperatorEqual - value: [NSNumber numberWithInt: 1]]; - fetchQualifier = [[EOAndQualifier alloc] initWithQualifiers: - cLastModifiedQualifier, - cDeletedQualifier, - nil]; - [fetchQualifier autorelease]; - [cLastModifiedQualifier release]; - [cDeletedQualifier release]; - - fs = [EOFetchSpecification - fetchSpecificationWithEntityName: [ocsFolder folderName] - qualifier: fetchQualifier - sortOrderings: nil]; - records = [ocsFolder - fetchFields: [NSArray arrayWithObject: @"c_name"] - fetchSpecification: fs - ignoreDeleted: NO]; - deletedCNames = [records objectsForKey: @"c_name" notFoundMarker: nil]; - max = [deletedCNames count]; - for (count = 0; count < max; count++) - { - cName = [deletedCNames objectAtIndex: count]; - [sogoObject removeChildRecordWithName: cName]; - messageEntry = [messages objectForKey: cName]; - if (messageEntry) - { - currentChangeNum - = [[messageEntry objectForKey: @"version"] - unsignedLongLongValue]; - if (MAPICNCompare (changeNum, currentChangeNum, NULL) - == NSOrderedAscending) - { - [(NSMutableArray *) deletedKeys addObject: cName]; - if (MAPICNCompare (maxChangeNum, currentChangeNum, NULL) - == NSOrderedAscending) - maxChangeNum = currentChangeNum; - } - } - } - if (maxChangeNum != changeNum) - *cnNbr = [NSNumber numberWithUnsignedLongLong: maxChangeNum]; - } - } - else - deletedKeys = [super getDeletedKeysFromChangeNumber: changeNum - andCN: cnNbr - inTableType: tableType]; - - return deletedKeys; -} - -- (NSArray *) activeUserRoles -{ - SOGoUser *activeUser; - WOContext *woContext; - - if (!activeUserRoles) - { - activeUser = [[self context] activeUser]; - woContext = [[self userContext] woContext]; - activeUserRoles = [activeUser rolesForObject: sogoObject - inContext: woContext]; - activeUserRoles = [self expandRoles: activeUserRoles]; - [activeUserRoles retain]; - } - - return activeUserRoles; -} - -- (BOOL) subscriberCanCreateMessages -{ - return [[self activeUserRoles] containsObject: SOGoRole_ObjectCreator]; -} - -- (BOOL) subscriberCanDeleteMessages -{ - return [[self activeUserRoles] containsObject: SOGoRole_ObjectEraser]; -} - -/* subclasses */ - -- (EOQualifier *) aclQualifier -{ - return nil; -} - -- (NSString *) component -{ - [self subclassResponsibility: _cmd]; - - return nil; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreGCSMessage.h b/Attic/OpenChange/MAPIStoreGCSMessage.h deleted file mode 100644 index 2cfd480d0..000000000 --- a/Attic/OpenChange/MAPIStoreGCSMessage.h +++ /dev/null @@ -1,44 +0,0 @@ -/* MAPIStoreGCSMessage.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTOREGCSMESSAGE_H -#define MAPISTOREGCSMESSAGE_H - -#import - -#import "MAPIStoreMessage.h" - -@interface MAPIStoreGCSMessage : MAPIStoreMessage -{ -} - -/* subclass helpers */ - -/* Return the message original creator */ -- (NSString *) creator; -- (NSString *) owner; -- (SOGoUser *) ownerUser; -- (void) updateVersions; - -@end - -#endif /* MAPISTOREGCSMESSAGE_H */ diff --git a/Attic/OpenChange/MAPIStoreGCSMessage.m b/Attic/OpenChange/MAPIStoreGCSMessage.m deleted file mode 100644 index e1792fbdf..000000000 --- a/Attic/OpenChange/MAPIStoreGCSMessage.m +++ /dev/null @@ -1,264 +0,0 @@ -/* MAPIStoreGCSMessage.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#import "MAPIStoreContext.h" -#import "MAPIStoreGCSFolder.h" -#import "MAPIStoreTypes.h" -#import "MAPIStoreUserContext.h" -#import "NSData+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreGCSMessage.h" - -#undef DEBUG -#include -#include - -@implementation MAPIStoreGCSMessage - -- (NSDate *) creationTime -{ - return [sogoObject creationDate]; -} - -- (NSDate *) lastModificationTime -{ - return [sogoObject lastModified]; -} - -- (enum mapistore_error) getPidTagCreatorName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - NSString *creator; - - creator = [self creator]; - if (creator) - { - *data = [creator asUnicodeInMemCtx: memCtx]; - rc = MAPISTORE_SUCCESS; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidTagChangeKey: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_SUCCESS; - NSData *changeKey; - MAPIStoreGCSFolder *parentFolder; - NSString *nameInContainer; - - if (isNew) - rc = MAPISTORE_ERR_NOT_FOUND; - else - { - parentFolder = (MAPIStoreGCSFolder *)[self container]; - nameInContainer = [self nameInContainer]; - changeKey = [parentFolder changeKeyForMessageWithKey: nameInContainer]; - if (!changeKey) - { - [parentFolder synchroniseCache]; - changeKey = [parentFolder changeKeyForMessageWithKey: nameInContainer]; - } - if (changeKey) - *data = [changeKey asBinaryInMemCtx: memCtx]; - else - { - [self warnWithFormat: @"No change key for %@ in folder %@", - nameInContainer, - [parentFolder url] - ]; - rc = MAPISTORE_ERR_NOT_FOUND; - } - } - - return rc; -} - -- (enum mapistore_error) getPidTagPredecessorChangeList: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_SUCCESS; - NSData *changeList; - MAPIStoreGCSFolder *parentFolder; - - if (isNew) - rc = MAPISTORE_ERR_NOT_FOUND; - else - { - parentFolder = (MAPIStoreGCSFolder *)[self container]; - changeList = [parentFolder - predecessorChangeListForMessageWithKey: [self nameInContainer]]; - if (!changeList) - { - [parentFolder synchroniseCache]; - changeList = [parentFolder - predecessorChangeListForMessageWithKey: [self nameInContainer]]; - } - if (!changeList) - abort (); - *data = [changeList asBinaryInMemCtx: memCtx]; - } - - return rc; -} - -- (uint64_t) objectVersion -{ - uint64_t version = ULLONG_MAX; - NSString *changeNumber; - BOOL synced; - - if (!isNew) - { - changeNumber = [(MAPIStoreGCSFolder *) container - changeNumberForMessageWithKey: [self nameInContainer]]; - if (!changeNumber) - { - [self warnWithFormat: @"attempting to get change number" - @" by synchronising folder..."]; - synced = [(MAPIStoreGCSFolder *) container synchroniseCache]; - if (synced) - { - changeNumber = [(MAPIStoreGCSFolder *) container - changeNumberForMessageWithKey: [self nameInContainer]]; - } - if (!changeNumber) - { - [self warnWithFormat: @"attempting to get change number" - @" by synchronising this specific message..."]; - synced = [(MAPIStoreGCSFolder *) container - synchroniseCacheFor: [self nameInContainer]]; - if (synced) - { - changeNumber = [(MAPIStoreGCSFolder *) container - changeNumberForMessageWithKey: [self nameInContainer]]; - } - if (!changeNumber) - { - [self errorWithFormat: @"still nothing. We crash!"]; - abort(); - } - } - } - version = [changeNumber unsignedLongLongValue] >> 16; - } - - return version; -} - -- (void) updateVersions -{ - /* Update ChangeKey and PredecessorChangeList on message's save */ - NSData *newChangeKey, *predecessorChangeList; - - newChangeKey = [properties objectForKey: MAPIPropertyKey (PR_CHANGE_KEY)]; - predecessorChangeList = [properties objectForKey: MAPIPropertyKey (PR_PREDECESSOR_CHANGE_LIST)]; - - [(MAPIStoreGCSFolder *) container - updateVersionsForMessageWithKey: [self nameInContainer] - withChangeKey: newChangeKey - andPredecessorChangeList: predecessorChangeList]; -} - -//---------------------- -// Sharing -//---------------------- - -- (NSString *) creator -{ - return [self owner]; -} - -- (NSString *) owner -{ - return [sogoObject ownerInContext: nil]; -} - -- (SOGoUser *) ownerUser -{ - NSString *ownerName; - SOGoUser *owner = nil; - - ownerName = [self owner]; - if ([ownerName length] != 0) - owner = [SOGoUser userWithLogin: ownerName]; - - return owner; -} - -- (BOOL) subscriberCanModifyMessage -{ - BOOL rc; - NSArray *roles; - - roles = [self activeUserRoles]; - - if (isNew) - rc = [roles containsObject: SOGoRole_ObjectCreator]; - else - rc = [roles containsObject: SOGoRole_ObjectEditor]; - - /* Check if the message is owned and it has permission to edit it */ - if (!rc && [roles containsObject: MAPIStoreRightEditOwn]) - rc = [[[container context] activeUser] isEqual: [self ownerUser]]; - - return rc; -} - -- (BOOL) subscriberCanDeleteMessage -{ - BOOL rc; - NSArray *roles; - - roles = [self activeUserRoles]; - rc = [roles containsObject: SOGoRole_ObjectEraser]; - - /* Check if the message is owned and it has permission to delete it */ - if (!rc && [roles containsObject: MAPIStoreRightDeleteOwn]) - { - NSString *currentUser; - - currentUser = [[container context] activeUser]; - rc = [currentUser isEqual: [self ownerUser]]; - } - - return rc; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreGCSMessageTable.h b/Attic/OpenChange/MAPIStoreGCSMessageTable.h deleted file mode 100644 index 72190c221..000000000 --- a/Attic/OpenChange/MAPIStoreGCSMessageTable.h +++ /dev/null @@ -1,36 +0,0 @@ -/* MAPIStoreGCSMessageTable.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 MAPISTOREGCSMESSAGETABLE_H -#define MAPISTOREGCSMESSAGETABLE_H - -#import "MAPIStoreMessageTable.h" - -@class EOQualifier; - -@interface MAPIStoreGCSMessageTable : MAPIStoreMessageTable - -- (NSString *) sortIdentifierForProperty: (enum MAPITAGS) property; - -@end - -#endif /* MAPISTOREGCSMESSAGETABLE_H */ diff --git a/Attic/OpenChange/MAPIStoreGCSMessageTable.m b/Attic/OpenChange/MAPIStoreGCSMessageTable.m deleted file mode 100644 index 0dac1fff9..000000000 --- a/Attic/OpenChange/MAPIStoreGCSMessageTable.m +++ /dev/null @@ -1,260 +0,0 @@ -/* MAPIStoreGCSMessageTable.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -#import -#import -#import -#import -#import - -#import -#import - -#import -#import -#import -#import - -#import -#import - -#import "MAPIStoreTypes.h" -#import "MAPIStoreGCSFolder.h" -#import "MAPIStoreGCSMessageTable.h" - -#undef DEBUG -#include - -@implementation MAPIStoreGCSMessageTable - -- (void) cleanupCaches -{ - [(MAPIStoreGCSFolder *) container synchroniseCache]; - [super cleanupCaches]; -} - -- (struct mapi_SPropertyRestriction *) _fixedDatePropertyRestriction: (struct mapi_SPropertyRestriction *) res - inMemCtx: (TALLOC_CTX *) memCtx -{ - struct mapi_SPropertyRestriction *translatedRes; - NSCalendarDate *dateValue; - int32_t longDate; - - translatedRes = talloc (memCtx, struct mapi_SPropertyRestriction); - translatedRes->ulPropTag = (res->ulPropTag & 0xffff0000) | PT_LONG; - translatedRes->relop = res->relop; - dateValue = NSObjectFromMAPISPropValue (&res->lpProp); - longDate = (int32_t) [dateValue timeIntervalSince1970]; - translatedRes->lpProp.ulPropTag = translatedRes->ulPropTag; - translatedRes->lpProp.value.l = longDate; - - return translatedRes; -} - -- (MAPIRestrictionState) evaluatePropertyRestriction: (struct mapi_SPropertyRestriction *) res - intoQualifier: (EOQualifier **) qualifier -{ - static SEL operators[] = { EOQualifierOperatorLessThan, - EOQualifierOperatorLessThanOrEqualTo, - EOQualifierOperatorGreaterThan, - EOQualifierOperatorGreaterThanOrEqualTo, - EOQualifierOperatorEqual, - EOQualifierOperatorNotEqual, - EOQualifierOperatorContains }; - SEL operator; - id value; - NSString *property; - NSNumber *lastModified; - MAPIRestrictionState rc; - TALLOC_CTX *memCtx = NULL; - - if (res->ulPropTag == PidTagChangeNumber) - { - NSString *changeNumber; - - value = NSObjectFromMAPISPropValue (&res->lpProp); - changeNumber = [NSString stringWithUnsignedLongLong: [(NSNumber *)value unsignedLongLongValue]]; - lastModified = [(MAPIStoreGCSFolder *) - container lastModifiedFromMessageChangeNumber: changeNumber]; - //[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]]; - //[self logWithFormat: @" c_lastmodified: %@", lastModified]; - if (lastModified) - { - SEL operator; - - operator = [self operatorFromRestrictionOperator: res->relop]; - *qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"c_lastmodified" - operatorSelector: operator - value: lastModified]; - [*qualifier autorelease]; - rc = MAPIRestrictionStateNeedsEval; - } - else - { - [self logWithFormat: @"No last modified found for: 0x%.16"PRIx64". Then no restriction applied", - [value unsignedLongLongValue]]; - rc = MAPIRestrictionStateAlwaysTrue; - } - } - else - { - property = [self backendIdentifierForProperty: res->ulPropTag]; - if (property) - { - if (res->relop < 7) - operator = operators[res->relop]; - else - { - operator = NULL; - [NSException raise: @"MAPIStoreRestrictionException" - format: @"unhandled operator type number %d", res->relop]; - } - - if ((res->ulPropTag & 0xffff) == PT_SYSTIME) - { - memCtx = talloc_zero (NULL, TALLOC_CTX); - res = [self _fixedDatePropertyRestriction: res - inMemCtx: memCtx]; - } - - value = NSObjectFromMAPISPropValue (&res->lpProp); - if ((res->ulPropTag & 0xffff) == PT_UNICODE) - { - property = [NSString stringWithFormat: @"UPPER(%@)", property]; - value = [value uppercaseString]; - } - - *qualifier = [[EOKeyValueQualifier alloc] initWithKey: property - operatorSelector: operator - value: value]; - [*qualifier autorelease]; - if (memCtx) - talloc_free (memCtx); - - rc = MAPIRestrictionStateNeedsEval; - } - else - { - [self warnUnhandledProperty: res->ulPropTag - inFunction: __FUNCTION__]; - rc = MAPIRestrictionStateAlwaysFalse; - } - } - - return rc; -} - -/* sorting */ - -- (EOSortOrdering *) _sortOrderingFromSortOrder: (struct SSortOrder *) sortOrder -{ - EOSortOrdering *newSortOrdering = nil; - NSString *sortIdentifier; - SEL orderSelector = NULL; - const char *propName; - - sortIdentifier = [self sortIdentifierForProperty: sortOrder->ulPropTag]; - if (sortIdentifier) - { - if ((sortOrder->ulPropTag & 0xffff) == PT_UNICODE - || (sortOrder->ulPropTag & 0xffff) == PT_STRING8) - { - if (sortOrder->ulOrder == TABLE_SORT_ASCEND) - orderSelector = EOCompareCaseInsensitiveAscending; - else if (sortOrder->ulOrder == TABLE_SORT_DESCEND) - orderSelector = EOCompareCaseInsensitiveDescending; - else if (sortOrder->ulOrder == TABLE_SORT_MAXIMUM_CATEGORY) - { - orderSelector = EOCompareCaseInsensitiveAscending; - [self errorWithFormat: - @"TABLE_SORT_MAXIMUM_CATEGORY is not handled"]; - } - } - else - { - if (sortOrder->ulOrder == TABLE_SORT_ASCEND) - orderSelector = EOCompareAscending; - else if (sortOrder->ulOrder == TABLE_SORT_DESCEND) - orderSelector = EOCompareDescending; - else if (sortOrder->ulOrder == TABLE_SORT_MAXIMUM_CATEGORY) - { - orderSelector = EOCompareAscending; - [self errorWithFormat: - @"TABLE_SORT_MAXIMUM_CATEGORY is not handled"]; - } - } - if (orderSelector) - newSortOrdering = [EOSortOrdering sortOrderingWithKey: sortIdentifier - selector: orderSelector]; - } - else - { - propName = get_proptag_name (sortOrder->ulPropTag); - if (!propName) - propName = ""; - [self errorWithFormat: - @"sort unhandled for property: %s (0x%.8x)", - propName, sortOrder->ulPropTag]; - } - - return newSortOrdering; -} - -- (void) setSortOrder: (const struct SSortOrderSet *) set -{ - NSMutableArray *newSortOrderings; - EOSortOrdering *sortOrdering; - uint16_t count; - - if (set) - { - newSortOrderings = [NSMutableArray arrayWithCapacity: set->cSorts]; - - /* TODO: */ - if (set->cCategories > 0) - [self errorWithFormat: @"we don't handle sort categories yet"]; - - for (count = 0; count < set->cSorts; count++) - { - sortOrdering = [self _sortOrderingFromSortOrder: set->aSort + count]; - if (sortOrdering) - [newSortOrderings addObject: sortOrdering]; - } - } - else - newSortOrderings = nil; - - ASSIGN (sortOrderings, newSortOrderings); - [self cleanupCaches]; - - [self logWithFormat: @"new sort orderings: %@", sortOrderings]; -} - -/* subclasses */ -- (NSString *) sortIdentifierForProperty: (enum MAPITAGS) property -{ - [self subclassResponsibility: _cmd]; - - return nil; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreMIME.h b/Attic/OpenChange/MAPIStoreMIME.h deleted file mode 100644 index eb2d2a6b2..000000000 --- a/Attic/OpenChange/MAPIStoreMIME.h +++ /dev/null @@ -1,37 +0,0 @@ -/* MAPIStoreMIME.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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 MAPISTOREMIME_H -#define MAPISTOREMIME_H - -@interface MAPIStoreMIME : NSObject -{ - NSMutableDictionary *mimeDict; -} - -+ (id) sharedMAPIStoreMIME; - -- (NSString *) mimeTypeForExtension: (NSString *) extension; - -@end - -#endif /* MAPISTOREMIME_H */ diff --git a/Attic/OpenChange/MAPIStoreMIME.m b/Attic/OpenChange/MAPIStoreMIME.m deleted file mode 100644 index 712cc88bc..000000000 --- a/Attic/OpenChange/MAPIStoreMIME.m +++ /dev/null @@ -1,154 +0,0 @@ -/* MAPIStoreMIME.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import -#import -#import -#import - -#import "MAPIStoreMIME.h" - -/* Seems common to all distros ? */ -#define MAPIStoreMIMEFile @"/etc/mime.types" - -@implementation MAPIStoreMIME - -+ (id) sharedMAPIStoreMIME -{ - static MAPIStoreMIME *sharedInstance = nil; - - if (!sharedInstance) - sharedInstance = [self new]; - - return sharedInstance; -} - -- (void) _parseLine: (const char *) line - withLength: (NSUInteger) length -{ - NSUInteger count = 0, lastWord = 0; - NSString *mimeType = nil, *word; - NSData *wordData; - BOOL comment = NO; - - while (count < length && !comment) - { - while (count < length - && (line[count] == ' ' || line[count] == '\t')) - count++; - lastWord = count; - while (count < length - && line[count] != ' ' && line[count] != '\t' - && !comment) - { - if (line[count] == '#') - comment = YES; - else - count++; - } - if (count > lastWord) - { - wordData = [NSData dataWithBytes: line + lastWord - length: count - lastWord]; - word = [[NSString alloc] initWithData: wordData - encoding: NSASCIIStringEncoding]; - if (word) - { - if (mimeType) - { - [mimeDict setObject: mimeType forKey: word]; - [word release]; - } - else - mimeType = word; - } - } - } - - [mimeType release]; -} - -- (void) _parseContent: (NSData *) content -{ - const char *data; - NSUInteger lineStart = 0, bytesRead = 0, max; - - data = [content bytes]; - max = [content length]; - bytesRead = 0; - lineStart = 0; - - while (bytesRead < max) - { - if (data[bytesRead] == '\n') - { - [self _parseLine: data + lineStart withLength: bytesRead - lineStart]; - lineStart = bytesRead + 1; - } - else if (data[bytesRead] == '\r') - { - [self _parseLine: data + lineStart withLength: bytesRead - lineStart]; - if (bytesRead < (max - 1) && data[bytesRead] == '\n') - lineStart = bytesRead + 2; - else - lineStart = bytesRead + 1; - } - bytesRead++; - } - - if (bytesRead > (lineStart + 1)) - [self _parseLine: data + lineStart withLength: bytesRead - lineStart]; -} - -- (void) _readMIMEFile -{ - NSFileHandle *inH; - NSData *content; - - inH = [NSFileHandle fileHandleForReadingAtPath: MAPIStoreMIMEFile]; - content = [inH readDataToEndOfFile]; - [self _parseContent: content]; -} - -- (id) init -{ - if ((self = [super init])) - { - mimeDict = [NSMutableDictionary new]; - [self _readMIMEFile]; - } - - return self; -} - -- (void) dealloc -{ - [mimeDict release]; - [super dealloc]; -} - -- (NSString *) mimeTypeForExtension: (NSString *) extension -{ - return [mimeDict objectForKey: [extension lowercaseString]]; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreMailAttachment.h b/Attic/OpenChange/MAPIStoreMailAttachment.h deleted file mode 100644 index b04b197ab..000000000 --- a/Attic/OpenChange/MAPIStoreMailAttachment.h +++ /dev/null @@ -1,41 +0,0 @@ -/* MAPIStoreMailAttachment.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTOREMAILATTACHMENT_H -#define MAPISTOREMAILATTACHMENT_H - -#import "MAPIStoreAttachment.h" - -@class NSDictionary; - -@interface MAPIStoreMailAttachment : MAPIStoreAttachment -{ - NSDictionary *bodyInfo; - SOGoMailBodyPart *bodyPart; -} - -- (void) setBodyInfo: (NSDictionary *) newBodyInfo; -- (void) setBodyPart: (SOGoMailBodyPart *) newBodyPart; - -@end - -#endif /* MAPISTOREMAILATTACHMENT_H */ diff --git a/Attic/OpenChange/MAPIStoreMailAttachment.m b/Attic/OpenChange/MAPIStoreMailAttachment.m deleted file mode 100644 index 17520202b..000000000 --- a/Attic/OpenChange/MAPIStoreMailAttachment.m +++ /dev/null @@ -1,204 +0,0 @@ -/* MAPIStoreMailAttachment.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#import "MAPIStoreTypes.h" -#import "MAPIStoreMailMessage.h" -#import "NSData+MAPIStore.h" -#import "NSDate+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreMailAttachment.h" - -#undef DEBUG -#include -#include -#include -#include - -@implementation MAPIStoreMailAttachment - -- (id) init -{ - if ((self = [super init])) - { - bodyInfo = nil; - bodyPart = nil; - } - - return self; -} - -- (void) dealloc -{ - [bodyInfo release]; - [bodyPart release]; - [super dealloc]; -} - -- (void) setBodyInfo: (NSDictionary *) newBodyInfo -{ - ASSIGN (bodyInfo, newBodyInfo); -} - -- (void) setBodyPart: (SOGoMailBodyPart *) newBodyPart -{ - ASSIGN (bodyPart, newBodyPart); -} - -- (enum mapistore_error) getPidTagAttachMethod: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, 0x00000001); // afByValue - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAttachTag: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [[self mimeAttachTag] asBinaryInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAttachSize: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - uint32_t longValue; - - longValue = [[bodyInfo objectForKey: @"size"] longValue]; - *data = MAPILongValue (memCtx, longValue); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagRecordKey: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - static char recordBytes[] = {0xd9, 0xd8, 0x11, 0xa3, 0xe2, 0x90, 0x18, 0x41, - 0x9e, 0x04, 0x58, 0x46, 0x9d, 0x6d, 0x1b, - 0x68}; - - *data = [[NSData dataWithBytes: recordBytes length: 16] - asBinaryInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (NSString *) _fileName -{ - return [bodyInfo filename]; -} - -- (enum mapistore_error) getPidTagAttachLongFilename: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [[self _fileName] asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAttachFilename: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *fileName, *baseName, *ext; - - fileName = [self _fileName]; - baseName = [fileName stringByDeletingPathExtension]; - if ([baseName length] > 8) - baseName = [baseName substringToIndex: 8]; - - ext = [fileName pathExtension]; - if ([ext length] > 3) - ext = [ext substringToIndex: 3]; - fileName = [NSString stringWithFormat: @"%@.%@", baseName, ext]; - - *data = [fileName asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagDisplayName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *fileName; - - fileName = [self _fileName]; - if ([fileName isEqualToString: @"sharing_metadata.xml"]) - /* Required to disallow user from seeing the attachment by default */ - *data = [@"sharing_metadata.xml" asUnicodeInMemCtx: memCtx]; - else - *data = [[bodyInfo objectForKey: @"description"] - asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAttachContentId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [[bodyInfo objectForKey: @"bodyId"] - asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAttachMimeTag: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *mimeTag, *fileName; - - fileName = [self _fileName]; - if ([fileName isEqualToString: @"sharing_metadata.xml"]) - /* Required by [MS-OXWSMSHR] Section 3.1.1 */ - mimeTag = [NSString stringWithFormat: @"application/x-sharing-metadata-xml"]; - else - mimeTag = [NSString stringWithFormat: @"%@/%@", - [bodyInfo objectForKey: @"type"], - [bodyInfo objectForKey: @"subtype"]]; - - *data = [[mimeTag lowercaseString] asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAttachDataBinary: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [[bodyPart fetchBLOBWithPeek: YES] asBinaryInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreMailContext.h b/Attic/OpenChange/MAPIStoreMailContext.h deleted file mode 100644 index 9e8371714..000000000 --- a/Attic/OpenChange/MAPIStoreMailContext.h +++ /dev/null @@ -1,37 +0,0 @@ -/* MAPIStoreMailContext.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 MAPISTOREMAILCONTEXT_H -#define MAPISTOREMAILCONTEXT_H - -#import "MAPIStoreContext.h" - -@interface MAPIStoreMailContext : MAPIStoreContext - -- (void) updateURLWithFolderName: (NSString *) newFolderName; - -@end - -@interface MAPIStoreOutboxContext : MAPIStoreMailContext -@end - -#endif /* MAPISTOREMAILCONTEXT_H */ diff --git a/Attic/OpenChange/MAPIStoreMailContext.m b/Attic/OpenChange/MAPIStoreMailContext.m deleted file mode 100644 index c1f39565f..000000000 --- a/Attic/OpenChange/MAPIStoreMailContext.m +++ /dev/null @@ -1,312 +0,0 @@ -/* MAPIStoreMailContext.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -#import -#import -#import -#import -#import -#import -#import -#import - -#import "MAPIStoreMailFolder.h" -#import "MAPIStoreUserContext.h" -#import "NSString+MAPIStore.h" - -#import -#import "MAPIApplication.h" -#import "MAPIStoreMailContext.h" - -#include -#undef DEBUG -#include - -static Class MAPIStoreMailFolderK, MAPIStoreOutboxFolderK; - -@implementation MAPIStoreMailContext - -+ (void) initialize -{ - MAPIStoreMailFolderK = [MAPIStoreMailFolder class]; - MAPIStoreOutboxFolderK = [MAPIStoreOutboxFolder class]; -} - -+ (NSString *) MAPIModuleName -{ - return @"mail"; -} - -+ (enum mapistore_context_role) MAPIContextRole -{ - return MAPISTORE_MAIL_ROLE; -} - -static inline NSString * -MakeDisplayFolderName (NSString *folderName) -{ - NSArray *parts; - NSString *lastFolder; - NSUInteger max; - - parts = [folderName componentsSeparatedByString: @"/"]; - max = [parts count]; - if (max > 1) - { - lastFolder = [parts objectAtIndex: max - 1]; - if ([lastFolder length] == 0) - lastFolder = [parts objectAtIndex: max - 2]; - } - else - lastFolder = folderName; - - return [[lastFolder substringFromIndex: 6] fromCSSIdentifier]; -} - -+ (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName - withIndexing: (struct indexing_context *) indexing - inMemCtx: (TALLOC_CTX *) memCtx -{ - struct mapistore_contexts_list *firstContext = NULL, *context; - NSString *urlBase, *stringData, *currentName, *realName, *inboxName, *draftsName, *sentName, *trashName; - NSArray *unprefixedFolders; - NSMutableArray *secondaryFolders; - enum mapistore_context_role role[] = {MAPISTORE_MAIL_ROLE, - MAPISTORE_DRAFTS_ROLE, - MAPISTORE_SENTITEMS_ROLE}; - NSString *folderName[3]; - NSUInteger count, max; - SOGoMailAccount *accountFolder; - MAPIStoreUserContext *userContext; - WOContext *woContext; - - userContext = [MAPIStoreUserContext userContextWithUsername: userName - andTDBIndexing: indexing]; - accountFolder = [[userContext rootFolders] objectForKey: @"mail"]; - woContext = [userContext woContext]; - - inboxName = @"folderINBOX"; - folderName[0] = inboxName; - - unprefixedFolders = [[accountFolder draftsFolderNameInContext: woContext] - componentsSeparatedByString: @"/"]; - draftsName = [NSString stringWithFormat: @"folder%@", - [unprefixedFolders componentsJoinedByString: @"/folder"]]; - folderName[1] = draftsName; - - unprefixedFolders = [[accountFolder sentFolderNameInContext: woContext] - componentsSeparatedByString: @"/"]; - sentName = [NSString stringWithFormat: @"folder%@", - [unprefixedFolders componentsJoinedByString: @"/folder"]]; - folderName[2] = sentName; - - /* Note: trash is not used as a mail folder, since "Deleted Items" makes use of - the fallback context */ - unprefixedFolders = [[accountFolder trashFolderNameInContext: woContext] - componentsSeparatedByString: @"/"]; - trashName = [NSString stringWithFormat: @"folder%@", - [unprefixedFolders componentsJoinedByString: @"/folder"]]; - - urlBase = [NSString stringWithFormat: @"sogo://%@:%@@mail/", - [userName stringByReplacingOccurrencesOfString: @"@" - withString: @"%40"], - [userName stringByReplacingOccurrencesOfString: @"@" - withString: @"%40"]]; - for (count = 0; count < 3; count++) - { - context = talloc_zero (memCtx, struct mapistore_contexts_list); - stringData = [NSString stringWithFormat: @"%@%@", urlBase, - [folderName[count] stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]]; - context->url = [stringData asUnicodeInMemCtx: context]; - /* remove "folder" prefix */ - stringData = MakeDisplayFolderName (folderName[count]); - context->name = [stringData asUnicodeInMemCtx: context]; - context->main_folder = true; - context->role = role[count]; - context->tag = "tag"; - DLIST_ADD_END (firstContext, context, void); - } - - /* FIXME: Flush any cache before retrieving the hierarchy */ - [accountFolder flushMailCaches]; - - secondaryFolders = [[accountFolder toManyRelationshipKeysWithNamespaces: NO] - mutableCopy]; - [secondaryFolders autorelease]; - [secondaryFolders removeObject: inboxName]; - [secondaryFolders removeObject: draftsName]; - [secondaryFolders removeObject: sentName]; - [secondaryFolders removeObject: trashName]; - max = [secondaryFolders count]; - for (count = 0; count < max; count++) - { - context = talloc_zero (memCtx, struct mapistore_contexts_list); - // secondaryFolders has the names (1) Imap4Encoded ,(2) asCSSIdentifier and (3) "folder"-prefixed - // e.g.: folderProbl&AOg-mes_SP_de_SP_synchronisation - currentName = [secondaryFolders objectAtIndex: count]; - // To get the real name we have to revert that (applying the decode functions - // in reverse order) - // e.g.: Problèmes de synchronisation - realName = [[[currentName substringFromIndex: 6] - fromCSSIdentifier] - stringByDecodingImap4FolderName]; - // And finally to represent that as URI we have to (1) asCSSIdentifier, - // (2) Imap4Encode (3) AddPercentEscapes and (4) add the "folder" prefix - // e.g.: folderProbl&AOg-mes_SP_de_SP_synchronisation - // In the example there are no percent escapes added because is already ok - stringData = [[[realName asCSSIdentifier] - stringByEncodingImap4FolderName] - stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]; - stringData = [NSString stringWithFormat: @"folder%@", stringData]; - context->url = [[NSString stringWithFormat: @"%@%@", urlBase, stringData] asUnicodeInMemCtx: context]; - context->name = [realName asUnicodeInMemCtx: context]; - context->main_folder = false; - context->role = MAPISTORE_MAIL_ROLE; - context->tag = "tag"; - DLIST_ADD_END (firstContext, context, void); - } - - return firstContext; -} - -+ (NSString *) - createRootSecondaryFolderWithFID: (uint64_t) fid - andName: (NSString *) newFolderName - forUser: (NSString *) userName -{ - NSString *mapistoreURI, *folderName; - MAPIStoreUserContext *userContext; - SOGoMailAccount *accountFolder; - SOGoMailFolder *newFolder; - - userContext = [MAPIStoreUserContext userContextWithUsername: userName - andTDBIndexing: NULL]; - accountFolder = [[userContext rootFolders] objectForKey: @"mail"]; - folderName = [NSString stringWithFormat: @"folder%@", - [[newFolderName stringByEncodingImap4FolderName] asCSSIdentifier]]; - newFolder = [SOGoMailFolder objectWithName: folderName - inContainer: accountFolder]; - if ([newFolder create]) - mapistoreURI = [NSString stringWithFormat: @"sogo://%@:%@@mail/%@/", - [userName stringByReplacingOccurrencesOfString: @"@" - withString: @"%40"], - [userName stringByReplacingOccurrencesOfString: @"@" - withString: @"%40"], - [folderName stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]]; - else - mapistoreURI = nil; - - return mapistoreURI; -} - -- (Class) MAPIStoreFolderClass -{ - return MAPIStoreMailFolderK; -} - -- (id) rootSOGoFolder -{ - return [[userContext rootFolders] objectForKey: @"mail"]; -} - -- (void) updateURLWithFolderName: (NSString *) newFolderName -{ - NSString *urlString, *escapedName; - NSMutableArray *pathComponents; - BOOL hasSlash; - NSUInteger max, folderNameIdx; - NSURL *newURL; - - /* we do not need to unescape the url here as it will be reassembled later - in the method */ - urlString = [contextUrl absoluteString]; - hasSlash = [urlString hasSuffix: @"/"]; - pathComponents = [[urlString componentsSeparatedByString: @"/"] - mutableCopy]; - [pathComponents autorelease]; - max = [pathComponents count]; - if (hasSlash) - folderNameIdx = max - 2; - else - folderNameIdx = max - 1; - escapedName = [newFolderName stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]; - [pathComponents replaceObjectAtIndex: folderNameIdx - withObject: escapedName]; - urlString = [pathComponents componentsJoinedByString: @"/"]; - newURL = [NSURL URLWithString: urlString]; - ASSIGN (contextUrl, newURL); -} - -@end - -@implementation MAPIStoreOutboxContext - -+ (NSString *) MAPIModuleName -{ - return @"outbox"; -} - -+ (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName - withIndexing: (struct indexing_context *) indexing - inMemCtx: (TALLOC_CTX *) memCtx -{ - struct mapistore_contexts_list *context; - NSString *url, *folderName; - NSArray *unprefixedFolders; - SOGoMailAccount *accountFolder; - MAPIStoreUserContext *userContext; - WOContext *woContext; - - userContext = [MAPIStoreUserContext userContextWithUsername: userName - andTDBIndexing: indexing]; - accountFolder = [[userContext rootFolders] objectForKey: @"mail"]; - woContext = [userContext woContext]; - - unprefixedFolders = [[accountFolder draftsFolderNameInContext: woContext] - componentsSeparatedByString: @"/"]; - folderName = [NSString stringWithFormat: @"folder%@", - [unprefixedFolders componentsJoinedByString: @"/folder"]]; - url = [NSString stringWithFormat: @"sogo://%@:%@@outbox/%@", - [userName stringByReplacingOccurrencesOfString: @"@" - withString: @"%40"], - [userName stringByReplacingOccurrencesOfString: @"@" - withString: @"%40"], - folderName]; - - context = talloc_zero (memCtx, struct mapistore_contexts_list); - context->url = [url asUnicodeInMemCtx: context]; - /* TODO: use a localized version of this display name */ - context->name = [@"Outbox" asUnicodeInMemCtx: context]; - context->main_folder = true; - context->role = MAPISTORE_OUTBOX_ROLE; - context->tag = "tag"; - context->prev = context; - - return context; -} - -- (Class) MAPIStoreFolderClass -{ - return MAPIStoreOutboxFolderK; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreMailFolder.h b/Attic/OpenChange/MAPIStoreMailFolder.h deleted file mode 100644 index 717868efb..000000000 --- a/Attic/OpenChange/MAPIStoreMailFolder.h +++ /dev/null @@ -1,72 +0,0 @@ -/* MAPIStoreMailFolder.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTOREMAILFOLDER_H -#define MAPISTOREMAILFOLDER_H - -#import "MAPIStoreFolder.h" - -@class NSNumber; - -@class WOContext; - -@class SOGoMailAccount; -@class SOGoMailFolder; - -@class MAPIStoreMailMessageTable; - -@interface MAPIStoreMailFolder : MAPIStoreFolder -{ - SOGoMAPIDBMessage *versionsMessage; - NSMutableDictionary *bodyData; -} - -- (BOOL) ensureFolderExists; - -/* synchronisation & versioning */ -- (BOOL) synchroniseCache; -- (void) synchronizeUpdatedFolder: (NSNumber *) lastModseq - withMapping: (NSMutableDictionary *) mapping; -- (BOOL) synchroniseCacheForUID: (NSString *) messageUID; -- (NSNumber *) modseqFromMessageChangeNumber: (NSString *) changeNum; -- (NSString *) messageUIDFromMessageKey: (NSString *) messageKey; -- (NSString *) changeNumberForMessageUID: (NSString *) messageUid; -- (void) setChangeKey: (NSData *) changeKey - forMessageWithKey: (NSString *) messageKey; -- (BOOL) updatePredecessorChangeListWith: (NSData *) changeKey - forMessageWithKey: (NSString *) messageKey; -- (NSData *) changeKeyForMessageWithKey: (NSString *) messageKey; -- (NSData *) predecessorChangeListForMessageWithKey: (NSString *) messageKey; - -/* Extra properties from mail messages that already hit the server */ -- (void) setExtraProperties: (NSDictionary *) props - forMessage: (NSString *) messageKey; -- (NSDictionary *) extraPropertiesForMessage: (NSString *) messageKey; - -@end - -/* MAPIStoreOutboxFolder is a special subclass of MAPIStoreMailFolder where - the displayname is always "Outbox" and can not be changed. */ -@interface MAPIStoreOutboxFolder : MAPIStoreMailFolder -@end - -#endif /* MAPISTOREMAILFOLDER_H */ diff --git a/Attic/OpenChange/MAPIStoreMailFolder.m b/Attic/OpenChange/MAPIStoreMailFolder.m deleted file mode 100644 index ee2ff7d61..000000000 --- a/Attic/OpenChange/MAPIStoreMailFolder.m +++ /dev/null @@ -1,1777 +0,0 @@ -/* MAPIStoreMailFolder.m - this file is part of SOGo - * - * Copyright (C) 2011-2013 Inverse inc - * - * 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 - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#import "MAPIApplication.h" -#import "MAPIStoreAppointmentWrapper.h" -#import "MAPIStoreContext.h" -#import "MAPIStoreFAIMessage.h" -#import "MAPIStoreMailContext.h" -#import "MAPIStoreMailMessage.h" -#import "MAPIStoreMailFolderTable.h" -#import "MAPIStoreMailMessageTable.h" -#import "MAPIStoreMapping.h" -#import "MAPIStoreTypes.h" -#import "MAPIStoreUserContext.h" -#import "NSData+MAPIStore.h" -#import "NSString+MAPIStore.h" -#import "SOGoMAPIDBMessage.h" -#import - -#import "MAPIStoreMailVolatileMessage.h" - -#import "MAPIStoreMailFolder.h" - -static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK; - -#include - -#undef DEBUG -#include -#include -#include -#include -#include -#include - -@implementation MAPIStoreMailFolder - -+ (void) initialize -{ - SOGoMailFolderK = [SOGoMailFolder class]; - MAPIStoreMailFolderK = [MAPIStoreMailFolder class]; - MAPIStoreOutboxFolderK = [MAPIStoreOutboxFolder class]; - [MAPIStoreAppointmentWrapper class]; -} - -- (id) init -{ - if ((self = [super init])) - { - versionsMessage = nil; - bodyData = [NSMutableDictionary new]; - } - - return self; -} - -- (void) dealloc -{ - [versionsMessage release]; - [bodyData release]; - [super dealloc]; -} - -- (void) setupVersionsMessage -{ - ASSIGN (versionsMessage, - [SOGoMAPIDBMessage objectWithName: @"versions.plist" - inContainer: dbFolder]); - [versionsMessage setObjectType: MAPIInternalCacheObject]; - [versionsMessage reloadIfNeeded]; -} - -- (BOOL) ensureFolderExists -{ - return [(SOGoMailFolder *) sogoObject exists] || [sogoObject create]; -} - -- (void) addProperties: (NSDictionary *) newProperties -{ - NSString *newDisplayName, *newNameInContainer; - NSMutableDictionary *propsCopy; - NSNumber *key; - uint64_t fid; - - key = MAPIPropertyKey (PR_DISPLAY_NAME_UNICODE); - newDisplayName = [newProperties objectForKey: key]; - if (newDisplayName - && ![self isKindOfClass: MAPIStoreOutboxFolderK] - && ![[(SOGoMailFolder *) sogoObject displayName] - isEqualToString: newDisplayName]) - { - fid = [self objectId]; - [(SOGoMailFolder *) sogoObject renameTo: newDisplayName]; - newNameInContainer = [sogoObject nameInContainer]; - if (!container) - [(MAPIStoreMailContext *) context - updateURLWithFolderName: newNameInContainer]; - [[self mapping] updateID: fid withURL: [self url]]; - [dbFolder setNameInContainer: newNameInContainer]; - [self cleanupCaches]; - - propsCopy = [newProperties mutableCopy]; - [propsCopy removeObjectForKey: key]; - [propsCopy autorelease]; - newProperties = propsCopy; - } - - [super addProperties: newProperties]; -} - -- (MAPIStoreMessageTable *) messageTable -{ - [self synchroniseCache]; - return [MAPIStoreMailMessageTable tableForContainer: self]; -} - -- (MAPIStoreFolderTable *) folderTable -{ - return [MAPIStoreMailFolderTable tableForContainer: self]; -} - -- (enum mapistore_error) createFolder: (struct SRow *) aRow - withFID: (uint64_t) newFID - andKey: (NSString **) newKeyP -{ - enum mapistore_error rc; - NSString *folderName, *nameInContainer; - SOGoMailFolder *newFolder; - int i; - - nameInContainer = nil; - rc = MAPISTORE_ERROR; - - folderName = nil; - for (i = 0; !folderName && i < aRow->cValues; i++) - { - if (aRow->lpProps[i].ulPropTag == PR_DISPLAY_NAME_UNICODE) - folderName = [NSString stringWithUTF8String: aRow->lpProps[i].value.lpszW]; - else if (aRow->lpProps[i].ulPropTag == PR_DISPLAY_NAME) - folderName = [NSString stringWithUTF8String: (const char *) aRow->lpProps[i].value.lpszA]; - } - - if (folderName) - { - nameInContainer = [NSString stringWithFormat: @"folder%@", - [[folderName stringByEncodingImap4FolderName] asCSSIdentifier]]; - - [[self userContext] activate]; - - newFolder = [SOGoMailFolderK objectWithName: nameInContainer - inContainer: sogoObject]; - if ([newFolder create]) - { - *newKeyP = nameInContainer; - rc = MAPISTORE_SUCCESS; - } - else if ([newFolder exists]) - rc = MAPISTORE_ERR_EXIST; - else - rc = MAPISTORE_ERR_DENIED; - } - - return rc; -} - -- (enum mapistore_error) deleteFolder -{ - enum mapistore_error rc; - NSException *error; - NSString *name; - - name = [self nameInContainer]; - if ([name isEqualToString: @"folderINBOX"]) - rc = MAPISTORE_ERR_DENIED; - else - { - error = [(SOGoMailFolder *) sogoObject delete]; - if (error) - rc = MAPISTORE_ERROR; - else - { - if (![versionsMessage delete]) - rc = MAPISTORE_SUCCESS; - else - rc = MAPISTORE_ERROR; - } - } - - return (rc == MAPISTORE_SUCCESS) ? [super deleteFolder] : rc; -} - -- (enum mapistore_error) getPidTagContentUnreadCount: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - EOQualifier *searchQualifier; - uint32_t longValue; - - searchQualifier - = [EOQualifier qualifierWithQualifierFormat: @"flags = %@", @"unseen"]; - longValue = [[sogoObject fetchUIDsMatchingQualifier: searchQualifier - sortOrdering: nil] - count]; - *data = MAPILongValue (memCtx, longValue); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagContainerClass: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [@"IPF.Note" asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (EOQualifier *) simplifyQualifier: (EOQualifier *) qualifier -{ - /* Hack: Reduce the number of MODSEQ constraints to a single one as - we assume the difference among MODSEQs will be small enough to - return a small number of UIDs. - - This is the only case we do simplify: - MODSEQ >= x | MODSEQ >= y | MODSEQ >= z => MODSEQ >= min(x,y,z) - */ - if (qualifier && [qualifier isKindOfClass: [EOOrQualifier class]]) - { - EOQualifier *simplifiedQualifier; - NSArray *quals; - NSNumber *minModseq; - NSUInteger i, count; - - quals = [(EOOrQualifier *)qualifier qualifiers]; - count = [quals count]; - if (count < 2) - return qualifier; - - minModseq = [NSNumber numberWithUnsignedLongLong: ULLONG_MAX]; - - for (i = 0; i < count; i++) - { - EOQualifier *subQualifier; - - subQualifier = [quals objectAtIndex: i]; - if ([subQualifier isKindOfClass: [EOAndQualifier class]] - && [[(EOAndQualifier *)subQualifier qualifiers] count] == 1) - subQualifier = [[(EOAndQualifier *)subQualifier qualifiers] objectAtIndex: 0]; - - if ([subQualifier isKindOfClass: [EOKeyValueQualifier class]] - && [[(EOKeyValueQualifier *)subQualifier key] isEqualToString: @"MODSEQ"]) - { - NSNumber *value; - - value = (NSNumber *)[(EOKeyValueQualifier *)subQualifier value]; - if ([minModseq compare: value] == NSOrderedDescending - && [value unsignedLongLongValue] > 0) - minModseq = (NSNumber *)[(EOKeyValueQualifier *)subQualifier value]; - - } - else - return qualifier; - } - - if ([minModseq unsignedLongLongValue] > 0 && [minModseq unsignedLongLongValue] < ULLONG_MAX) - { - simplifiedQualifier = [[EOKeyValueQualifier alloc] - initWithKey: @"MODSEQ" - operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo - value: minModseq]; - [simplifiedQualifier autorelease]; - return simplifiedQualifier; - } - } - - return qualifier; -} - -- (EOQualifier *) nonDeletedQualifier -{ - static EOQualifier *nonDeletedQualifier = nil; - EOQualifier *deletedQualifier; - - if (!nonDeletedQualifier) - { - deletedQualifier - = [[EOKeyValueQualifier alloc] - initWithKey: @"FLAGS" - operatorSelector: EOQualifierOperatorContains - value: [NSArray arrayWithObject: @"Deleted"]]; - nonDeletedQualifier = [[EONotQualifier alloc] - initWithQualifier: deletedQualifier]; - [deletedQualifier release]; - } - - return nonDeletedQualifier; -} - -- (NSArray *) messageKeysMatchingQualifier: (EOQualifier *) qualifier - andSortOrderings: (NSArray *) sortOrderings -{ - NSArray *uidKeys; - EOQualifier *fetchQualifier, *simplifiedQualifier; - - if ([self ensureFolderExists]) - { - if (!sortOrderings) - sortOrderings = [NSArray arrayWithObject: @"ARRIVAL"]; - - if (qualifier) - { - simplifiedQualifier = [self simplifyQualifier: qualifier]; - fetchQualifier - = [[EOAndQualifier alloc] initWithQualifiers: - [self nonDeletedQualifier], simplifiedQualifier, - nil]; - [fetchQualifier autorelease]; - } - else - fetchQualifier = [self nonDeletedQualifier]; - - uidKeys = [[sogoObject fetchUIDsMatchingQualifier: fetchQualifier - sortOrdering: sortOrderings] - stringsWithFormat: @"%@.eml"]; - } - else - uidKeys = nil; - - return uidKeys; -} - -- (NSMutableString *) _imapFolderNameRepresentation: (NSString *) subfolderName -{ - NSMutableString *representation; - NSString *nameInContainer, *strippedName; - - nameInContainer = [self nameInContainer]; - if (container) - representation = [(MAPIStoreMailFolder *) container - _imapFolderNameRepresentation: nameInContainer]; - else - { - if (![nameInContainer hasPrefix: @"folder"]) - abort (); - strippedName = [nameInContainer substringFromIndex: 6]; - representation = [NSMutableString stringWithString: strippedName]; - } - - if (![subfolderName hasPrefix: @"folder"]) - abort (); - strippedName = [[subfolderName substringFromIndex: 6] stringByDecodingImap4FolderName]; - [representation appendFormat: @"/%@", strippedName]; - - return representation; -} - -- (void) _cleanupSubfolderKeys: (NSMutableArray *) subfolderKeys -{ - SOGoMailAccount *account; - NSString *draftsFolderName, *sentFolderName, *trashFolderName; - NSString *subfolderKey, *cmpString; - NSUInteger count, max; - NSMutableArray *keysToRemove; - - account = [(SOGoMailFolder *) sogoObject mailAccountFolder]; - draftsFolderName = [account draftsFolderNameInContext: nil]; - sentFolderName = [account sentFolderNameInContext: nil]; - trashFolderName = [account trashFolderNameInContext: nil]; - - max = [subfolderKeys count]; - keysToRemove = [NSMutableArray arrayWithCapacity: max]; - for (count = 0; count < max; count++) - { - subfolderKey = [subfolderKeys objectAtIndex: count]; - cmpString = [self _imapFolderNameRepresentation: subfolderKey]; - if ([cmpString isEqualToString: draftsFolderName] - || [cmpString isEqualToString: sentFolderName] - || [cmpString isEqualToString: trashFolderName]) - [keysToRemove addObject: subfolderKey]; - } - - [subfolderKeys removeObjectsInArray: keysToRemove]; -} - -- (NSArray *) folderKeysMatchingQualifier: (EOQualifier *) qualifier - andSortOrderings: (NSArray *) sortOrderings -{ - NSArray *filteredSubfolderKeys; - NSMutableArray *subfolderKeys; - NSMutableArray *subfolderKeysQualifying; - NSString *subfolderKey; - NSUInteger count, max; - - if ([self ensureFolderExists]) - { - /* Only folder name can be used as qualifier key */ - if (qualifier) - [self warnWithFormat: @"qualifier is only used for folders with name"]; - if (sortOrderings) - [self errorWithFormat: @"sort orderings are not used for folders"]; - - /* FIXME: Flush any cache before retrieving the hierarchy, this - slows things down but it is safer */ - if (!qualifier) - [sogoObject flushMailCaches]; - - subfolderKeys = [[sogoObject toManyRelationshipKeys] mutableCopy]; - [subfolderKeys autorelease]; - - [self _cleanupSubfolderKeys: subfolderKeys]; - - if (qualifier) - { - subfolderKeysQualifying = [NSMutableArray array]; - max = [subfolderKeys count]; - for (count = 0; count < max; count++) { - subfolderKey = [subfolderKeys objectAtIndex: count]; - /* Remove "folder" prefix */ - subfolderKey = [subfolderKey substringFromIndex: 6]; - subfolderKey = [[subfolderKey fromCSSIdentifier] stringByDecodingImap4FolderName]; - [subfolderKeysQualifying addObject: [NSDictionary dictionaryWithObject: subfolderKey - forKey: @"name"]]; - } - filteredSubfolderKeys = [subfolderKeysQualifying filteredArrayUsingQualifier: qualifier]; - - max = [filteredSubfolderKeys count]; - subfolderKeys = [NSMutableArray arrayWithCapacity: max]; - for (count = 0; count < max; count++) - { - subfolderKey = [[filteredSubfolderKeys objectAtIndex: count] valueForKey: @"name"]; - subfolderKey = [NSString stringWithFormat: @"folder%@", [[subfolderKey stringByEncodingImap4FolderName] asCSSIdentifier]]; - [subfolderKeys addObject: subfolderKey]; - } - - } - } - else - subfolderKeys = nil; - - return subfolderKeys; -} - -- (NSDate *) creationTime -{ - return [NSCalendarDate dateWithTimeIntervalSince1970: 0x4dbb2dbe]; /* oc_version_time */ -} - -- (NSDate *) lastMessageModificationTime -{ - NSNumber *ti; - NSDate *value = nil; - - [self synchroniseCache]; - ti = [[versionsMessage properties] - objectForKey: @"SyncLastSynchronisationDate"]; - if (ti) - value = [NSDate dateWithTimeIntervalSince1970: [ti doubleValue]]; - else - value = [NSDate date]; - - //[self logWithFormat: @"lastMessageModificationTime: %@", value]; - - return value; -} - -- (SOGoFolder *) aclFolder -{ - return (SOGoFolder *) sogoObject; -} - -- (NSArray *) permissionEntries -{ - NSArray *permissionEntries; - - if ([self ensureFolderExists]) - permissionEntries = [super permissionEntries]; - else - permissionEntries = nil; - - return permissionEntries; -} - -- (BOOL) supportsSubFolders -{ - BOOL supportsSubFolders; - MAPIStoreUserContext *userContext; - - if ([[self nameInContainer] isEqualToString: @"folderINBOX"]) - { - userContext = [self userContext]; - supportsSubFolders = ![userContext inboxHasNoInferiors]; - } - else - supportsSubFolders = YES; - - return supportsSubFolders; -} - -/* synchronisation */ - -/* Tree: -{ - SyncLastModseq = x; - SyncLastSynchronisationDate = x; ** not updated until something changed - Messages = { - MessageKey = { - Version = x; - Modseq = x; - Deleted = b; - }; - ... - }; - VersionMapping = { - Version = MessageKey; - ... - } -} -*/ - -static NSComparisonResult -_compareFetchResultsByMODSEQ (id entry1, id entry2, void *data) -{ - static NSNumber *zeroNumber = nil; - NSNumber *modseq1, *modseq2; - - if (!zeroNumber) - { - zeroNumber = [NSNumber numberWithUnsignedLongLong: 0]; - [zeroNumber retain]; - } - - modseq1 = [entry1 objectForKey: @"modseq"]; - if (!modseq1) - modseq1 = zeroNumber; - modseq2 = [entry2 objectForKey: @"modseq"]; - if (!modseq2) - modseq2 = zeroNumber; - - return [modseq1 compare: modseq2]; -} - -- (void) _updatePredecessorChangeListWith: (NSData *) predecessorChangeList - forMessageEntry: (NSMutableDictionary *) messageEntry -{ - NSData *globCnt, *oldGlobCnt; - NSMutableDictionary *changeList; - NSString *guid; - struct SizedXid *sizedXIDList; - struct XID xid; - uint32_t i, length; - - sizedXIDList = [predecessorChangeList asSizedXidArrayInMemCtx: NULL with: &length]; - - changeList = [messageEntry objectForKey: @"PredecessorChangeList"]; - if (!changeList) - { - changeList = [NSMutableDictionary new]; - [messageEntry setObject: changeList - forKey: @"PredecessorChangeList"]; - [changeList release]; - } - - if (sizedXIDList) { - for (i = 0; i < length; i++) - { - xid = sizedXIDList[i].XID; - guid = [NSString stringWithGUID: &xid.NameSpaceGuid]; - globCnt = [NSData dataWithBytes: xid.LocalId.data length: xid.LocalId.length]; - oldGlobCnt = [changeList objectForKey: guid]; - if (!oldGlobCnt || ([globCnt compare: oldGlobCnt] == NSOrderedDescending)) - [changeList setObject: globCnt forKey: guid]; - } - - talloc_free (sizedXIDList); - } - - [versionsMessage save]; -} - -- (void) _setChangeKey: (NSData *) changeKey - forMessageEntry: (NSMutableDictionary *) messageEntry -{ - struct XID *xid; - NSString *guid; - NSData *globCnt; - NSDictionary *changeKeyDict; - NSMutableDictionary *changeList; - - xid = [changeKey asXIDInMemCtx: NULL]; - guid = [NSString stringWithGUID: &xid->NameSpaceGuid]; - globCnt = [NSData dataWithBytes: xid->LocalId.data length: xid->LocalId.length]; - talloc_free (xid); - - /* 1. set change key association */ - changeKeyDict = [NSDictionary dictionaryWithObjectsAndKeys: - guid, @"GUID", - globCnt, @"LocalId", - nil]; - [messageEntry setObject: changeKeyDict forKey: @"ChangeKey"]; - - /* 2. append/update predecessor change list */ - changeList = [messageEntry objectForKey: @"PredecessorChangeList"]; - if (!changeList) - { - changeList = [NSMutableDictionary new]; - [messageEntry setObject: changeList - forKey: @"PredecessorChangeList"]; - [changeList release]; - } - [changeList setObject: globCnt forKey: guid]; -} - -- (BOOL) synchroniseCache -{ - BOOL rc = YES; - uint64_t newChangeNum; - NSNumber *ti, *modseq, *lastModseq, *nextModseq; - NSString *changeNumber, *uid, *messageKey; - uint64_t lastModseqNbr; - EOQualifier *searchQualifier; - NSArray *uids, *changeNumbers; - NSUInteger count, max, nFetched; - NSArray *fetchResults; - NSDictionary *result; - NSData *changeKey; - NSMutableArray *messageKeys; - NSMutableDictionary *currentProperties, *messages, *mapping, *messageEntry; - NSCalendarDate *now; - BOOL foundChange = NO; - - /* NOTE: we are using NSString instance for "uid" and "changeNumber" because - NSNumber proved to give very bad performances when used as NSDictionary - keys with GNUstep 1.22.1. The bug seems to be solved with 1.24 but many - distros still ship an older version. */ - now = [NSCalendarDate date]; - [now setTimeZone: utcTZ]; - - [versionsMessage reloadIfNeeded]; - currentProperties = [versionsMessage properties]; - messages = [currentProperties objectForKey: @"Messages"]; - if (!messages) - { - messages = [NSMutableDictionary new]; - [currentProperties setObject: messages forKey: @"Messages"]; - [messages release]; - } - mapping = [currentProperties objectForKey: @"VersionMapping"]; - if (!mapping) - { - mapping = [NSMutableDictionary new]; - [currentProperties setObject: mapping forKey: @"VersionMapping"]; - [mapping release]; - } - - lastModseq = [currentProperties objectForKey: @"SyncLastModseq"]; - if (lastModseq) - { - lastModseqNbr = [lastModseq unsignedLongLongValue]; - nextModseq = [NSNumber numberWithUnsignedLongLong: lastModseqNbr + 1]; - searchQualifier = [[EOKeyValueQualifier alloc] - initWithKey: @"modseq" - operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo - value: nextModseq]; - - [searchQualifier autorelease]; - } - else - { - lastModseqNbr = 0; - searchQualifier = [self nonDeletedQualifier]; - } - - /* 1. we fetch modified or added uids */ - uids = [sogoObject fetchUIDsMatchingQualifier: searchQualifier - sortOrdering: nil]; - max = [uids count]; - if (max > 0) - { - messageKeys = [NSMutableArray arrayWithCapacity: max]; - for (count = 0; count < max; count++) - { - messageKey = [NSString stringWithFormat: @"%@.eml", - [uids objectAtIndex: count]]; - [messageKeys addObject: messageKey]; - } - [self ensureIDsForChildKeys: messageKeys]; - - changeNumbers = [[self context] getNewChangeNumbers: max]; - - fetchResults - = [(NSDictionary *) [sogoObject fetchUIDs: uids - parts: [NSArray arrayWithObjects: @"modseq", @"flags", nil]] - objectForKey: @"fetch"]; - - /* NOTE: we sort items manually because Cyrus does not properly sort - entries with a MODSEQ of 0 */ - fetchResults - = [fetchResults sortedArrayUsingFunction: _compareFetchResultsByMODSEQ - context: NULL]; - - nFetched = [fetchResults count]; - if (nFetched != max) { - [self errorWithFormat: @"Error fetching UIDs. Asked: %d Received: %d." - @"Check the IMAP conversation for details", max, nFetched]; - return NO; - } - - for (count = 0; count < max; count++) - { - result = [fetchResults objectAtIndex: count]; - uid = [[result objectForKey: @"uid"] stringValue]; - modseq = [result objectForKey: @"modseq"]; - newChangeNum = [[changeNumbers objectAtIndex: count] - unsignedLongLongValue]; - changeNumber = [NSString stringWithUnsignedLongLong: newChangeNum]; - - messageEntry = [NSMutableDictionary new]; - [messages setObject: messageEntry forKey: uid]; - [messageEntry release]; - - [messageEntry setObject: modseq forKey: @"modseq"]; - [messageEntry setObject: changeNumber forKey: @"version"]; - - //[self logWithFormat: @"added message entry for uid %@, modseq %@," - // @" version %@", uid, modseq, changeNumber]; - - changeKey = [self getReplicaKeyFromGlobCnt: newChangeNum >> 16]; - [self _setChangeKey: changeKey forMessageEntry: messageEntry]; - - [mapping setObject: modseq forKey: changeNumber]; - - if (!lastModseq - || ([lastModseq compare: modseq] == NSOrderedAscending)) - lastModseq = modseq; - - if ([[result objectForKey: @"flags"] containsObject: @"deleted"]) - [currentProperties setObject: changeNumber - forKey: @"SyncLastDeleteChangeNumber"]; - } - - [currentProperties setObject: lastModseq forKey: @"SyncLastModseq"]; - foundChange = YES; - } - - /* 2. we synchronise expunged UIDs */ - fetchResults = [(SOGoMailFolder *) sogoObject - fetchUIDsOfVanishedItems: lastModseqNbr]; - - max = [fetchResults count]; - - changeNumber = nil; - for (count = 0; count < max; count++) - { - uid = [[fetchResults objectAtIndex: count] stringValue]; - if ([messages objectForKey: uid]) - { - if (!changeNumber) - { - newChangeNum = [[self context] getNewChangeNumber]; - changeNumber = [NSString stringWithUnsignedLongLong: newChangeNum]; - } - [messages removeObjectForKey: uid]; - [self logWithFormat: @"Removed message entry for UID %@", uid]; - } - else - { - [self logWithFormat:@"Message entry not found for UID %@", uid]; - } - } - if (changeNumber) - { - [currentProperties setObject: changeNumber - forKey: @"SyncLastDeleteChangeNumber"]; - [mapping setObject: lastModseq forKey: changeNumber]; - foundChange = YES; - } - - if (foundChange) - { - [self synchronizeUpdatedFolder: lastModseq - withMapping: mapping]; - - ti = [NSNumber numberWithDouble: [now timeIntervalSince1970]]; - [currentProperties setObject: ti - forKey: @"SyncLastSynchronisationDate"]; - [versionsMessage save]; - } - - - return rc; -} - -- (void) synchronizeUpdatedFolder: (NSNumber *) lastModseq - withMapping: (NSMutableDictionary *) mapping -{ - /* This method should be called whenever something has changed on the folder. - Then we will perform two actions: - 1 - Update the PidTagChangeNumber property of the root container. - 2 - Store relationship PidTagChangenumber with lastModseq value on the - mapping given as parameter for this folder */ - uint64_t *current_cn; - struct SRow row; - struct SPropValue prop; - uint64_t fid; - const char *username; - struct openchangedb_context *oc_ctx; - enum MAPISTATUS retval; - TALLOC_CTX *local_mem_ctx = NULL; - - row.cValues = 1; - prop.ulPropTag = PidTagChangeNumber; - prop.value.d = 0; // It doesn't matter, it will be autogenerated - row.lpProps = ∝ - - /* We are doing a "touch" operation to update change number of the root container. - We get the root container as it has the properties in the OpenChange DB */ - username = [[self context] connectionInfo]->username; - oc_ctx = [[self context] connectionInfo]->oc_ctx; - fid = [[self rootContainer] objectId]; - retval = openchangedb_set_folder_properties(oc_ctx, username, fid, &row); - if (retval != MAPI_E_SUCCESS) - { - [self errorWithFormat:@"%s: Error setting change number on %"PRIu64, - __PRETTY_FUNCTION__, fid]; - return; - } - - local_mem_ctx = talloc_named(NULL, 0, __PRETTY_FUNCTION__); - if (local_mem_ctx == NULL) - { - [self errorWithFormat:@"%s: Error with talloc_named, out of memory?", - __PRETTY_FUNCTION__]; - return; - } - retval = openchangedb_get_folder_property(local_mem_ctx, oc_ctx, username, - PidTagChangeNumber, fid, - (void **) ¤t_cn); - if (retval != MAPI_E_SUCCESS) - { - [self errorWithFormat:@"%s: Error getting change number on %"PRIu64, - __PRETTY_FUNCTION__, fid]; - talloc_free(local_mem_ctx); - return; - } - - [mapping setObject: lastModseq - forKey: [NSString stringWithUnsignedLongLong: *current_cn]]; - talloc_free(local_mem_ctx); -} - -- (BOOL) synchroniseCacheForUID: (NSString *) messageUID -{ - /* Try to synchronise old UIDs in versions.plist cache using an - specific UID. It returns a boolean indicating if the - synchronisation were done. - - It should be used as last resort, keeping synchroniseCache to main - sync entry point. - */ - NSMutableDictionary *currentProperties, *messages, *messageEntry, *mapping; - NSArray *fetchResults; - uint64_t changeNumber; - NSDictionary *result; - NSNumber *modseq; - NSString *changeNumberStr; - NSData *changeKey; - - [versionsMessage reloadIfNeeded]; - currentProperties = [versionsMessage properties]; - messages = [currentProperties objectForKey: @"Messages"]; - messageEntry = [messages objectForKey: messageUID]; - if (!messageEntry) - { - fetchResults = [(NSDictionary *) [sogoObject fetchUIDs: [NSArray arrayWithObject: messageUID] - parts: [NSArray arrayWithObjects: @"modseq", @"flags", nil]] - objectForKey: @"fetch"]; - if ([fetchResults count] == 1) - { - result = [fetchResults objectAtIndex: 0]; - modseq = [result objectForKey: @"modseq"]; - changeNumber = [[self context] getNewChangeNumber]; - changeNumberStr = [NSString stringWithUnsignedLongLong: changeNumber]; - - /* Create new message entry in Messages dict */ - messageEntry = [NSMutableDictionary new]; - [messages setObject: messageEntry forKey: messageUID]; - [messageEntry release]; - - /* Store the modseq and change number */ - [messageEntry setObject: modseq forKey: @"modseq"]; - [messageEntry setObject: changeNumberStr forKey: @"version"]; - - /* Store the change key */ - changeKey = [self getReplicaKeyFromGlobCnt: changeNumber >> 16]; - [self _setChangeKey: changeKey forMessageEntry: messageEntry]; - - /* Store the changeNumber -> modseq mapping */ - mapping = [currentProperties objectForKey: @"VersionMapping"]; - [mapping setObject: modseq forKey: changeNumberStr]; - - /* Store the last deleted change number if it is soft-deleted */ - if ([[result objectForKey: @"flags"] containsObject: @"deleted"]) - [currentProperties setObject: changeNumberStr - forKey: @"SyncLastDeleteChangeNumber"]; - - /* Save the message */ - [versionsMessage save]; - return YES; - } - else - { - return NO; - } - } - /* If message entry exists, then synchroniseCache did its job */ - return YES; -} - - -- (NSNumber *) modseqFromMessageChangeNumber: (NSString *) changeNum -{ - NSDictionary *mapping; - NSNumber *modseq; - NSEnumerator *enumerator; - id key; - uint64_t found, target, current, replica_id, current_cn; - NSString *closestChangeNum; - - mapping = [[versionsMessage properties] objectForKey: @"VersionMapping"]; - modseq = [mapping objectForKey: changeNum]; - if (modseq) return modseq; - - // Not found from stored change numbers for this folder. - // Get the closest modseq for the change number given. - // O(n) cost but will be unusual behaviour. - target = exchange_globcnt([changeNum unsignedLongLongValue] >> 16); - replica_id = [changeNum unsignedLongLongValue] & 0xFFFF; - found = 0; - enumerator = [mapping keyEnumerator]; - while ((key = [enumerator nextObject])) - { - current_cn = [(NSString *)key unsignedLongLongValue]; - if ((current_cn & 0xFFFF) != replica_id) - continue; - current = exchange_globcnt(current_cn >> 16); - if (current < target && current > found) - found = current; - } - - if (found) - { - closestChangeNum = [NSString stringWithUnsignedLongLong: - (exchange_globcnt(found) << 16 | replica_id)]; - modseq = [mapping objectForKey: closestChangeNum]; - } - - return modseq; -} - -- (NSString *) messageUIDFromMessageKey: (NSString *) messageKey -{ - NSString *messageUid; - NSRange dotRange; - - dotRange = [messageKey rangeOfString: @".eml"]; - if (dotRange.location != NSNotFound) - messageUid = [messageKey substringToIndex: dotRange.location]; - else - { - messageUid = nil; - [self errorWithFormat:@"%s: Unexpected messageKey value [%@]", - __PRETTY_FUNCTION__, messageKey]; - } - - return messageUid; -} - -- (NSString *) changeNumberForMessageUID: (NSString *) messageUid -{ - NSDictionary *messages; - NSString *changeNumber; - - messages = [[versionsMessage properties] objectForKey: @"Messages"]; - changeNumber = [[messages objectForKey: messageUid] - objectForKey: @"version"]; - - return changeNumber; -} - -- (NSMutableDictionary *) _messageEntryFromMessageKey: (NSString *) messageKey -{ - NSMutableDictionary *messages, *messageEntry; - NSString *messageUid; - BOOL synced; - - messageUid = [self messageUIDFromMessageKey: messageKey]; - messages = [[versionsMessage properties] objectForKey: @"Messages"]; - messageEntry = [messages objectForKey: messageUid]; - if (!messageEntry) - { - [self warnWithFormat: @"attempting to synchronise to get the message entry for " - @"this message %@", messageKey]; - synced = [self synchroniseCacheForUID: messageUid]; - if (synced) - messageEntry = [[[versionsMessage properties] objectForKey: @"Messages"] objectForKey: messageUid]; - if (!messageEntry) - { - [self errorWithFormat: @"still nothing. We crash!"]; - abort (); - } - } - - return messageEntry; -} - -- (void) setChangeKey: (NSData *) changeKey - forMessageWithKey: (NSString *) messageKey -{ - [self _setChangeKey: changeKey - forMessageEntry: [self _messageEntryFromMessageKey: messageKey]]; - - [versionsMessage save]; -} - -- (BOOL) updatePredecessorChangeListWith: (NSData *) changeKey - forMessageWithKey: (NSString *) messageKey -{ - /* Update predecessor change list property given the change key. It - returns if the change key has been added to the list or not */ - BOOL added = NO; - NSData *globCnt, *oldGlobCnt; - NSDictionary *messageEntry; - NSMutableDictionary *changeList; - NSString *guid; - struct XID *xid; - - xid = [changeKey asXIDInMemCtx: NULL]; - guid = [NSString stringWithGUID: &xid->NameSpaceGuid]; - globCnt = [NSData dataWithBytes: xid->LocalId.data length: xid->LocalId.length]; - talloc_free (xid); - - messageEntry = [self _messageEntryFromMessageKey: messageKey]; - if (messageEntry) - { - changeList = [messageEntry objectForKey: @"PredecessorChangeList"]; - if (changeList) - { - oldGlobCnt = [changeList objectForKey: guid]; - if (!oldGlobCnt || ([globCnt compare: oldGlobCnt] == NSOrderedDescending)) - { - [changeList setObject: globCnt forKey: guid]; - [versionsMessage save]; - added = YES; - } - } - else - [self errorWithFormat: @"Missing predecessor change list to update"]; - } - - return added; -} - -- (NSData *) changeKeyForMessageWithKey: (NSString *) messageKey -{ - NSDictionary *messages, *changeKeyDict; - NSString *guid, *messageUid; - NSData *globCnt, *changeKey = nil; - - messageUid = [self messageUIDFromMessageKey: messageKey]; - messages = [[versionsMessage properties] objectForKey: @"Messages"]; - changeKeyDict = [[messages objectForKey: messageUid] - objectForKey: @"ChangeKey"]; - if (changeKeyDict) - { - guid = [changeKeyDict objectForKey: @"GUID"]; - globCnt = [changeKeyDict objectForKey: @"LocalId"]; - changeKey = [NSData dataWithChangeKeyGUID: guid andCnt: globCnt]; - } - - return changeKey; -} - -- (NSData *) predecessorChangeListForMessageWithKey: (NSString *) messageKey -{ - NSMutableData *list = nil; - NSDictionary *messages, *changeListDict; - NSArray *keys; - NSMutableArray *changeKeys; - NSUInteger count, max; - NSData *changeKey; - NSString *guid, *messageUid; - NSData *globCnt; - - messageUid = [self messageUIDFromMessageKey: messageKey]; - messages = [[versionsMessage properties] objectForKey: @"Messages"]; - changeListDict = [[messages objectForKey: messageUid] - objectForKey: @"PredecessorChangeList"]; - if (changeListDict) - { - keys = [changeListDict allKeys]; - max = [keys count]; - - changeKeys = [NSMutableArray arrayWithCapacity: max]; - for (count = 0; count < max; count++) - { - guid = [keys objectAtIndex: count]; - globCnt = [changeListDict objectForKey: guid]; - changeKey = [NSData dataWithChangeKeyGUID: guid andCnt: globCnt]; - [changeKeys addObject: changeKey]; - } - [changeKeys sortUsingFunction: MAPIChangeKeyGUIDCompare - context: nil]; - - list = [NSMutableData data]; - for (count = 0; count < max; count++) - { - changeKey = [changeKeys objectAtIndex: count]; - [list appendUInt8: [changeKey length]]; - [list appendData: changeKey]; - } - } - - return list; -} - -/* Management for extra properties once they already hit the IMAP server */ -- (void) setExtraProperties: (NSDictionary *) props - forMessage: (NSString *) messageKey -{ - NSMutableDictionary *extraProps, *currentProperties; - NSString *messageUid; - - messageUid = [self messageUIDFromMessageKey: messageKey]; - currentProperties = [versionsMessage properties]; - extraProps = [currentProperties objectForKey: @"ExtraMessagesProperties"]; - if (!extraProps) - { - extraProps = [NSMutableDictionary new]; - [currentProperties setObject: extraProps forKey: @"ExtraMessagesProperties"]; - [extraProps release]; - } - - [extraProps setObject: props - forKey: messageUid]; - [versionsMessage save]; -} - -- (NSDictionary *) extraPropertiesForMessage: (NSString *) messageKey -{ - NSString *messageUid; - - messageUid = [self messageUIDFromMessageKey: messageKey]; - return [[[versionsMessage properties] objectForKey: @"ExtraMessagesProperties"] - objectForKey: messageUid]; -} - -- (NSArray *) getDeletedKeysFromChangeNumber: (uint64_t) changeNum - andCN: (NSNumber **) cnNbr - inTableType: (uint8_t) tableType -{ - NSArray *deletedKeys, *deletedUIDs; - NSString *changeNumber; - uint64_t modseq; - NSDictionary *versionProperties; - EOQualifier *deletedQualifier, *kvQualifier, *searchQualifier; - - if (tableType == MAPISTORE_MESSAGE_TABLE) - { - changeNumber = [NSString stringWithFormat: @"0x%.16llx", changeNum]; - modseq = [[self modseqFromMessageChangeNumber: changeNumber] - unsignedLongLongValue]; - if (modseq > 0) - { - /* Hard deleted items */ - deletedUIDs = [(SOGoMailFolder *) sogoObject - fetchUIDsOfVanishedItems: modseq]; - - /* Soft deleted items */ - kvQualifier = [[EOKeyValueQualifier alloc] - initWithKey: @"modseq" - operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo - value: [NSNumber numberWithUnsignedLongLong: modseq]]; - deletedQualifier - = [[EOKeyValueQualifier alloc] - initWithKey: @"FLAGS" - operatorSelector: EOQualifierOperatorContains - value: [NSArray arrayWithObject: @"Deleted"]]; - - searchQualifier = [[EOAndQualifier alloc] - initWithQualifiers: - kvQualifier, deletedQualifier, nil]; - - deletedUIDs = [deletedUIDs arrayByAddingObjectsFromArray: - [sogoObject fetchUIDsMatchingQualifier: searchQualifier - sortOrdering: nil]]; - - [deletedQualifier release]; - [kvQualifier release]; - [searchQualifier release]; - - deletedKeys = [deletedUIDs stringsWithFormat: @"%@.eml"]; - if ([deletedUIDs count] > 0) - { - versionProperties = [versionsMessage properties]; - changeNumber = [versionProperties - objectForKey: @"SyncLastDeleteChangeNumber"]; - *cnNbr = [NSNumber numberWithUnsignedLongLong: - [changeNumber unsignedLongLongValue]]; - [versionsMessage save]; - } - } - else - deletedKeys = [NSArray array]; - } - else - deletedKeys = [super getDeletedKeysFromChangeNumber: changeNum - andCN: cnNbr - inTableType: tableType]; - - return deletedKeys; -} - -static void -_appendIMAPRange (NSMutableArray *UIDs, uint32_t low, uint32_t high) -{ - uint32_t count; - - for (count = low; count < high + 1; count++) - [UIDs addObject: [NSNumber numberWithUnsignedLong: count]]; -} - -static NSUInteger -_parseUID (const unichar *uniString, uint32_t *newUidP) -{ - NSUInteger count = 0; - uint32_t newUid = 0; - - while (uniString[count] >= '0' && uniString[count] <= '9') - { - newUid = newUid * 10 + (uniString[count] - 48); - count++; - } - *newUidP = newUid; - - return count; -} - -static NSUInteger -_parseIMAPRange (const unichar *uniString, NSArray **UIDsP) -{ - NSMutableArray *UIDs; - NSUInteger count = 0; - uint32_t currentUid, rangeMin; - BOOL done = NO, inRange = NO; - - rangeMin = 0; - currentUid = 0; - UIDs = [NSMutableArray array]; - while (!done) - { - count += _parseUID (uniString + count, ¤tUid); - switch (uniString[count]) - { - case ':': - inRange = YES; - rangeMin = currentUid; - break; - case ' ': - case 0: - done = YES; - case ',': - if (inRange) - { - _appendIMAPRange (UIDs, rangeMin, currentUid); - inRange = NO; - } - else - [UIDs addObject: [NSNumber numberWithUnsignedLong: currentUid]]; - break; - default: - abort (); - } - count++; - } - *UIDsP = UIDs; - - return count; -} - -static void -_parseCOPYUID (NSString *line, NSArray **destUIDsP) -{ - unichar *uniString; - NSUInteger count = 0, max; - // char state = 'i'; /* i = init, v = validity, s = source range, d = dest range */ - - /* sample: 1 OK [COPYUID 1311899334 1:3 11:13] Completed */ - - max = [line length]; - uniString = NSZoneMalloc (NULL, sizeof (unichar) * (max + 1)); - [line getCharacters: uniString]; - uniString[max] = 0; - - while (count < max && uniString[count] != ' ') - count++; - count++; - while (count < max && uniString[count] != ' ') - count++; - count++; - while (count < max && uniString[count] != ' ') - count++; - count++; - if (count < max) - count += _parseIMAPRange (uniString + count, destUIDsP); - - NSZoneFree (NULL, uniString); -} - -// -// Move (or eventually copy) the mails identified by -// "srcMids" from the source folder into this folder. -// -- (enum mapistore_error) moveCopyMessagesWithMIDs: (uint64_t *) srcMids - andCount: (uint32_t) midCount - fromFolder: (MAPIStoreFolder *) sourceFolder - withMIDs: (uint64_t *) targetMids - andChangeKeys: (struct Binary_r **) targetChangeKeys - andPredecessorChangeLists: (struct Binary_r **) targetPredecessorChangeLists - wantCopy: (uint8_t) wantCopy - inMemCtx: (TALLOC_CTX *) memCtx -{ - NGImap4Connection *connection; - NGImap4Client *client; - NSString *sourceFolderName, *targetFolderName, *messageURL, *messageKey, - *uid, *v; - NSMutableArray *uids, *oldMessageURLs; - NSArray *destUIDs; - MAPIStoreMapping *mapping; - NSDictionary *result; - NSUInteger count; - NSArray *a; - NSData *changeList; - - if (![sourceFolder isKindOfClass: [MAPIStoreMailFolder class]]) - return [super moveCopyMessagesWithMIDs: srcMids andCount: midCount - fromFolder: sourceFolder withMIDs: targetMids - andChangeKeys: targetChangeKeys - andPredecessorChangeLists: targetPredecessorChangeLists - wantCopy: wantCopy - inMemCtx: memCtx]; - - /* Conversion of mids to IMAP uids */ - mapping = [self mapping]; - uids = [NSMutableArray arrayWithCapacity: midCount]; - oldMessageURLs = [NSMutableArray arrayWithCapacity: midCount]; - for (count = 0; count < midCount; count++) - { - messageURL = [mapping urlFromID: srcMids[count]]; - if (messageURL) - { - uid = [self messageUIDFromMessageKey: [messageURL lastPathComponent]]; - [uids addObject: uid]; - - [oldMessageURLs addObject: messageURL]; - } - else - return MAPISTORE_ERROR; - } - - /* IMAP COPY */ - connection = [sogoObject imap4Connection]; - sourceFolderName = [connection - imap4FolderNameForURL: [[sourceFolder sogoObject] imap4URL]]; - targetFolderName = [connection - imap4FolderNameForURL: [sogoObject imap4URL]]; - - client = [connection client]; - [client select: sourceFolderName]; - result = [client copyUids: uids toFolder: targetFolderName]; - if (![[result objectForKey: @"result"] boolValue]) - return MAPISTORE_ERROR; - - /* "Move" treatment: Store \Deleted and unregister urls as soft-deleted */ - if (!wantCopy) - { - [client storeFlags: [NSArray arrayWithObject: @"Deleted"] forUIDs: uids - addOrRemove: YES]; - for (count = 0; count < midCount; count++) - { - /* Using soft-deleted to make deleted fmids to return the - srcMids. - See [MAPIStoreFolder getDeletedFMIDs:andCN:fromChangeNumber:inTableType:inMemCtx] - for details */ - [mapping unregisterURLWithID: srcMids[count] - andFlags: MAPISTORE_SOFT_DELETE]; - } - } - - /* Registration of target messages */ - // - // We use the UIDPLUS IMAP extension here in order to speedup UID retrieval - // If supported by the server, we'll get something like: COPYUID 1315425789 1 8 - // - // Sometimes COPYUID isn't returned at all by Cyrus or in case the server doesn't - // support the UIDPLUS IMAP extension, we fallback to a simple UID search. - // - v = [[[result objectForKey: @"RawResponse"] objectForKey: @"ResponseResult"] objectForKey: @"flag"]; - if (v) - { - destUIDs = nil; - _parseCOPYUID (v, &destUIDs); - } - else - { - /* FIXME: this may fail if new messages are appended to the folder - between the COPY and SORT operations */ - [client select: targetFolderName]; - a = [[client sort: @"ARRIVAL" qualifier: nil encoding: @"UTF-8"] - objectForKey: @"sort"]; - destUIDs = [[a sortedArrayUsingSelector: @selector (compare:)] - subarrayWithRange: NSMakeRange ([a count] - midCount, midCount)]; - } - for (count = 0; count < midCount; count++) - { - messageURL = [NSString stringWithFormat: @"%@%@.eml", - [self url], - [destUIDs objectAtIndex: count]]; - [mapping registerURL: messageURL withID: targetMids[count]]; - } - - /* Update the change keys */ - if (targetChangeKeys) - { - [self synchroniseCache]; - for (count = 0; count < midCount; count++) - { - changeList = [NSData dataWithBinary: targetPredecessorChangeLists[count]]; - messageKey = [NSString stringWithFormat: @"%@.eml", - [destUIDs objectAtIndex: count]]; - [self _updatePredecessorChangeListWith: changeList - forMessageEntry: [self _messageEntryFromMessageKey: messageKey]]; - } - } - - // We cleanup cache of our source and destination folders - [self cleanupCaches]; - [sourceFolder cleanupCaches]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) moveCopyToFolder: (MAPIStoreFolder *) targetFolder - withNewName: (NSString *) newFolderName - isMove: (BOOL) isMove - isRecursive: (BOOL) isRecursive - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - NSURL *folderURL, *newFolderURL; - struct SRow folderRow; - struct SPropValue nameProperty; - MAPIStoreMailFolder *newFolder; - SOGoMailAccount *accountFolder; - SOGoMailFolder *targetSOGoFolder; - NSMutableArray *uids; - NSArray *childKeys; - NSUInteger count, max; - NGImap4Connection *connection; - NGImap4Client *client; - NSString *newURL, *parentDBFolderPath, *childKey, *folderIMAPName, - *urlNamePart, *newFolderIMAPName, *newFolderDBName; - NSException *error; - MAPIStoreMapping *mapping; - NSDictionary *result; - - if ([targetFolder isKindOfClass: MAPIStoreMailFolderK] || (!targetFolder && isMove)) - { - folderURL = [sogoObject imap4URL]; - if (!newFolderName) - newFolderName = [sogoObject displayName]; - targetSOGoFolder = [targetFolder sogoObject]; - if (isMove) - { - newFolderDBName = [[newFolderName stringByEncodingImap4FolderName] asCSSIdentifier]; - if (targetSOGoFolder) - { - /* Mimetise [SOGoMailFolderK imap4URLString] */ - urlNamePart = [[newFolderName stringByEncodingImap4FolderName] stringByEscapingURL]; - newFolderURL = [NSURL URLWithString: urlNamePart - relativeToURL: [targetSOGoFolder imap4URL]]; - } - else - { - /* Mimetise what createRootSecondaryFolderWithFID does */ - accountFolder = [[[self userContext] rootFolders] objectForKey: @"mail"]; - targetSOGoFolder = [SOGoMailFolder objectWithName: [NSString stringWithFormat: @"folder%@", - newFolderDBName] - inContainer: accountFolder]; - newFolderURL = [targetSOGoFolder imap4URL]; - } - error = [[sogoObject imap4Connection] - moveMailboxAtURL: folderURL - toURL: newFolderURL]; - if (error) - rc = MAPISTORE_ERR_DENIED; - else - { - rc = MAPISTORE_SUCCESS; - mapping = [self mapping]; - if (targetFolder) - newURL = [NSString stringWithFormat: @"%@folder%@/", - [targetFolder url], newFolderDBName]; - else - newURL = [NSString stringWithFormat: @"sogo://%@:%@@mail/folder%@/", - [[self userContext] username], [[self userContext] username], - newFolderDBName]; - [mapping updateID: [self objectId] withURL: newURL]; - if (targetFolder) - { - parentDBFolderPath = [[targetFolder dbFolder] path]; - if (!parentDBFolderPath) - parentDBFolderPath = @""; - [dbFolder changePathTo: [NSString stringWithFormat: - @"%@/folder%@", - parentDBFolderPath, - newFolderDBName] - intoNewContainer: [targetFolder dbFolder]]; - } - else - [dbFolder changePathTo: [NSString stringWithFormat: - @"/mail/folder%@", newFolderDBName] - intoNewContainer: nil]; - } - } - else - { - nameProperty.ulPropTag = PidTagDisplayName; - nameProperty.value.lpszW = [newFolderName UTF8String]; - folderRow.lpProps = &nameProperty; - folderRow.cValues = 1; - rc = [targetFolder createFolder: &folderRow - withFID: -1 - andKey: &childKey]; - if (rc == MAPISTORE_SUCCESS) - { - newFolder = [targetFolder lookupFolder: childKey]; - - connection = [sogoObject imap4Connection]; - folderIMAPName = [connection - imap4FolderNameForURL: [sogoObject imap4URL]]; - newFolderIMAPName = [connection - imap4FolderNameForURL: [[newFolder sogoObject] imap4URL]]; - client = [connection client]; - [client select: folderIMAPName]; - - childKeys = [self messageKeys]; - max = [childKeys count]; - uids = [NSMutableArray arrayWithCapacity: max]; - for (count = 0; count < max; count++) - { - childKey = [childKeys objectAtIndex: count]; - [uids addObject: [self messageUIDFromMessageKey: childKey]]; - } - - result = [client copyUids: uids - toFolder: newFolderIMAPName]; - if ([[result objectForKey: @"result"] boolValue]) - { - if (isRecursive) - { - childKeys = [self folderKeys]; - max = [childKeys count]; - for (count = 0; count < max; count++) - { - childKey = [childKeys objectAtIndex: count]; - [[self lookupFolder: childKey] - moveCopyToFolder: newFolder - withNewName: nil - isMove: NO - isRecursive: YES - inMemCtx: memCtx]; - } - } - } - else - rc = MAPISTORE_ERROR; - } - } - [targetFolder cleanupCaches]; - } - else - rc = [super moveCopyToFolder: targetFolder withNewName: newFolderName - isMove: isMove - isRecursive: isRecursive - inMemCtx: memCtx]; - - return rc; -} - -- (MAPIStoreMessage *) createMessage -{ - SOGoCacheObject *childObject; - - [[[self context] userContext] activate]; - - childObject = [SOGoCacheObject objectWithName: [SOGoCacheObject globallyUniqueObjectId] - inContainer: sogoObject]; - return [MAPIStoreMailVolatileMessage - mapiStoreObjectWithSOGoObject: childObject - inContainer: self]; -} - -- (id) lookupMessage: (NSString *) messageKey -{ - MAPIStoreMailMessage *message; - NSArray *rawBodyData; - - message = [super lookupMessage: messageKey]; - if (message) - { - rawBodyData = [bodyData objectForKey: messageKey]; - if (rawBodyData) - [message setBodyContentFromRawData: rawBodyData]; - } - - return message; -} - -- (NSArray *) rolesForExchangeRights: (uint32_t) rights -{ - NSMutableArray *roles; - - roles = [NSMutableArray arrayWithCapacity: 6]; - if (rights & RoleOwner) - [roles addObject: SOGoMailRole_Administrator]; - if (rights & RightsCreateItems) - { - [roles addObject: SOGoRole_ObjectCreator]; - [roles addObject: SOGoMailRole_Writer]; - [roles addObject: SOGoMailRole_Poster]; - } - if (rights & RightsDeleteAll) - { - [roles addObject: SOGoRole_ObjectEraser]; - [roles addObject: SOGoRole_FolderEraser]; - [roles addObject: SOGoMailRole_Expunger]; - } - if (rights & RightsEditAll) - [roles addObject: SOGoRole_ObjectEditor]; - if (rights & RightsReadItems) - [roles addObject: SOGoRole_ObjectViewer]; - if (rights & RightsCreateSubfolders) - [roles addObject: SOGoRole_FolderCreator]; - - // [self logWithFormat: @"roles for rights %.8x = (%@)", rights, roles]; - - return roles; -} - -- (uint32_t) exchangeRightsForRoles: (NSArray *) roles -{ - uint32_t rights = 0; - - if ([roles containsObject: SOGoMailRole_Administrator]) - rights |= (RoleOwner ^ RightsAll); - if ([roles containsObject: SOGoRole_ObjectCreator]) - rights |= RightsCreateItems; - if ([roles containsObject: SOGoRole_ObjectEraser] - && [roles containsObject: SOGoRole_FolderEraser]) - rights |= RightsDeleteAll | RightsDeleteOwn; - - if ([roles containsObject: SOGoRole_ObjectEditor]) - rights |= RightsEditAll | RightsEditOwn; - if ([roles containsObject: SOGoRole_ObjectViewer]) - rights |= RightsReadItems; - if ([roles containsObject: SOGoRole_FolderCreator]) - rights |= RightsCreateSubfolders; - - if (rights != 0) - rights |= RoleNone; /* actually "folder visible" */ - - // [self logWithFormat: @"rights for roles (%@) = %.8x", roles, rights]; - - return rights; -} - -- (enum mapistore_error) preloadMessageBodiesWithKeys: (NSArray *) keys - ofTableType: (enum mapistore_table_type) tableType -{ - NSEnumerator *enumerator; - NSUInteger max; - NSString *messageKey; - MAPIStoreMailMessage *message; - NSArray* bodyContent; - - if (tableType != MAPISTORE_MESSAGE_TABLE) - return MAPISTORE_SUCCESS; - - [bodyData removeAllObjects]; - - max = [keys count]; - if (max == 0) - return MAPISTORE_SUCCESS; - - enumerator = [keys objectEnumerator]; - while ((messageKey = [enumerator nextObject])) - { - message = [self lookupMessage: messageKey]; - if (message) - { - bodyContent = [message getBodyContent]; - if (bodyContent) - { - [bodyData setObject: bodyContent forKey: messageKey]; - } - } - } - - return MAPISTORE_SUCCESS; -} - -@end - -@implementation MAPIStoreOutboxFolder - -- (enum mapistore_error) getPidTagDisplayName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [@"Outbox" asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreMailFolderTable.h b/Attic/OpenChange/MAPIStoreMailFolderTable.h deleted file mode 100644 index 5ec2c4a5b..000000000 --- a/Attic/OpenChange/MAPIStoreMailFolderTable.h +++ /dev/null @@ -1,31 +0,0 @@ -/* MAPIStoreMailFolderTable.h - this file is part of SOGo - * - * Copyright (C) 2015 Enrique J. Hernández - * - * Author: Enrique J. Hernández - * - * 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 MAPISTOREMAILFOLDERTABLE_H -#define MAPISTOREMAILFOLDERTABLE_H - -#import "MAPIStoreFolderTable.h" - -@interface MAPIStoreMailFolderTable : MAPIStoreFolderTable -@end - -#endif /* MAPISTOREMAILFOLDERTABLE_H */ diff --git a/Attic/OpenChange/MAPIStoreMailFolderTable.m b/Attic/OpenChange/MAPIStoreMailFolderTable.m deleted file mode 100644 index 542e1dc8f..000000000 --- a/Attic/OpenChange/MAPIStoreMailFolderTable.m +++ /dev/null @@ -1,42 +0,0 @@ -/* MAPIStoreMailFolderTable.m - this file is part of SOGo - * - * Copyright (C) 2015 Enrique J. Hernández - * - * 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. - */ - -#import - -#import "MAPIStoreMailFolderTable.h" -#import "MAPIStoreTypes.h" - -@implementation MAPIStoreMailFolderTable - -- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property -{ - switch(property) - { - case PR_DISPLAY_NAME: - case PR_DISPLAY_NAME_UNICODE: - return @"name"; - default: - return nil; - } -} - - -@end - diff --git a/Attic/OpenChange/MAPIStoreMailMessage.h b/Attic/OpenChange/MAPIStoreMailMessage.h deleted file mode 100644 index 580be0a6e..000000000 --- a/Attic/OpenChange/MAPIStoreMailMessage.h +++ /dev/null @@ -1,88 +0,0 @@ -/* MAPIStoreMailMessage.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTOREMAILMESSAGE_H -#define MAPISTOREMAILMESSAGE_H - -#import "MAPIStoreMessage.h" - -@class NSString; -@class NSArray; -@class NSMutableArray; -@class NSMutableDictionary; - -@class MAPIStoreAppointmentWrapper; -@class MAPIStoreMailFolder; - -@interface MAPIStoreMailMessage : MAPIStoreMessage -{ - BOOL headerSetup; - BOOL mailIsEvent; - BOOL mailIsMeetingRequest; - BOOL mailIsSharingObject; - - NSMutableArray *bodyContentKeys; - NSMutableDictionary *bodyPartsEncodings; - NSMutableDictionary *bodyPartsCharsets; - NSMutableDictionary *bodyPartsMimeTypes; - NSMutableDictionary *bodyPartsMixed; - - NSString *headerCharset; - NSString *headerMimeType; - BOOL bodySetup; - NSArray *bodyContent; - BOOL fetchedAttachments; - - MAPIStoreAppointmentWrapper *appointmentWrapper; -} - -- (NSString *) subject; - -- (enum mapistore_error) getPidTagIconIndex: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagFlagStatus: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; - -- (enum mapistore_error) getPidTagMessageFlags: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagFollowupIcon: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagImportance: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagReceivedByEmailAddress: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagSenderEmailAddress: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagDisplayTo: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagDisplayCc: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagDisplayBcc: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; - -/* batch-mode helpers */ -- (void) setBodyContentFromRawData: (NSArray *) rawContent; -- (NSArray *) getBodyContent; - -@end - -#endif /* MAPISTOREMAILMESSAGE_H */ diff --git a/Attic/OpenChange/MAPIStoreMailMessage.m b/Attic/OpenChange/MAPIStoreMailMessage.m deleted file mode 100644 index 6c20a6b04..000000000 --- a/Attic/OpenChange/MAPIStoreMailMessage.m +++ /dev/null @@ -1,2019 +0,0 @@ -/* MAPIStoreMailMessage.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 Inverse inc - * - * Author: Wolfgang Sourdeau - * Ludovic Marcotte - * - * 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. - */ - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#import "Codepages.h" -#import "NSData+MAPIStore.h" -#import "NSObject+MAPIStore.h" -#import "NSString+MAPIStore.h" -#import "MAPIStoreAppointmentWrapper.h" -#import "MAPIStoreContext.h" -#import "MAPIStoreFolder.h" -#import "MAPIStoreMailAttachment.h" -#import "MAPIStoreMailFolder.h" -#import "MAPIStoreMapping.h" -#import "MAPIStoreSamDBUtils.h" -#import "MAPIStoreSharingMessage.h" -#import "MAPIStoreTypes.h" -#import "MAPIStoreUserContext.h" - -#import "MAPIStoreMailMessage.h" - -#undef DEBUG -#include -#include -#include -#include - -#define BODY_CONTENT_TEXT 0 -#define BODY_CONTENT_HTML 1 - -@class iCalCalendar, iCalEvent; - -static Class NSExceptionK, MAPIStoreSharingMessageK; -static NSArray *acceptedMimeTypes; - -@interface NSString (MAPIStoreMIME) - -- (NSString *) _strippedBodyKey; - -@end - -@implementation NSString (MAPIStoreMIME) - -- (NSString *) _strippedBodyKey -{ - NSRange bodyRange; - NSString *strippedKey; - - bodyRange = [self rangeOfString: @"body.peek["]; - if (bodyRange.length > 0) - { - strippedKey = [self substringFromIndex: NSMaxRange (bodyRange)]; - strippedKey = [strippedKey substringToIndex: [strippedKey length] - 1]; - } - else - strippedKey = nil; - - return strippedKey; -} - -@end - -@implementation SOGoMailObject (MAPIStoreExtension) - -- (Class) mapistoreMessageClass -{ - return [MAPIStoreMailMessage class]; -} - -@end - -@implementation MAPIStoreMailMessage - -+ (void) initialize -{ - NSExceptionK = [NSException class]; - MAPIStoreSharingMessageK = [MAPIStoreSharingMessage class]; - acceptedMimeTypes = [[NSArray alloc] initWithObjects: @"text/calendar", - @"application/ics", - @"text/html", - @"text/plain", - nil]; -} - -- (id) init -{ - if ((self = [super init])) - { - bodyContentKeys = nil; - bodyPartsEncodings = nil; - bodyPartsCharsets = nil; - bodyPartsMimeTypes = nil; - bodyPartsMixed = nil; - - headerSetup = NO; - bodySetup = NO; - bodyContent = nil; - - mailIsEvent = NO; - mailIsMeetingRequest = NO; - mailIsSharingObject = NO; - headerCharset = nil; - headerMimeType = nil; - - appointmentWrapper = nil; - } - - return self; -} - -- (void) dealloc -{ - [bodyContentKeys release]; - [bodyPartsEncodings release]; - [bodyPartsCharsets release]; - [bodyPartsMimeTypes release]; - [bodyPartsMixed release]; - - [bodyContent release]; - - [headerMimeType release]; - [headerCharset release]; - [appointmentWrapper release]; - [super dealloc]; -} - -- (NSString *) subject -{ - return [sogoObject decodedSubject]; -} - -- (NSDate *) creationTime -{ - return [sogoObject date]; -} - -- (NSDate *) lastModificationTime -{ - return [sogoObject date]; -} - -- (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP - inMemCtx: (TALLOC_CTX *) memCtx -{ - BOOL listedProperties[65536]; - NSUInteger count; - uint16_t propId; - - if (mailIsSharingObject) - { - memset (listedProperties, NO, 65536 * sizeof (BOOL)); - [super getAvailableProperties: propertiesP inMemCtx: memCtx]; - for (count = 0; count < (*propertiesP)->cValues; count++) - { - propId = ((*propertiesP)->aulPropTag[count] >> 16) & 0xffff; - listedProperties[propId] = YES; - } - [MAPIStoreSharingMessage fillAvailableProperties: *propertiesP - withExclusions: listedProperties]; - return MAPISTORE_SUCCESS; - } - else - return [super getAvailableProperties: propertiesP inMemCtx: memCtx]; -} - -static NSComparisonResult -_compareBodyKeysByPriority (id entry1, id entry2, void *data) -{ - NSComparisonResult result; - NSArray *keys; - NSString *data1, *data2; - NSUInteger count1, count2; - - keys = data; - - data1 = [entry1 objectForKey: @"mimeType"]; - count1 = [keys indexOfObject: data1]; - data2 = [entry2 objectForKey: @"mimeType"]; - count2 = [keys indexOfObject: data2]; - - if (count1 == count2) - { - data1 = [entry1 objectForKey: @"key"]; - count1 = [data1 countOccurrencesOfString: @"."]; - data2 = [entry2 objectForKey: @"key"]; - count2 = [data2 countOccurrencesOfString: @"."]; - if (count1 == count2) - { - data1 = [data1 _strippedBodyKey]; - count1 = [data1 intValue]; - data2 = [data2 _strippedBodyKey]; - count2 = [data2 intValue]; - if (count1 == count2) - result = NSOrderedSame; - else if (count1 < count2) - result = NSOrderedAscending; - else - result = NSOrderedDescending; - } - else if (count1 < count2) - result = NSOrderedAscending; - else - result = NSOrderedDescending; - } - else if (count1 < count2) - result = NSOrderedAscending; - else - result = NSOrderedDescending; - - return result; -} - -- (void) _fetchHeaderData -{ - MAPIStoreSharingMessage *sharingMessage; - NSMutableArray *keys; - NSUInteger keysCount; - NSDictionary *partHeaderData, *parameters; - NSString *sharingHeader; - - keys = [NSMutableArray array]; - [sogoObject addRequiredKeysOfStructure: [sogoObject bodyStructure] - path: @"" - toArray: keys - acceptedTypes: acceptedMimeTypes - withPeek: YES]; - [keys sortUsingFunction: _compareBodyKeysByPriority context: acceptedMimeTypes]; - keysCount = [keys count]; - if (keysCount > 0) - { - NSUInteger i; - BOOL hasHtml = NO; - BOOL hasText = NO; - - bodyContentKeys = [[NSMutableArray alloc] initWithCapacity: keysCount]; - bodyPartsEncodings = [[NSMutableDictionary alloc] initWithCapacity: keysCount]; - bodyPartsCharsets = [[NSMutableDictionary alloc] initWithCapacity: keysCount]; - bodyPartsMimeTypes = [[NSMutableDictionary alloc] initWithCapacity: keysCount]; - bodyPartsMixed = [[NSMutableDictionary alloc] initWithCapacity: keysCount]; - - for (i = 0; i < keysCount; i++) - { - NSDictionary *bodyStructureKey; - NSString *key; - NSString *mimeType; - BOOL mixedPart; - NSString *strippedKey; - NSString *encoding; - NSString *charset; - NSDictionary *partParameters; - NSString *multipart; - - bodyStructureKey = [keys objectAtIndex: i]; - key = [bodyStructureKey objectForKey: @"key"]; - if (key == nil) - continue; - - [bodyContentKeys addObject: key]; - - strippedKey = [key _strippedBodyKey]; - partHeaderData = [sogoObject lookupInfoForBodyPart: strippedKey]; - - partParameters = [partHeaderData objectForKey: @"parameterList"]; - encoding = [partHeaderData objectForKey: @"encoding"]; - charset = [partParameters objectForKey: @"charset"]; - mimeType = [bodyStructureKey objectForKey: @"mimeType"]; - - /* multipart/mixed is the default type. - multipart/alternative is the only other type of multipart supported now. - */ - multipart = [bodyStructureKey objectForKey: @"multipart"]; - if ([multipart isEqualToString: @""]) - { - mixedPart = NO; - } - else - { - mixedPart = !([multipart isEqualToString: @"multipart/alternative"] || - [multipart isEqualToString: @"multipart/related"]); - } - - if (encoding) - [bodyPartsEncodings setObject: encoding forKey: key]; - if (charset) - [bodyPartsCharsets setObject: charset forKey: key]; - if (mimeType) - { - [bodyPartsMimeTypes setObject: mimeType forKey: key]; - if ([mimeType isEqualToString: @"text/plain"]) - hasText = YES; - else if ([mimeType isEqualToString: @"text/html"]) - hasHtml = YES; - } - [bodyPartsMixed setObject: [NSNumber numberWithBool: mixedPart] forKey: key]; - - if (i == 0) - { - ASSIGN (headerMimeType, mimeType); - parameters = partParameters; - } - - if (charset) - { - if (headerCharset == nil) - { - ASSIGN (headerCharset, charset); - } - else if (![headerCharset isEqualToString: charset]) - { - /* Because we have different charsets we will encode all in UTF-8 */ - ASSIGN (headerCharset, @"utf-8"); - } - } - - } - - if (!hasHtml || !hasText) - { - NSArray *bodyPartsMixedKeys = [bodyPartsMixed allKeys]; - for (i = 0; i < [keys count]; i++) - { - NSString *key = [bodyPartsMixedKeys objectAtIndex: i]; - [bodyPartsMixed setObject: [NSNumber numberWithBool: NO] forKey: key]; - } - } - - - if ([headerMimeType isEqualToString: @"text/calendar"] - || [headerMimeType isEqualToString: @"application/ics"]) - { - mailIsEvent = YES; - if ([[parameters objectForKey: @"method"] isEqualToString: @"REQUEST"]) - mailIsMeetingRequest = YES; - } - else - { - sharingHeader = [[sogoObject mailHeaders] objectForKey: @"x-ms-sharing-localtype"]; - if (sharingHeader) - { - mailIsSharingObject = YES; - /* It is difficult to subclass this in folder class, that's why - a sharing object is a proxy in a mail message */ - sharingMessage = [[MAPIStoreSharingMessage alloc] - initWithMailHeaders: [sogoObject mailHeaders] - andConnectionInfo: [[self context] connectionInfo] - fromMessage: self]; - [self addProxy: sharingMessage]; - [sharingMessage release]; - } - } - } - - headerSetup = YES; -} - -- (void) _fetchBodyData -{ - if (!headerSetup) - [self _fetchHeaderData]; - - if (!bodyContent && bodyContentKeys) - { - id result; - NSString *key; - NSEnumerator *enumerator; - NSMutableData *htmlContent; - NSMutableData *textContent; - NSStringEncoding headerEncoding; - - result = [sogoObject fetchParts: bodyContentKeys]; - result = [[result valueForKey: @"RawResponse"] objectForKey: @"fetch"]; - - htmlContent = [[NSMutableData alloc] initWithCapacity: 0]; - textContent = [[NSMutableData alloc] initWithCapacity: 0]; - - headerEncoding = [NSString stringEncodingForEncodingNamed: headerCharset]; - - enumerator = [bodyContentKeys objectEnumerator]; - while ((key = [enumerator nextObject])) - { - NSString *noPeekKey = [key stringByReplacingOccurrencesOfString: @"body.peek" - withString: @"body"]; - - NSData *content = [[result objectForKey: noPeekKey] objectForKey: @"data"]; - if (content == nil) - continue; - NSString *mimeType = [bodyPartsMimeTypes objectForKey: key]; - if (mimeType == nil) - continue; - NSString *contentEncoding = [bodyPartsEncodings objectForKey: key]; - if (contentEncoding == nil) - contentEncoding = @"7-bit"; - - /* We should provide a case for each of the types in acceptedMimeTypes */ - if (!mailIsEvent) - { - NSString *charset; - NSStringEncoding charsetEncoding; - NSString *stringValue; - BOOL html; - BOOL mixed = [[bodyPartsMixed objectForKey: key] boolValue]; - if ([mimeType isEqualToString: @"text/html"]) - { - html = YES; - } - else if ([mimeType isEqualToString: @"text/plain"]) - { - html = NO; - } - else - { - [self warnWithFormat: @"Unsupported MIME type for non-event body part: %@.", - mimeType]; - continue; - } - - content = [content bodyDataFromEncoding: contentEncoding]; - charset = [bodyPartsCharsets objectForKey: key]; - - stringValue = nil; - if (charset) - { - charsetEncoding = [NSString stringEncodingForEncodingNamed: charset]; - if ((charsetEncoding == headerEncoding) || !headerEncoding) - { - if (html) - [htmlContent appendData: content]; - else - [textContent appendData: content]; - } - else - { - stringValue = [content bodyStringFromCharset: charset]; - if (html) - [htmlContent appendData: [stringValue dataUsingEncoding: headerEncoding]]; - else - [textContent appendData: [stringValue dataUsingEncoding: headerEncoding]]; - } - - if (mixed) - { - // We must add it also to the other mail representation - if (html) - { - // TODO: html conversion to text - if (stringValue && headerEncoding) - [textContent appendData: [stringValue dataUsingEncoding: headerEncoding]]; - else - [textContent appendData: content]; - } - else - { - if (headerEncoding) - { - if (stringValue == nil) - stringValue = [content bodyStringFromCharset: charset]; - - stringValue = [stringValue stringByReplacingOccurrencesOfString: @"\n" - withString: @"
"]; - [htmlContent appendData: [stringValue dataUsingEncoding: headerEncoding]]; - } - else - { - [htmlContent appendData: content]; - } - } - } - } - else - { - /* Without charset we cannot mangle the text, so we add as it stands */ - if (html || mixed) - [htmlContent appendData: content]; - if (!html || mixed) - [textContent appendData: content]; - } - - } - else if ([mimeType isEqualToString: @"text/calendar"] || - [mimeType isEqualToString: @"application/ics"]) - { - content = [content bodyDataFromEncoding: contentEncoding]; - [textContent appendData: content]; - } - else - { - [self warnWithFormat: @"Unsupported combination for event body part. MIME type: %@", - mimeType]; - } - } - - NSArray *newBodyContent = [[NSArray alloc] initWithObjects: textContent, htmlContent, nil]; - ASSIGN (bodyContent, newBodyContent); - } - - bodySetup = YES; -} - -- (NSArray*) getBodyContent -{ - if (!bodySetup) - [self _fetchBodyData]; - return bodyContent; -} - -- (MAPIStoreAppointmentWrapper *) _appointmentWrapper -{ - NSData *textContent; - NSArray *events, *from; - iCalCalendar *calendar; - iCalEvent *event; - NSString *stringValue, *senderEmail; - MAPIStoreContext *context; - - if (!appointmentWrapper) - { - if (!bodySetup) - [self _fetchBodyData]; - - textContent = [bodyContent objectAtIndex: BODY_CONTENT_TEXT]; - stringValue = [textContent bodyStringFromCharset: headerCharset]; - calendar = [iCalCalendar parseSingleFromSource: stringValue]; - events = [calendar events]; - if ([events count] > 0) - { - event = [events objectAtIndex: 0]; - from = [sogoObject fromEnvelopeAddresses]; - if ([from count] > 0) - senderEmail = [[from objectAtIndex: 0] email]; - else - senderEmail = nil; - context = [self context]; - appointmentWrapper = [MAPIStoreAppointmentWrapper - wrapperWithICalEvent: event - andUser: [context activeUser] - andSenderEmail: senderEmail - withConnectionInfo: [context connectionInfo]]; - [appointmentWrapper retain]; - } - } - - return appointmentWrapper; -} - -- (enum mapistore_error) getPidTagChangeKey: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_SUCCESS; - NSData *changeKey; - MAPIStoreMailFolder *parentFolder; - NSString *nameInContainer; - - if (isNew) - rc = MAPISTORE_ERR_NOT_FOUND; - else - { - parentFolder = (MAPIStoreMailFolder *)[self container]; - nameInContainer = [self nameInContainer]; - changeKey = [parentFolder changeKeyForMessageWithKey: nameInContainer]; - if (!changeKey) - { - [self warnWithFormat: @"attempting to get change key" - @" by synchronising folder..."]; - [(MAPIStoreMailFolder *) container synchroniseCache]; - [parentFolder synchroniseCache]; - changeKey = [parentFolder changeKeyForMessageWithKey: nameInContainer]; - if (changeKey) - [self logWithFormat: @"got one"]; - else - { - [self errorWithFormat: @"still nothing. We crash!"]; - abort (); - } - } - *data = [changeKey asBinaryInMemCtx: memCtx]; - } - - return rc; -} - -- (enum mapistore_error) getPidTagPredecessorChangeList: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_SUCCESS; - NSData *changeList; - - if (isNew) - rc = MAPISTORE_ERR_NOT_FOUND; - else - { - changeList = [(MAPIStoreMailFolder *)[self container] - predecessorChangeListForMessageWithKey: [self nameInContainer]]; - if (!changeList) - { - [self warnWithFormat: @"attempting to get predecessor change list" - @" by synchronising folder..."]; - [(MAPIStoreMailFolder *) container synchroniseCache]; - changeList = [(MAPIStoreMailFolder *)[self container] - predecessorChangeListForMessageWithKey: [self nameInContainer]]; - if (changeList) - [self logWithFormat: @"got one"]; - else - { - [self errorWithFormat: @"still nothing. We crash!"]; - abort (); - } - } - *data = [changeList asBinaryInMemCtx: memCtx]; - } - - return rc; -} - -- (uint64_t) objectVersion -{ - uint64_t version = ULLONG_MAX; - NSString *uid, *changeNumber; - BOOL synced; - - uid = [(MAPIStoreMailFolder *) - container messageUIDFromMessageKey: [self nameInContainer]]; - if (uid) - { - changeNumber = [(MAPIStoreMailFolder *) container - changeNumberForMessageUID: uid]; - if (!changeNumber) - { - [self warnWithFormat: @"attempting to get change number" - @" by synchronising folder..."]; - [(MAPIStoreMailFolder *) container synchroniseCache]; - changeNumber = [(MAPIStoreMailFolder *) container - changeNumberForMessageUID: uid]; - if (changeNumber) - [self logWithFormat: @"got one"]; - else - { - [self warnWithFormat: @"attempting to get change number" - @" by synchronising this specific message..."]; - synced = [(MAPIStoreMailFolder *) container synchroniseCacheForUID: uid]; - if (synced) - { - changeNumber = [(MAPIStoreMailFolder *) container - changeNumberForMessageUID: uid]; - } - else - { - [self errorWithFormat: @"still nothing. We crash!"]; - abort(); - } - } - } - version = [changeNumber unsignedLongLongValue] >> 16; - } - else - abort(); - - return version; -} - -- (enum mapistore_error) getPidTagIconIndex: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - uint32_t longValue; - - if (!headerSetup) - [self _fetchHeaderData]; - - if (mailIsEvent) - [[self _appointmentWrapper] getPidTagIconIndex: data inMemCtx: memCtx]; - else - { - /* 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 mapistore_error) getPidLidResponseStatus: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, 0); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidImapDeleted: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - uint32_t longValue; - - if ([sogoObject deleted]) - longValue = 1; - else - longValue = 0; - *data = MAPILongValue (memCtx, longValue); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagSubjectPrefix: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *subject; - NSUInteger colIdx; - NSString *stringValue; - - /* As specified in [MS-OXCMAIL] 2.2.3.2.6.1, if there are three - or less characters followed by a colon at the beginning of - the subject, we can assume that's the subject prefix */ - subject = [self subject]; - colIdx = [subject rangeOfString: @":"].location; - if (colIdx != NSNotFound && colIdx < 4) - stringValue = [NSString stringWithFormat: @"%@: ", - [subject substringToIndex: colIdx]]; - else - stringValue = @""; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagNormalizedSubject: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *stringValue, *subject; - NSUInteger quoteStartIdx, quoteEndIdx, colIdx; - NSRange quoteRange; - - if (!headerSetup) - [self _fetchHeaderData]; - - subject = [self subject]; - if (mailIsMeetingRequest) - { - - /* SOGo "spices up" the invitation/update mail's subject, but - the client uses it to name the attendee's event, so we keep - only what's inside the quotes */ - quoteStartIdx = [subject rangeOfString: @"\""].location; - quoteEndIdx = [subject rangeOfString: @"\"" - options: NSBackwardsSearch].location; - if (quoteStartIdx != NSNotFound - && quoteEndIdx != NSNotFound - && quoteStartIdx != quoteEndIdx) - { - quoteRange = NSMakeRange(quoteStartIdx + 1, quoteEndIdx - quoteStartIdx - 1); - stringValue = [subject substringWithRange: quoteRange]; - } - else stringValue = subject; - } - else - { - - /* As specified in [MS-OXCMAIL] 2.2.3.2.6.1, if there are three - or less characters followed by a colon at the beginning of - the subject, we can assume that's the subject prefix */ - 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; -} - -- (enum mapistore_error) getPidLidFInvited: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getYes: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagMessageClass: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!headerSetup) - [self _fetchHeaderData]; - - if (mailIsEvent) - [[self _appointmentWrapper] getPidTagMessageClass: data - inMemCtx: memCtx]; - else if (mailIsSharingObject) - *data = talloc_strdup (memCtx, "IPM.Sharing"); - else - *data = talloc_strdup (memCtx, "IPM.Note"); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagReplyRequested: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!headerSetup) - [self _fetchHeaderData]; - - return (mailIsMeetingRequest - ? [self getYes: data inMemCtx: memCtx] - : MAPISTORE_ERR_NOT_FOUND); -} - -- (enum mapistore_error) getPidTagResponseRequested: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagReplyRequested: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagLatestDeliveryTime: (void **) data // DOUBT - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagCreationTime: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagOriginalSubmitTime: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagCreationTime: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagClientSubmitTime: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagCreationTime: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagMessageDeliveryTime: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagCreationTime: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagMessageFlags: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - 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 attachmentKeys] - count] > 0) - v |= MSGFLAG_HASATTACH; - - *data = MAPILongValue (memCtx, v); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagFlagStatus: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - 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; -} - -- (enum mapistore_error) getPidTagFollowupIcon: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - 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; -} - -- (enum mapistore_error) getPidTagSensitivity: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getLongZero: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagOriginalSensitivity: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagSensitivity: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagSentRepresentingAddressType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getSMTPAddrType: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagReceivedRepresentingAddressType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getSMTPAddrType: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagReceivedByAddressType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getSMTPAddrType: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagSenderAddressType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getSMTPAddrType: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) _getEmailAddressFromEmail: (NSString *) fullMail - inData: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NGMailAddress *ngAddress; - NSString *email; - - if (!fullMail) - fullMail = @""; - - ngAddress = [[NGMailAddressParser mailAddressParserWithString: fullMail] - parse]; - if ([ngAddress isKindOfClass: [NGMailAddress class]]) - email = [ngAddress address]; - else - email = @""; - - *data = [email asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) _getCNFromEmail: (NSString *) fullMail - inData: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NGMailAddress *ngAddress; - NSString *cn; - - if (!fullMail) - fullMail = @""; - - ngAddress = [[NGMailAddressParser mailAddressParserWithString: fullMail] - parse]; - if ([ngAddress isKindOfClass: [NGMailAddress class]]) - { - cn = [ngAddress displayName]; - - // If we don't have a displayName, we use the email address instead. This - // avoid bug #2119 - where Outlook won't display anything in the "From" field, - // nor in the recipient field if we reply to the email. - if (![cn length]) - cn = [ngAddress address]; - } - else - cn = @""; - - *data = [cn asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) _getEntryIdFromEmail: (NSString *) fullMail - inData: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *username, *cn, *email; - SOGoUserManager *mgr; - NSDictionary *contactInfos; - NGMailAddress *ngAddress; - NSData *entryId; - enum mapistore_error rc; - - if (fullMail) - { - ngAddress = [[NGMailAddressParser mailAddressParserWithString: fullMail] - parse]; - if ([ngAddress isKindOfClass: [NGMailAddress class]]) - { - email = [ngAddress address]; - cn = [ngAddress displayName]; - } - else - { - email = fullMail; - cn = @""; - } - - mgr = [SOGoUserManager sharedUserManager]; - contactInfos = [mgr contactInfosForUserWithUIDorEmail: email]; - if (contactInfos) - { - username = [contactInfos objectForKey: @"sAMAccountName"]; - entryId = MAPIStoreInternalEntryId([[self context] connectionInfo], username); - } - else - entryId = MAPIStoreExternalEntryId (cn, email); - - *data = [entryId asBinaryInMemCtx: memCtx]; - - rc = MAPISTORE_SUCCESS; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidTagSenderEmailAddress: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getEmailAddressFromEmail: [sogoObject from] - inData: data - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagSenderName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getCNFromEmail: [sogoObject from] - inData: data - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagSenderEntryId: (void **) data inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getEntryIdFromEmail: [sogoObject from] - inData: data - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagOriginalAuthorName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagSenderEmailAddress: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagSentRepresentingEmailAddress: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagSenderEmailAddress: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagSentRepresentingName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagSenderName: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagSentRepresentingEntryId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagSenderEntryId: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagReceivedByEmailAddress: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getEmailAddressFromEmail: [sogoObject to] - inData: data - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagReceivedByName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getCNFromEmail: [sogoObject to] - inData: data - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagReceivedByEntryId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getEntryIdFromEmail: [sogoObject to] - inData: data - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagReceivedRepresentingName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagReceivedByName: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagReceivedRepresentingEmailAddress: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagReceivedByEmailAddress: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagReceivedRepresentingEntryId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagReceivedByEntryId: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagDisplayTo: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [[sogoObject to] asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagOriginalDisplayTo: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagDisplayTo: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagDisplayCc: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *stringValue; - - stringValue = [sogoObject cc]; - if (!stringValue) - stringValue = @""; - - *data = [stringValue asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagOriginalDisplayCc: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagDisplayCc: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagDisplayBcc: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getEmptyString: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagOriginalDisplayBcc: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagDisplayBcc: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidNameContentType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [@"message/rfc822" asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagImportance: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - 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; -} - -- (enum mapistore_error) getPidTagInternetCodepage: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSNumber *codepage; - - codepage = [Codepages getCodepageFromName: headerCharset]; - if (!codepage) - { - [self warnWithFormat: @"Couldn't find codepage from `%@`. " - @"Using UTF-8 by default", headerCharset]; - codepage = [Codepages getCodepageFromName: @"utf-8"]; - } - - *data = MAPILongValue(memCtx, [codepage intValue]); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagBody: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSData *textContent; - enum mapistore_error rc; - - if (!bodySetup) - [self _fetchBodyData]; - - if (!bodyContent) - { - *data = NULL; - return MAPISTORE_ERR_NOT_FOUND; - } - - if (mailIsEvent) - { - rc = [[self _appointmentWrapper] getPidTagBody: data - inMemCtx: memCtx]; - } - else - { - textContent = [bodyContent objectAtIndex: BODY_CONTENT_TEXT]; - if ([textContent length]) - { - NSString *stringValue = [textContent bodyStringFromCharset: headerCharset]; - *data = [stringValue asUnicodeInMemCtx: memCtx]; - rc = MAPISTORE_SUCCESS; - } - else - { - *data = NULL; - rc = MAPISTORE_ERR_NOT_FOUND; - } - } - - return rc; -} - -- (enum mapistore_error) getPidTagHtml: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSData *htmlContent; - enum mapistore_error rc; - - if (!bodySetup) - [self _fetchBodyData]; - - if (!bodyContent || mailIsEvent) - { - *data = NULL; - return MAPISTORE_ERR_NOT_FOUND; - } - - htmlContent = [bodyContent objectAtIndex: BODY_CONTENT_HTML] ; - - if ([htmlContent length]) - { - *data = [htmlContent asBinaryInMemCtx: memCtx]; - rc = MAPISTORE_SUCCESS; - } - else - { - *data = NULL; - rc = MAPISTORE_ERR_NOT_FOUND; - } - - return rc; -} - -- (enum mapistore_error) getPidTagRtfCompressed: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = NULL; - - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidTagRtfInSync: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getNo: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagInternetMessageId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [[sogoObject messageId] asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagReadReceiptRequested: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getNo: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidGlobalObjectId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!headerSetup) - [self _fetchHeaderData]; - - return (mailIsEvent - ? [[self _appointmentWrapper] getPidLidGlobalObjectId: data - inMemCtx: memCtx] - : MAPISTORE_ERR_NOT_FOUND); -} - -- (enum mapistore_error) getPidLidCleanGlobalObjectId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!headerSetup) - [self _fetchHeaderData]; - - return (mailIsEvent - ? [[self _appointmentWrapper] getPidLidCleanGlobalObjectId: data - inMemCtx: memCtx] - : MAPISTORE_ERR_NOT_FOUND); -} - -- (enum mapistore_error) getPidLidServerProcessed: (void **) data inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!headerSetup) - [self _fetchHeaderData]; - - return (mailIsEvent - ? [[self _appointmentWrapper] getPidLidServerProcessed: data - inMemCtx: memCtx] - : MAPISTORE_ERR_NOT_FOUND); -} - -- (enum mapistore_error) getPidLidServerProcessingActions: (void **) data inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!headerSetup) - [self _fetchHeaderData]; - - return (mailIsEvent - ? [[self _appointmentWrapper] getPidLidServerProcessingActions: data - inMemCtx: memCtx] - : MAPISTORE_ERR_NOT_FOUND); -} - -- (enum mapistore_error) getPidTagProcessed: (void **) data inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - - if (!headerSetup) - [self _fetchHeaderData]; - - if (mailIsEvent) - rc = [self getYes: data inMemCtx: memCtx]; - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -// - (enum mapistore_error) getPidLidServerProcessed: (void **) data -// inMemCtx: (TALLOC_CTX *) memCtx -// { -// if (!headerSetup) -// [self _fetchHeaderData]; - -// return (mailIsEvent -// ? [[self _appointmentWrapper] getPidLidServerProcessed: data -// inMemCtx: memCtx] -// : MAPISTORE_ERR_NOT_FOUND); -// } - -- (enum mapistore_error) getPidLidPrivate: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!headerSetup) - [self _fetchHeaderData]; - - return (mailIsEvent - ? [[self _appointmentWrapper] getPidLidPrivate: data - inMemCtx: memCtx] - : [self getNo: data inMemCtx: memCtx]); -} - -- (enum mapistore_error) getPidTagMessageEditorFormat: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - uint32_t format; - - if (!headerSetup) - [self _fetchHeaderData]; - - if ([headerMimeType isEqualToString: @"text/plain"]) - format = EDITOR_FORMAT_PLAINTEXT; - else if ([headerMimeType isEqualToString: @"text/html"]) - format = EDITOR_FORMAT_HTML; - else - format = 0; /* EDITOR_FORMAT_DONTKNOW */ - - *data = MAPILongValue (memCtx, format); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidReminderSet: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getNo: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidUseTnef: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getNo: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidRemoteStatus: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getLongZero: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidAgingDontAgeMe: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getYes: data inMemCtx: memCtx]; -} - -/* event getters */ -- (enum mapistore_error) getPidTagStartDate: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!headerSetup) - [self _fetchHeaderData]; - - return (mailIsEvent - ? [[self _appointmentWrapper] getPidTagStartDate: data inMemCtx: memCtx] - : MAPISTORE_ERR_NOT_FOUND); -} - -- (enum mapistore_error) getPidLidAppointmentMessageClass: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_SUCCESS; - - if (!headerSetup) - [self _fetchHeaderData]; - - if (mailIsEvent) - *data = talloc_strdup (memCtx, "IPM.Appointment"); - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidLidAppointmentStartWhole: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!headerSetup) - [self _fetchHeaderData]; - - return (mailIsEvent - ? [[self _appointmentWrapper] getPidLidAppointmentStartWhole: data - inMemCtx: memCtx] - : MAPISTORE_ERR_NOT_FOUND); -} - -- (enum mapistore_error) getPidLidCommonStart: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!headerSetup) - [self _fetchHeaderData]; - - return (mailIsEvent - ? [[self _appointmentWrapper] getPidLidCommonStart: data - inMemCtx: memCtx] - : MAPISTORE_ERR_NOT_FOUND); -} - -- (enum mapistore_error) getPidTagEndDate: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!headerSetup) - [self _fetchHeaderData]; - - return (mailIsEvent - ? [[self _appointmentWrapper] getPidTagEndDate: data inMemCtx: memCtx] - : MAPISTORE_ERR_NOT_FOUND); -} - -- (enum mapistore_error) getPidLidAppointmentEndWhole: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!headerSetup) - [self _fetchHeaderData]; - - return (mailIsEvent - ? [[self _appointmentWrapper] getPidLidAppointmentEndWhole: data - inMemCtx: memCtx] - : MAPISTORE_ERR_NOT_FOUND); -} - -- (enum mapistore_error) getPidLidCommonEnd: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!headerSetup) - [self _fetchHeaderData]; - - return (mailIsEvent - ? [[self _appointmentWrapper] getPidLidCommonEnd: data - inMemCtx: memCtx] - : MAPISTORE_ERR_NOT_FOUND); -} - -- (enum mapistore_error) getPidLidAppointmentDuration: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!headerSetup) - [self _fetchHeaderData]; - - return (mailIsEvent - ? [[self _appointmentWrapper] getPidLidAppointmentDuration: data - inMemCtx: memCtx] - : MAPISTORE_ERR_NOT_FOUND); -} - -- (enum mapistore_error) getPidLidAppointmentSubType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!headerSetup) - [self _fetchHeaderData]; - - return (mailIsEvent - ? [[self _appointmentWrapper] getPidLidAppointmentSubType: data - inMemCtx: memCtx] - : MAPISTORE_ERR_NOT_FOUND); -} - -- (enum mapistore_error) getPidLidBusyStatus: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!headerSetup) - [self _fetchHeaderData]; - - return (mailIsEvent - ? [[self _appointmentWrapper] getPidLidBusyStatus: data - inMemCtx: memCtx] - : MAPISTORE_ERR_NOT_FOUND); -} - -- (enum mapistore_error) getPidLidLocation: (void **) data // LOCATION - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!headerSetup) - [self _fetchHeaderData]; - - return (mailIsEvent - ? [[self _appointmentWrapper] getPidLidLocation: data - inMemCtx: memCtx] - : MAPISTORE_ERR_NOT_FOUND); -} - -- (enum mapistore_error) getPidLidIsRecurring: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!headerSetup) - [self _fetchHeaderData]; - - return (mailIsEvent - ? [[self _appointmentWrapper] getPidLidIsRecurring: data - inMemCtx: memCtx] - : MAPISTORE_ERR_NOT_FOUND); -} - -- (enum mapistore_error) getPidLidRecurring: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!headerSetup) - [self _fetchHeaderData]; - - return (mailIsEvent - ? [[self _appointmentWrapper] getPidLidRecurring: data - inMemCtx: memCtx] - : MAPISTORE_ERR_NOT_FOUND); -} - -- (enum mapistore_error) getPidLidAppointmentRecur: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!headerSetup) - [self _fetchHeaderData]; - - return (mailIsEvent - ? [[self _appointmentWrapper] getPidLidAppointmentRecur: data - inMemCtx: memCtx] - : MAPISTORE_ERR_NOT_FOUND); -} - -- (enum mapistore_error) getPidTagOwnerAppointmentId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!headerSetup) - [self _fetchHeaderData]; - - return (mailIsEvent - ? [[self _appointmentWrapper] getPidTagOwnerAppointmentId: data - inMemCtx: memCtx] - : MAPISTORE_ERR_NOT_FOUND); -} - -- (enum mapistore_error) getPidLidMeetingType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!headerSetup) - [self _fetchHeaderData]; - - return (mailIsEvent - ? [[self _appointmentWrapper] getPidLidMeetingType: data - inMemCtx: memCtx] - : MAPISTORE_ERR_NOT_FOUND); -} - -- (enum mapistore_error) getPidTagTransportMessageHeaders: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSDictionary *mailHeaders; - NSEnumerator *keyEnumerator; - NSMutableArray *headers; - NGMimeMessageGenerator *g; - NSString *headerKey, *fullHeader, *headerGenerated; - id headerValue; - NSData *headerData; - - /* Let's encode each mail header and put them on 'headers' array */ - mailHeaders = [sogoObject mailHeaders]; - headers = [NSMutableArray arrayWithCapacity: [mailHeaders count]]; - - g = [[NGMimeMessageGenerator alloc] init]; - keyEnumerator = [mailHeaders keyEnumerator]; - while ((headerKey = [keyEnumerator nextObject])) - { - headerValue = [mailHeaders objectForKey: headerKey]; - - headerData = [g generateDataForHeaderField: headerKey value: headerValue]; - headerGenerated = [[NSString alloc] initWithData: headerData encoding:NSUTF8StringEncoding]; - fullHeader = [NSString stringWithFormat:@"%@: %@", headerKey, headerGenerated]; - [headerGenerated release]; - - [headers addObject: fullHeader]; - } - [g release]; - - *data = [[headers componentsJoinedByString:@"\n"] asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (void) getMessageData: (struct mapistore_message **) dataPtr - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSArray *addresses; - NSString *addressMethods[] = { @"fromEnvelopeAddresses", - @"toEnvelopeAddresses", - @"ccEnvelopeAddresses", - @"bccEnvelopeAddresses" }; - enum ulRecipClass addressTypes[] = { MAPI_ORIG, MAPI_TO, - MAPI_CC, MAPI_BCC }; - NSUInteger arrayCount, count, recipientStart, max, p; - NGImap4EnvelopeAddress *currentAddress; - NSString *username, *cn, *email; - NSData *entryId; - NSDictionary *contactInfos; - SOGoUserManager *mgr; - struct mapistore_message *msgData; - struct mapistore_message_recipient *recipient; - - [super getMessageData: &msgData inMemCtx: memCtx]; - - if (!headerSetup) - [self _fetchHeaderData]; - - if (mailIsEvent) - [[self _appointmentWrapper] fillMessageData: msgData - inMemCtx: memCtx]; - else - { - mgr = [SOGoUserManager sharedUserManager]; - - /* Retrieve recipients from the message */ - - msgData->columns = set_SPropTagArray (msgData, 9, - PR_OBJECT_TYPE, - PR_DISPLAY_TYPE, - PR_7BIT_DISPLAY_NAME_UNICODE, - PR_SMTP_ADDRESS_UNICODE, - PR_SEND_INTERNET_ENCODING, - PR_RECIPIENT_DISPLAY_NAME_UNICODE, - PR_RECIPIENT_FLAGS, - PR_RECIPIENT_ENTRYID, - PR_RECIPIENT_TRACKSTATUS); - - msgData->recipients_count = 0; - msgData->recipients = NULL; - - recipientStart = 0; - - for (arrayCount = 0; arrayCount < 4; arrayCount++) - { - addresses = [sogoObject performSelector: NSSelectorFromString (addressMethods[arrayCount])]; - max = [addresses count]; - if (max > 0) - { - msgData->recipients_count += max; - msgData->recipients = talloc_realloc (msgData, msgData->recipients, struct mapistore_message_recipient, msgData->recipients_count); - - for (count = 0; count < max; count++) - { - recipient = msgData->recipients + recipientStart; - currentAddress = [addresses objectAtIndex: count]; - cn = [currentAddress personalName]; - email = [currentAddress baseEMail]; - if ([cn length] == 0) - cn = email; - contactInfos = [mgr contactInfosForUserWithUIDorEmail: email]; - - if (contactInfos) - { - username = [contactInfos objectForKey: @"sAMAccountName"]; - recipient->username = [username asUnicodeInMemCtx: msgData]; - entryId = MAPIStoreInternalEntryId ([[self context] connectionInfo], username); - } - else - { - recipient->username = NULL; - entryId = MAPIStoreExternalEntryId (cn, email); - } - recipient->type = addressTypes[arrayCount]; - - /* properties */ - p = 0; - recipient->data = talloc_array (msgData, void *, msgData->columns->cValues); - memset (recipient->data, 0, msgData->columns->cValues * sizeof (void *)); - - // PR_OBJECT_TYPE = MAPI_MAILUSER (see MAPI_OBJTYPE) - recipient->data[p] = MAPILongValue (msgData, MAPI_MAILUSER); - p++; - - // PR_DISPLAY_TYPE = DT_MAILUSER (see MS-NSPI) - recipient->data[p] = MAPILongValue (msgData, 0); - p++; - - // PR_7BIT_DISPLAY_NAME_UNICODE - recipient->data[p] = [cn asUnicodeInMemCtx: msgData]; - p++; - - // PR_SMTP_ADDRESS_UNICODE - recipient->data[p] = [email asUnicodeInMemCtx: msgData]; - p++; - - // PR_SEND_INTERNET_ENCODING = 0x00060000 (plain text, see OXCMAIL) - recipient->data[p] = MAPILongValue (msgData, 0x00060000); - p++; - - // PR_RECIPIENT_DISPLAY_NAME_UNICODE - recipient->data[p] = [cn asUnicodeInMemCtx: msgData]; - p++; - - // PR_RECIPIENT_FLAGS - recipient->data[p] = MAPILongValue (msgData, 0x01); - p++; - - // PR_RECIPIENT_ENTRYID - recipient->data[p] = [entryId asBinaryInMemCtx: msgData]; - p++; - - // PR_RECIPIENT_TRACKSTATUS - recipient->data[p] = MAPILongValue (msgData, 0x00); - p++; - - recipientStart++; - } - } - } - } - *dataPtr = msgData; -} - -- (void) _fetchAttachmentPartsInBodyInfo: (NSDictionary *) bodyInfo - withPrefix: (NSString *) keyPrefix -{ - NSArray *parts; - NSUInteger count, max; - - if ([[bodyInfo filename] length] > 0) - { - if ([keyPrefix length] == 0) - keyPrefix = @"0"; - [attachmentParts setObject: bodyInfo - forKey: keyPrefix]; - } - else - { - if ([keyPrefix length] > 0) - keyPrefix = [NSString stringWithFormat: @"%@/", keyPrefix]; - parts = [bodyInfo objectForKey: @"parts"]; - max = [parts count]; - for (count = 0; count < max; count++) - [self _fetchAttachmentPartsInBodyInfo: [parts objectAtIndex: count] - withPrefix: [NSString stringWithFormat: @"%@%d", - keyPrefix, count + 1]]; - } -} - -- (NSArray *) attachmentKeysMatchingQualifier: (EOQualifier *) qualifier - andSortOrderings: (NSArray *) sortOrderings -{ - [self _fetchAttachmentPartsInBodyInfo: [sogoObject bodyStructure] - withPrefix: @""]; - - return [super attachmentKeysMatchingQualifier: qualifier - andSortOrderings: sortOrderings]; -} - -- (id) lookupAttachment: (NSString *) childKey -{ - MAPIStoreMailAttachment *attachment; - SOGoMailBodyPart *currentPart; - NSArray *keyParts; - NSUInteger count, max; - - attachment = nil; - - keyParts = [childKey componentsSeparatedByString: @"/"]; - max = [keyParts count]; - if (max > 0) - { - [[self userContext] activate]; - - currentPart = [sogoObject lookupName: [keyParts objectAtIndex: 0] - inContext: nil - acquire: NO]; - if ([currentPart isKindOfClass: NSExceptionK]) - currentPart = nil; - - for (count = 1; currentPart && count < max; count++) - { - [parentContainersBag addObject: currentPart]; - currentPart = [currentPart lookupName: [keyParts objectAtIndex: count] - inContext: nil - acquire: NO]; - if ([currentPart isKindOfClass: NSExceptionK]) - currentPart = nil; - } - - if (currentPart) - { - attachment = [MAPIStoreMailAttachment - mapiStoreObjectInContainer: self]; - [attachment setBodyPart: currentPart]; - [attachment setBodyInfo: [attachmentParts objectForKey: childKey]]; - [attachment setAID: [[self attachmentKeys] indexOfObject: childKey]]; - } - } - - return attachment; -} - -- (enum mapistore_error) setReadFlag: (uint8_t) flag -{ - /* TODO: notifications should probably be emitted from here */ - if (flag & CLEAR_READ_FLAG) - [properties setObject: [NSNumber numberWithBool: NO] forKey: @"read_flag_set"]; - else - [properties setObject: [NSNumber numberWithBool: YES] forKey: @"read_flag_set"]; - - return MAPISTORE_SUCCESS; -} - -- (void) setBodyContentFromRawData: (NSArray *) rawContent -{ - if (!headerSetup) - [self _fetchHeaderData]; - - ASSIGN (bodyContent, rawContent); - bodySetup = YES; -} - -- (MAPIStoreSharingMessage *) _sharingObject -{ - /* Get the sharing object if available */ - NSUInteger i, max; - id proxy; - - max = [proxies count]; - for (i = 0; i < max; i++) { - proxy = [proxies objectAtIndex: i]; - if ([proxy isKindOfClass: MAPIStoreSharingMessageK]) - return proxy; - } - return nil; -} - -- (void) save: (TALLOC_CTX *) memCtx -{ - BOOL modified = NO; - BOOL seen, storedSeenFlag; - NSNumber *value; - NSString *imapFlag = @"\\Seen"; - - value = [properties objectForKey: MAPIPropertyKey (PR_FLAG_STATUS)]; - if (value) - { - /* We don't handle the concept of "Follow Up" */ - if ([value intValue] == 2) - [sogoObject addFlags: @"\\Flagged"]; - else /* 0: unflagged, 1: follow up complete */ - [sogoObject removeFlags: @"\\Flagged"]; - - modified = YES; - } - - /* Manage seen flag on save */ - value = [properties objectForKey: @"read_flag_set"]; - if (value) - { - seen = [value boolValue]; - storedSeenFlag = [[[sogoObject fetchCoreInfos] objectForKey: @"flags"] containsObject: @"seen"]; - /* We modify the flags anyway to generate a new change number */ - if (seen) - { - if (storedSeenFlag) - [sogoObject removeFlags: imapFlag]; - [sogoObject addFlags: imapFlag]; - } - else - { - if (!storedSeenFlag) - [sogoObject addFlags: imapFlag]; - [sogoObject removeFlags: imapFlag]; - } - modified = YES; - } - - if (modified) - [(MAPIStoreMailFolder *)[self container] synchroniseCache]; - - if (mailIsSharingObject) - [[self _sharingObject] saveWithMessage: self - andSOGoObject: sogoObject]; - -} - -@end diff --git a/Attic/OpenChange/MAPIStoreMailMessageTable.h b/Attic/OpenChange/MAPIStoreMailMessageTable.h deleted file mode 100644 index 8efa43c16..000000000 --- a/Attic/OpenChange/MAPIStoreMailMessageTable.h +++ /dev/null @@ -1,35 +0,0 @@ -/* MAPIStoreMailMessageTable.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -#ifndef MAPISTOREMAILMESSAGETABLE_H -#define MAPISTOREMAILMESSAGETABLE_H - -#import "MAPIStoreMessageTable.h" - -@interface MAPIStoreMailMessageTable : MAPIStoreMessageTable -{ - BOOL fetchedCoreInfos; -} - -@end - -#endif /* MAPISTOREMAILMESSAGETABLE_H */ diff --git a/Attic/OpenChange/MAPIStoreMailMessageTable.m b/Attic/OpenChange/MAPIStoreMailMessageTable.m deleted file mode 100644 index 2375ca39b..000000000 --- a/Attic/OpenChange/MAPIStoreMailMessageTable.m +++ /dev/null @@ -1,359 +0,0 @@ -/* MAPIStoreMailMessageTable.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -#import -#import -#import -#import -#import -#import -#import -#import - -#import -#import -#import - -#import "MAPIStoreContext.h" -#import "MAPIStoreMailFolder.h" -#import "MAPIStoreMailMessage.h" -#import "MAPIStoreTypes.h" -#import "NSData+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreMailMessageTable.h" - -#undef DEBUG -#include -#include - -@implementation MAPIStoreMailMessageTable - -static Class MAPIStoreMailMessageK, NSDataK, NSStringK; - -+ (void) initialize -{ - MAPIStoreMailMessageK = [MAPIStoreMailMessage class]; - NSDataK = [NSData class]; - NSStringK = [NSString class]; -} - -+ (Class) childObjectClass -{ - return MAPIStoreMailMessageK; -} - -- (id) init -{ - if ((self = [super init])) - { - ASSIGN (sortOrderings, [NSArray arrayWithObject: @"ARRIVAL"]); - fetchedCoreInfos = NO; - } - - return self; -} - -- (void) cleanupCaches -{ - [(MAPIStoreMailFolder *) container synchroniseCache]; - fetchedCoreInfos = NO; - [super cleanupCaches]; -} - -- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property -{ - static NSMutableDictionary *knownProperties = nil; - - if (!knownProperties) - { - knownProperties = [NSMutableDictionary new]; - [knownProperties setObject: @"DATE" - forKey: MAPIPropertyKey (PR_CLIENT_SUBMIT_TIME)]; - [knownProperties setObject: @"DATE" - forKey: MAPIPropertyKey (PR_MESSAGE_DELIVERY_TIME)]; - [knownProperties setObject: @"MESSAGE-ID" - forKey: MAPIPropertyKey (PR_INTERNET_MESSAGE_ID_UNICODE)]; - } - - return [knownProperties objectForKey: MAPIPropertyKey (property)]; -} - -/* restrictions */ - -- (MAPIRestrictionState) evaluatePropertyRestriction: (struct mapi_SPropertyRestriction *) res - intoQualifier: (EOQualifier **) qualifier -{ - MAPIRestrictionState rc; - id value; - NSNumber *modseq; - - value = NSObjectFromMAPISPropValue (&res->lpProp); - switch ((uint32_t) res->ulPropTag) - { - case PR_MESSAGE_CLASS_UNICODE: - if ([value isEqualToString: @"IPM.Note"]) - rc = MAPIRestrictionStateAlwaysTrue; - else - rc = MAPIRestrictionStateAlwaysFalse; - break; - - case PidLidAppointmentStartWhole: - case PidLidAppointmentEndWhole: - case PidLidRecurring: - //[self logWithFormat: @"apt restriction on mail folder?"]; - rc = MAPIRestrictionStateAlwaysFalse; - break; - - case PidLidAutoProcessState: - if ([value intValue] == 0) - rc = MAPIRestrictionStateAlwaysTrue; - else - rc = MAPIRestrictionStateAlwaysFalse; - break; - - case PR_SEARCH_KEY: - rc = MAPIRestrictionStateAlwaysFalse; - break; - - case 0x0fff00fb: /* PR_ENTRY_ID in PtyServerId form */ - case 0x0ff600fb: - /* resProperty: struct mapi_SPropertyRestriction - relop : 0x04 (4) - ulPropTag : UNKNOWN_ENUM_VALUE (0xFF600FB) - lpProp: struct mapi_SPropValue - ulPropTag : UNKNOWN_ENUM_VALUE (0xFF600FB) - value : union mapi_SPropValue_CTR(case 251) - bin : SBinary_short cb=21 -[0000] 01 01 00 1A 00 00 00 00 00 9C 83 E8 0F 00 00 00 ........ ........ -[0010] 00 00 00 00 00 ..... */ - rc = MAPIRestrictionStateAlwaysFalse; - break; - - case PidTagConversationKey: - rc = MAPIRestrictionStateAlwaysFalse; - break; - - case PidTagChangeNumber: - { - value = [NSString stringWithFormat: @"0x%.16llx", [value unsignedLongLongValue]]; - modseq = [(MAPIStoreMailFolder *) - container modseqFromMessageChangeNumber: value]; - //[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]]; - //[self logWithFormat: @" modseq: %.16lx", [modseq unsignedLongLongValue]]; - if (modseq) - { - if (res->relop == RELOP_GT) - modseq = [NSNumber numberWithUnsignedLongLong: - [modseq unsignedLongLongValue] + 1]; - - } - else - modseq = [NSNumber numberWithUnsignedLongLong: 0]; - - if (res->relop == RELOP_GT || res->relop == RELOP_GE) - { - *qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"MODSEQ" - operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo - value: modseq]; - [*qualifier autorelease]; - rc = MAPIRestrictionStateNeedsEval; - } - else - { - /* Ignore other operations as IMAP only support MODSEQ >= X */ - [self warnWithFormat: @"Ignoring '%@' as only supported operators are > and >=", - NSStringFromSelector ([self operatorFromRestrictionOperator: res->relop])]; - rc = MAPIRestrictionStateAlwaysTrue; - } - } - break; - - default: - rc = [super evaluatePropertyRestriction: res intoQualifier: qualifier]; - } - - return rc; -} - -- (MAPIRestrictionState) evaluateContentRestriction: (struct mapi_SContentRestriction *) res - intoQualifier: (EOQualifier **) qualifier -{ - MAPIRestrictionState rc; - id value; - - value = NSObjectFromMAPISPropValue (&res->lpProp); - if ([value isKindOfClass: NSDataK]) - { - value = [[NSString alloc] initWithData: value - encoding: NSUTF8StringEncoding]; - [value autorelease]; - } - else if (![value isKindOfClass: NSStringK]) - [NSException raise: @"MAPIStoreTypeConversionException" - format: @"unhandled content restriction for class '%@'", - NSStringFromClass ([value class])]; - - switch (res->ulPropTag) - { - case PR_MESSAGE_CLASS_UNICODE: - if ([value isEqualToString: @"IPM.Note"]) - rc = MAPIRestrictionStateAlwaysTrue; - else - rc = MAPIRestrictionStateAlwaysFalse; - break; - case PidTagConversationKey: - rc = MAPIRestrictionStateAlwaysFalse; - break; - default: - rc = [super evaluateContentRestriction: res intoQualifier: qualifier]; - } - - return rc; -} - -- (MAPIRestrictionState) evaluateExistRestriction: (struct mapi_SExistRestriction *) res - intoQualifier: (EOQualifier **) qualifier -{ - MAPIRestrictionState rc; - - switch (res->ulPropTag) - { - case PR_MESSAGE_CLASS_UNICODE: - rc = MAPIRestrictionStateAlwaysFalse; - break; - case PR_MESSAGE_DELIVERY_TIME: - rc = MAPIRestrictionStateAlwaysTrue; - break; - case PR_CLIENT_SUBMIT_TIME: - rc = MAPIRestrictionStateAlwaysTrue; - break; - case PR_PROCESSED: - rc = MAPIRestrictionStateAlwaysFalse; - break; - default: - rc = [super evaluateExistRestriction: res intoQualifier: qualifier]; - } - - return rc; -} - -/* sorting */ - -- (NSString *) _sortIdentifierForProperty: (enum MAPITAGS) property -{ - static NSMutableDictionary *knownProperties = nil; - - if (!knownProperties) - { - knownProperties = [NSMutableDictionary new]; - /* ARRIVAL, CC */ - [knownProperties setObject: @"DATE" - forKey: MAPIPropertyKey (PR_CLIENT_SUBMIT_TIME)]; - [knownProperties setObject: @"DATE" - forKey: MAPIPropertyKey (PR_MESSAGE_DELIVERY_TIME)]; - [knownProperties setObject: @"FROM" - forKey: MAPIPropertyKey (PR_SENT_REPRESENTING_NAME_UNICODE)]; - [knownProperties setObject: @"SIZE" - forKey: MAPIPropertyKey (PR_MESSAGE_SIZE)]; - [knownProperties setObject: @"SIZE" - forKey: MAPIPropertyKey (PidLidRemoteTransferSize)]; - [knownProperties setObject: @"SUBJECT" - forKey: MAPIPropertyKey (PR_NORMALIZED_SUBJECT_UNICODE)]; - [knownProperties setObject: @"TO" - forKey: MAPIPropertyKey (PR_DISPLAY_TO_UNICODE)]; - } - - return [knownProperties objectForKey: MAPIPropertyKey (property)]; -} - -- (void) setSortOrder: (const struct SSortOrderSet *) set -{ - NSMutableArray *newSortOrderings; - NSMutableString *newSortOrdering; - struct SSortOrder *sortOrder; - NSString *sortIdentifier; - const char *propName; - uint16_t count; - - if (set) - { - /* TODO: */ - if (set->cCategories > 0) - [self errorWithFormat: @"we don't handle sort categories yet"]; - - newSortOrderings = [NSMutableArray array]; - - for (count = 0; count < set->cSorts; count++) - { - sortOrder = set->aSort + count; - sortIdentifier - = [self _sortIdentifierForProperty: sortOrder->ulPropTag]; - if (sortIdentifier) - { - newSortOrdering = [NSMutableString string]; - if (sortOrder->ulOrder == TABLE_SORT_DESCEND) - [newSortOrdering appendString: @" REVERSE"]; - else if (sortOrder->ulOrder == TABLE_SORT_MAXIMUM_CATEGORY) - [self errorWithFormat: @"TABLE_SORT_MAXIMUM_CATEGORY is not handled"]; - [newSortOrdering appendFormat: @" %@", sortIdentifier]; - [newSortOrderings addObject: [newSortOrdering substringFromIndex: 1]]; - } - else - { - propName = get_proptag_name (sortOrder->ulPropTag); - if (!propName) - propName = ""; - [self errorWithFormat: - @"sort unhandled for property: %s (0x%.8x)", - propName, sortOrder->ulPropTag]; - } - } - if ([newSortOrderings count] > 0) - ASSIGN (sortOrderings, newSortOrderings); - else - ASSIGN (sortOrderings, [NSArray arrayWithObject: @"ARRIVAL"]); - //[self logWithFormat: @"new sort orderings: '%@'", sortOrderings]; - } - else - ASSIGN (sortOrderings, [NSArray arrayWithObject: @"ARRIVAL"]); - - [self cleanupCaches]; -} - -- (enum mapistore_error) getRow: (struct mapistore_property_data **) dataP - withRowID: (uint32_t) rowId - andQueryType: (enum mapistore_query_type) queryType - inMemCtx: (TALLOC_CTX *) memCtx -{ - if (!fetchedCoreInfos) - { - fetchedCoreInfos = YES; - [(SOGoMailFolder *) [(MAPIStoreMailFolder *) container sogoObject] - prefetchCoreInfosForMessageKeys: [self restrictedChildKeys]]; - } - - return [super getRow: dataP withRowID: rowId - andQueryType: queryType inMemCtx: memCtx]; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreMailVolatileMessage.h b/Attic/OpenChange/MAPIStoreMailVolatileMessage.h deleted file mode 100644 index 417faeff6..000000000 --- a/Attic/OpenChange/MAPIStoreMailVolatileMessage.h +++ /dev/null @@ -1,34 +0,0 @@ -/* MAPIStoreMailVolatileMessage.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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 MAPISTOREMAILVOLATILEMESSAGE_H -#define MAPISTOREMAILVOLATILEMESSAGE_H - -#import "MAPIStoreMessage.h" - -@interface MAPIStoreMailVolatileMessage : MAPIStoreMessage - -- (enum mapistore_error) submitWithFlags: (enum SubmitFlags) flags; - -@end - -#endif /* MAPISTOREMAILVOLATILEMESSAGE_H */ diff --git a/Attic/OpenChange/MAPIStoreMailVolatileMessage.m b/Attic/OpenChange/MAPIStoreMailVolatileMessage.m deleted file mode 100644 index 36c3179e7..000000000 --- a/Attic/OpenChange/MAPIStoreMailVolatileMessage.m +++ /dev/null @@ -1,1190 +0,0 @@ -/* MAPIStoreMailVolatileMessage.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -/* TODO: - - calendar invitations - - merge some code in a common module with SOGoDraftObject -*/ - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#import "Codepages.h" -#import "MAPIStoreAttachment.h" -#import "MAPIStoreAttachmentTable.h" -#import "MAPIStoreContext.h" -#import "MAPIStoreMailFolder.h" -#import "MAPIStoreMIME.h" -#import "MAPIStoreMapping.h" -#import "MAPIStoreSamDBUtils.h" -#import "MAPIStoreTypes.h" -#import "MAPIStoreUserContext.h" -#import "NSData+MAPIStore.h" -#import "NSObject+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreMailVolatileMessage.h" - -#undef DEBUG -#include -#include -#include - -static Class NSNumberK = Nil; - -static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" }; - -// -// Useful extension that comes from Pantomime which is also -// released under the LGPL. We should eventually merge -// this with the same category found in SOPE's NGSmtpClient.m -// or simply drop sope-mime in favor of Pantomime -// -@interface NSMutableData (DataCleanupExtension) - -- (NSRange) rangeOfCString: (const char *) theCString; -- (NSRange) rangeOfCString: (const char *) theCString - options: (unsigned int) theOptions - range: (NSRange) theRange; -@end - -@implementation NSMutableData (DataCleanupExtension) - -- (NSRange) rangeOfCString: (const char *) theCString -{ - return [self rangeOfCString: theCString - options: 0 - range: NSMakeRange(0,[self length])]; -} - --(NSRange) rangeOfCString: (const char *) theCString - options: (unsigned int) theOptions - range: (NSRange) theRange -{ - const char *b, *bytes; - int i, len, slen; - - if (!theCString) - { - return NSMakeRange(NSNotFound,0); - } - - bytes = [self bytes]; - len = [self length]; - slen = strlen(theCString); - - b = bytes; - - if (len > theRange.location + theRange.length) - { - len = theRange.location + theRange.length; - } - - if (theOptions == NSCaseInsensitiveSearch) - { - i = theRange.location; - b += i; - - for (; i <= len-slen; i++, b++) - { - if (!strncasecmp(theCString,b,slen)) - { - return NSMakeRange(i,slen); - } - } - } - else - { - i = theRange.location; - b += i; - - for (; i <= len-slen; i++, b++) - { - if (!memcmp(theCString,b,slen)) - { - return NSMakeRange(i,slen); - } - } - } - - return NSMakeRange(NSNotFound,0); -} - -@end - -@interface MAPIStoreAttachment (MAPIStoreMIME) - -- (BOOL) hasContentId; -- (NGMimeBodyPart *) asMIMEBodyPart; - -@end - -@implementation MAPIStoreAttachment (MAPIStoreMIME) - -- (BOOL) hasContentId -{ - NSString *contentId = [properties - objectForKey: MAPIPropertyKey (PR_ATTACH_CONTENT_ID_UNICODE)]; - return contentId && [contentId length] > 0; -} - -- (NGMimeBodyPart *) asMIMEBodyPart -{ - NGMimeBodyPart *bodyPart = nil; - NSString *filename, *mimeType, *baseDisposition, *contentType, - *contentDisposition, *contentId; - NSData *content; - struct mapistore_connection_info *connInfo; - SOGoDomainDefaults *dd; - SOGoUser *activeUser; - NGMutableHashMap *map; - - content = [properties objectForKey: MAPIPropertyKey (PR_ATTACH_DATA_BIN)]; - if (content) - { - filename - = [properties - objectForKey: MAPIPropertyKey (PR_ATTACH_LONG_FILENAME_UNICODE)]; - if (![filename length]) - filename - = [properties - objectForKey: MAPIPropertyKey (PR_ATTACH_FILENAME_UNICODE)]; - - mimeType = [properties - objectForKey: MAPIPropertyKey (PR_ATTACH_MIME_TAG_UNICODE)]; - if (!mimeType && [filename length]) - mimeType = [[MAPIStoreMIME sharedMAPIStoreMIME] - mimeTypeForExtension: [filename pathExtension]]; - if (!mimeType) - mimeType = @"application/octet-stream"; - - if ([mimeType hasPrefix: @"text/"]) - { - connInfo = [[self context] connectionInfo]; - activeUser = [SOGoUser userWithLogin: [NSString stringWithUTF8String: connInfo->username]]; - dd = [activeUser domainDefaults]; - baseDisposition = ([dd mailAttachTextDocumentsInline] - ? @"inline" : @"attachment"); - } - else if ([mimeType hasPrefix: @"image/"] || [mimeType hasPrefix: @"message"]) - baseDisposition = @"inline"; - else - baseDisposition = @"attachment"; - - if ([filename length] > 0) - { - contentType = [NSString stringWithFormat: @"%@; name=\"%@\"", - mimeType, filename]; - contentDisposition = [NSString stringWithFormat: @"%@; filename=\"%@\"", - baseDisposition, filename]; - } - else - { - contentType = mimeType; - contentDisposition = baseDisposition; - } - - map = [[NGMutableHashMap alloc] initWithCapacity: 16]; - [map addObject: contentType forKey: @"content-type"]; - [map addObject: contentDisposition forKey: @"content-disposition"]; - contentId = [properties - objectForKey: MAPIPropertyKey (PR_ATTACH_CONTENT_ID_UNICODE)]; - if (contentId && [contentId length] > 0) - [map setObject: [NSString stringWithFormat: @"<%@>", contentId] - forKey: @"content-id"]; - bodyPart = [NGMimeBodyPart bodyPartWithHeader: map]; - [bodyPart setBody: content]; - [map release]; - } - else - [self errorWithFormat: @"no content for attachment"]; - - return bodyPart; -} - -@end - -@implementation MAPIStoreMailVolatileMessage - -+ (void) initialize -{ - NSNumberK = [NSNumber class]; -} - -- (id) initWithSOGoObject: (id) newSOGoObject - inContainer: (MAPIStoreObject *) newContainer -{ - if ((self = [super initWithSOGoObject: newSOGoObject - inContainer: newContainer])) - { - ASSIGN (properties, [sogoObject properties]); - } - - return self; -} - -- (void) addProperties: (NSDictionary *) newProperties -{ - [super addProperties: newProperties]; - [sogoObject adjustLastModified]; -} - -- (BOOL) canGetProperty: (enum MAPITAGS) propTag -{ - return ([super canGetProperty: propTag] - || [properties objectForKey: MAPIPropertyKey (propTag)] != nil); -} - -- (uint64_t) objectVersion -{ - NSNumber *version; - - version = [properties objectForKey: @"version"]; - - return (version - ? [version unsignedLongLongValue] - : ULLONG_MAX); -} - -- (enum mapistore_error) getPidTagMessageClass: (void **) data inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [@"IPM.Note" asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagChangeKey: (void **) data inMemCtx: (TALLOC_CTX *) memCtx -{ - NSData *changeKey; - enum mapistore_error rc; - - changeKey = [properties objectForKey: MAPIPropertyKey (PR_CHANGE_KEY)]; - if (changeKey) - { - *data = [changeKey asBinaryInMemCtx: memCtx]; - rc = MAPISTORE_SUCCESS; - } - else - rc = [super getPidTagChangeKey: data inMemCtx: memCtx]; - - return rc; -} - -- (NSDate *) creationTime -{ - return [sogoObject creationDate]; -} - -- (NSDate *) lastModificationTime -{ - return [sogoObject lastModified]; -} - -- (id) lookupAttachment: (NSString *) childKey -{ - return [attachmentParts objectForKey: childKey]; -} - -- (void) getMessageData: (struct mapistore_message **) dataPtr - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSArray *recipients; - NSUInteger count, max, recipientsMax, p, current; - NSString *username, *cn, *email; - NSData *entryId; - NSDictionary *allRecipients, *dict, *contactInfos; - SOGoUserManager *mgr; - struct mapistore_message *msgData; - struct mapistore_message_recipient *recipient; - enum ulRecipClass type; - - // [super getMessageData: &msgData inMemCtx: memCtx]; - - msgData = talloc_zero (memCtx, struct mapistore_message); - - allRecipients = [properties objectForKey: @"recipients"]; - msgData->columns = set_SPropTagArray (msgData, 9, - PR_OBJECT_TYPE, - PR_DISPLAY_TYPE, - PR_7BIT_DISPLAY_NAME_UNICODE, - PR_SMTP_ADDRESS_UNICODE, - PR_SEND_INTERNET_ENCODING, - PR_RECIPIENT_DISPLAY_NAME_UNICODE, - PR_RECIPIENT_FLAGS, - PR_RECIPIENT_ENTRYID, - PR_RECIPIENT_TRACKSTATUS); - - /* Retrieve recipients from the message */ - max = ([[allRecipients objectForKey: @"orig"] count] - + [[allRecipients objectForKey: @"to"] count] - + [[allRecipients objectForKey: @"cc"] count] - + [[allRecipients objectForKey: @"bcc"] count]); - - mgr = [SOGoUserManager sharedUserManager]; - msgData->recipients_count = max; - msgData->recipients = talloc_array (msgData, struct mapistore_message_recipient, max); - current = 0; - for (type = MAPI_ORIG; type <= MAPI_BCC; type++) - { - recipients = [allRecipients objectForKey: recTypes[type]]; - recipientsMax = [recipients count]; - for (count = 0; count < recipientsMax; count++) - { - recipient = msgData->recipients + current; - recipient->type = type; - - dict = [recipients objectAtIndex: count]; - cn = [dict objectForKey: @"fullName"]; - email = [dict objectForKey: @"email"]; - - contactInfos = [mgr contactInfosForUserWithUIDorEmail: email]; - if (contactInfos) - { - username = [contactInfos objectForKey: @"sAMAccountName"]; - recipient->username = [username asUnicodeInMemCtx: msgData]; - entryId = MAPIStoreInternalEntryId ([[self context] connectionInfo], username); - } - else - { - recipient->username = NULL; - entryId = MAPIStoreExternalEntryId (cn, email); - } - - /* properties */ - p = 0; - recipient->data = talloc_array (msgData, void *, msgData->columns->cValues); - memset (recipient->data, 0, msgData->columns->cValues * sizeof (void *)); - - // PR_OBJECT_TYPE = MAPI_MAILUSER (see MAPI_OBJTYPE) - recipient->data[p] = MAPILongValue (msgData, MAPI_MAILUSER); - p++; - - // PR_DISPLAY_TYPE = DT_MAILUSER (see MS-NSPI) - recipient->data[p] = MAPILongValue (msgData, 0); - p++; - - // PR_7BIT_DISPLAY_NAME_UNICODE - recipient->data[p] = [cn asUnicodeInMemCtx: msgData]; - p++; - - // PR_SMTP_ADDRESS_UNICODE - recipient->data[p] = [email asUnicodeInMemCtx: msgData]; - p++; - - // PR_SEND_INTERNET_ENCODING = 0x00060000 (plain text, see OXCMAIL) - recipient->data[p] = MAPILongValue (msgData, 0x00060000); - p++; - - // PR_RECIPIENT_DISPLAY_NAME_UNICODE - recipient->data[p] = [cn asUnicodeInMemCtx: msgData]; - p++; - - // PR_RECIPIENT_FLAGS - recipient->data[p] = MAPILongValue (msgData, 0x01); - p++; - - // PR_RECIPIENT_ENTRYID - recipient->data[p] = [entryId asBinaryInMemCtx: msgData]; - p++; - - // PR_RECIPIENT_TRACKSTATUS - recipient->data[p] = MAPILongValue (msgData, 0x00); - p++; - - current++; - } - } - *dataPtr = msgData; -} - -static inline NSString * -MakeRecipientString (NSDictionary *recipient) -{ - NSString *fullName, *email, *fullEmail; - - fullName = [recipient objectForKey: @"fullName"]; - email = [recipient objectForKey: @"email"]; - if ([email length] > 0) - { - if ([fullName length] > 0) - fullEmail = [NSString stringWithFormat: @"%@ <%@>", fullName, email]; - else - fullEmail = email; - } - else - { - NSLog (@"recipient not generated from record: %@", recipient); - fullEmail = nil; - } - - return fullEmail; -} - -static inline NSArray * -MakeRecipientsList (NSArray *recipients) -{ - NSMutableArray *list; - NSUInteger count, max; - NSString *recipient; - - max = [recipients count]; - list = [NSMutableArray arrayWithCapacity: max]; - for (count = 0; count < max; count++) - { - recipient = MakeRecipientString ([recipients objectAtIndex: count]); - if (recipient) - [list addObject: recipient]; - } - - return list; -} - -static NSString * -QuoteSpecials (NSString *address) -{ - NSString *result, *part, *s2; - int i, len; - - // We want to correctly send mails to recipients such as : - // foo.bar - // foo (bar) - // bar, foo - if ([address indexOf: '('] >= 0 || [address indexOf: ')'] >= 0 - || [address indexOf: '<'] >= 0 || [address indexOf: '>'] >= 0 - || [address indexOf: '@'] >= 0 || [address indexOf: ','] >= 0 - || [address indexOf: ';'] >= 0 || [address indexOf: ':'] >= 0 - || [address indexOf: '\\'] >= 0 || [address indexOf: '"'] >= 0 - || [address indexOf: '.'] >= 0 - || [address indexOf: '['] >= 0 || [address indexOf: ']'] >= 0) - { - // We search for the first instance of < from the end - // and we quote what was before if we need to - len = [address length]; - i = -1; - while (len--) - if ([address characterAtIndex: len] == '<') - { - i = len; - break; - } - - if (i > 0) - { - part = [address substringToIndex: i - 1]; - s2 = [[part stringByReplacingString: @"\\" withString: @"\\\\"] - stringByReplacingString: @"\"" withString: @"\\\""]; - result = [NSString stringWithFormat: @"\"%@\" %@", s2, [address substringFromIndex: i]]; - } - else - { - s2 = [[address stringByReplacingString: @"\\" withString: @"\\\\"] - stringByReplacingString: @"\"" withString: @"\\\""]; - result = [NSString stringWithFormat: @"\"%@\"", s2]; - } - } - else - result = address; - - return result; -} - -static inline void -FillMessageHeadersFromSharingProperties (NGMutableHashMap *headers, NSDictionary *mailProperties) -{ - /* Store the *important* properties related with a sharing object as - MIME eXtension headers. See [MS-OXSHARE] Section 2.2 for details - about the properties */ - - id value; - NSNumber *sharingFlavourNum = nil; - - value = [mailProperties objectForKey: MAPIPropertyKey (PidLidSharingCapabilities)]; - if (value) - [headers setObject: value - forKey: @"X-MS-Sharing-Capabilities"]; - - value = [mailProperties objectForKey: MAPIPropertyKey (PidLidSharingFlavor)]; - if (value) - sharingFlavourNum = (NSNumber *)value; - else - { - value = [mailProperties objectForKey: MAPIPropertyKey (PidNameXSharingFlavor)]; - if (value) - { - /* Transform the hex string to unsigned int */ - NSScanner *scanner; - unsigned int sharingFlavour; - scanner = [NSScanner scannerWithString:value]; - if ([scanner scanHexInt:&sharingFlavour]) - sharingFlavourNum =[NSNumber numberWithUnsignedInt: sharingFlavour]; - } - } - if (sharingFlavourNum) - { - if ([sharingFlavourNum unsignedIntegerValue] == 0x5100) - { - /* 0x5100 sharing flavour is not in standard but it seems to - be a denial of request + invitation message so we store - deny sharing flavour */ - sharingFlavourNum = [NSNumber numberWithUnsignedInt: SHARING_DENY_REQUEST]; - } - [headers setObject: sharingFlavourNum - forKey: @"X-MS-Sharing-Flavor"]; - } - - value = [mailProperties objectForKey: MAPIPropertyKey (PidLidSharingInitiatorEntryId)]; - if (value) - [headers setObject: [[value stringByEncodingBase64] stringByReplacingOccurrencesOfString: @"\n" - withString: @""] - forKey: @"X-MS-Sharing-InitiatorEntryId"]; - - value = [mailProperties objectForKey: MAPIPropertyKey (PidLidSharingInitiatorName)]; - if (value) - [headers setObject: value - forKey: @"X-MS-Sharing-InitiatorName"]; - - value = [mailProperties objectForKey: MAPIPropertyKey (PidLidSharingInitiatorSmtp)]; - if (value) - [headers setObject: value - forKey: @"X-MS-Sharing-InitiatorSmtp"]; - - value = [mailProperties objectForKey: MAPIPropertyKey (PidLidSharingLocalType)]; - if (value) - [headers setObject: value - forKey: @"X-MS-Sharing-LocalType"]; - - value = [mailProperties objectForKey: MAPIPropertyKey (PidLidSharingProviderName)]; - if (value) - [headers setObject: value - forKey: @"X-MS-Sharing-ProviderName"]; - - value = [mailProperties objectForKey: MAPIPropertyKey (PidLidSharingRemoteName)]; - if (value) - [headers setObject: value - forKey: @"X-MS-Sharing-RemoteName"]; - - value = [mailProperties objectForKey: MAPIPropertyKey (PidLidSharingRemoteStoreUid)]; - if (value) - [headers setObject: value - forKey: @"X-MS-Sharing-RemoteStoreUid"]; - - value = [mailProperties objectForKey: MAPIPropertyKey (PidLidSharingRemoteUid)]; - if (value) - [headers setObject: value - forKey: @"X-MS-Sharing-RemoteUid"]; - - value = [mailProperties objectForKey: MAPIPropertyKey (PidLidSharingResponseTime)]; - if (value) - [headers setObject: value - forKey: @"X-MS-Sharing-ResponseTime"]; - - value = [mailProperties objectForKey: MAPIPropertyKey (PidLidSharingResponseType)]; - if (value) - [headers setObject: value - forKey: @"X-MS-Sharing-ResponseType"]; - -} - -static inline void -FillMessageHeadersFromProperties (NGMutableHashMap *headers, - NSDictionary *mailProperties, BOOL withBcc, - struct mapistore_connection_info *connInfo) -{ - BOOL fromResolved = NO; - NSData *senderEntryId; - NSMutableString *subject; - NSString *from, *recId, *messageId, *subjectData, *recipientsStr, *msgClass; - NSArray *list; - NSCalendarDate *date; - NSDictionary *recipients; - enum ulRecipClass type, bccLimit; - SOGoUser *activeUser; - NSNumber *priority; - - activeUser - = [SOGoUser - userWithLogin: [NSString stringWithUTF8String: connInfo->username]]; - - from = [NSString stringWithFormat: @"%@ <%@>", - [activeUser cn], [[activeUser allEmails] objectAtIndex: 0]]; - [headers setObject: QuoteSpecials (from) forKey: @"from"]; - - /* save the recipients */ - recipients = [mailProperties objectForKey: @"recipients"]; - if (recipients) - { - if (withBcc) - bccLimit = MAPI_BCC; - else - bccLimit = MAPI_CC; - - for (type = MAPI_TO; type <= bccLimit; type++) - { - recId = recTypes[type]; - list = MakeRecipientsList ([recipients objectForKey: recId]); - [headers setObjects: list forKey: recId]; - } - - list = MakeRecipientsList ([recipients objectForKey: @"orig"]); - if ([list count]) - { - [headers setObjects: list forKey: @"from"]; - fromResolved = YES; - } - } - - if (!fromResolved) - { - TALLOC_CTX *local_mem_ctx; - local_mem_ctx = talloc_new(NULL); - if (!local_mem_ctx) - { - NSLog (@"%s: Out of memory", __PRETTY_FUNCTION__); - return; - } - - NSLog (@"Message without an orig from, try to guess it from PidTagSenderEntryId"); - senderEntryId = [mailProperties objectForKey: MAPIPropertyKey (PR_SENDER_ENTRYID)]; - if (senderEntryId) - { - struct Binary_r bin32; - struct AddressBookEntryId *addrBookEntryId; - NSString *username; - NSMutableDictionary *fromRecipient; - - fromRecipient = [NSMutableDictionary dictionaryWithCapacity: 2]; - - bin32.cb = [senderEntryId length]; - bin32.lpb = (uint8_t *) [senderEntryId bytes]; - addrBookEntryId = get_AddressBookEntryId (local_mem_ctx, &bin32); - if (addrBookEntryId && [[NSString stringWithGUID: &addrBookEntryId->ProviderUID] - hasSuffix: @"08002b2fe182"]) - { - /* TODO: better way to distinguish local and other ones */ - username = MAPIStoreSamDBUserAttribute (connInfo, @"legacyExchangeDN", - [NSString stringWithUTF8String: addrBookEntryId->X500DN], @"sAMAccountName"); - if (username) - { - SOGoUser *fromUser; - - fromUser = [SOGoUser userWithLogin: [username lowercaseString]]; - [fromRecipient setObject: [fromUser cn] forKey: @"fullName"]; - [fromRecipient setObject: [[fromUser allEmails] objectAtIndex: 0] - forKey: @"email"]; - } - else - [fromRecipient setObject: [NSString stringWithUTF8String: addrBookEntryId->X500DN] - forKey: @"email"]; - - } - else - { - /* Try with One-Off EntryId */ - struct OneOffEntryId *oneOffEntryId; - - oneOffEntryId = get_OneOffEntryId (local_mem_ctx, &bin32); - if (oneOffEntryId && [[NSString stringWithGUID: &oneOffEntryId->ProviderUID] - hasSuffix: @"00dd010f5402"]) - { - [fromRecipient setObject: [NSString stringWithUTF8String: oneOffEntryId->DisplayName.lpszW] - forKey: @"fullName"]; - [fromRecipient setObject: [NSString stringWithUTF8String: oneOffEntryId->EmailAddress.lpszW] - forKey: @"email"]; - } - } - - if ([[fromRecipient allKeys] count] > 0) - { - list = MakeRecipientsList ([NSArray arrayWithObjects: fromRecipient, nil]); - if ([list count]) - [headers setObjects: list forKey: @"from"]; - } - - } - /* Free entryId */ - talloc_free(local_mem_ctx); - } - - if (!recipients) - { - NSLog (@"Message without recipients." - @"Guessing recipients from PidTagOriginalDisplayTo and PidTagOriginalCc"); - recipientsStr = [mailProperties objectForKey: MAPIPropertyKey (PidTagOriginalDisplayTo)]; - if (recipientsStr) - { - list = [recipientsStr componentsSeparatedByString:@", "]; - if ([list count]) - [headers setObjects: list forKey: @"to"]; - } - - recipientsStr = [mailProperties objectForKey: MAPIPropertyKey (PidTagOriginalDisplayCc)]; - if (recipientsStr) - { - list = [recipientsStr componentsSeparatedByString:@", "]; - if ([list count]) - [headers setObjects: list forKey: @"cc"]; - } - } - - subject = [NSMutableString stringWithCapacity: 128]; - subjectData = [mailProperties objectForKey: MAPIPropertyKey (PR_SUBJECT_PREFIX_UNICODE)]; - if (subjectData) - [subject appendString: subjectData]; - subjectData = [mailProperties objectForKey: MAPIPropertyKey (PR_NORMALIZED_SUBJECT_UNICODE)]; - if (subjectData) - [subject appendString: subjectData]; - if ([subject length] == 0) - { - subjectData = [mailProperties objectForKey: MAPIPropertyKey (PR_SUBJECT_UNICODE)]; - if (subjectData) - [subject appendString: subjectData]; - } - [headers setObject: [subject asQPSubjectString: @"utf-8"] forKey: @"subject"]; - - messageId = [mailProperties objectForKey: MAPIPropertyKey (PR_INTERNET_MESSAGE_ID_UNICODE)]; - if ([messageId length]) - [headers setObject: messageId forKey: @"message-id"]; - - date = [mailProperties objectForKey: MAPIPropertyKey (PR_CLIENT_SUBMIT_TIME)]; - if (date) - { - [headers addObject: [date rfc822DateString] forKey: @"date"]; - } - [headers addObject: @"1.0" forKey: @"MIME-Version"]; - - priority = [mailProperties objectForKey: MAPIPropertyKey (PidTagImportance)]; - - if ([priority intValue] == 2) - { - [headers addObject: @"1 (Highest)" forKey: @"X-Priority"]; - } - else if ([priority intValue] == 1) - { - [headers removeAllObjectsForKey: @"X-Priority"]; - } - else - { - [headers addObject: @"5 (Lowest)" forKey: @"X-Priority"]; - } - - msgClass = [mailProperties objectForKey: MAPIPropertyKey (PidTagMessageClass)]; - if ([msgClass isEqualToString: @"IPM.Sharing"]) - { - FillMessageHeadersFromSharingProperties (headers, mailProperties); - } - -} - -static NSArray * -MakeAttachmentParts (NSDictionary *attachmentParts, BOOL withContentId) -{ - NSMutableArray *attachmentMimeParts; - NSArray *keys; - MAPIStoreAttachment *attachment; - NSUInteger count, max; - NGMimeBodyPart *mimePart; - - keys = [attachmentParts allKeys]; - max = [keys count]; - attachmentMimeParts = [NSMutableArray arrayWithCapacity: max]; - for (count = 0; count < max; count++) - { - attachment = [attachmentParts - objectForKey: [keys objectAtIndex: count]]; - if ([attachment hasContentId] == withContentId) - { - mimePart = [attachment asMIMEBodyPart]; - if (mimePart) - [attachmentMimeParts addObject: mimePart]; - } - } - - return attachmentMimeParts; -} - -static inline id -MakeTextPlainBody (NSDictionary *mailProperties, NSString **contentType) -{ - id textPlainBody; - - textPlainBody = [[mailProperties - objectForKey: MAPIPropertyKey (PR_BODY_UNICODE)] - dataUsingEncoding: NSUTF8StringEncoding]; - *contentType = @"text/plain; charset=utf-8"; - - return textPlainBody; -} - -static inline id -MakeTextHtmlBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, - NSString **contentType) -{ - id textHtmlBody; - NSData *htmlBody; - NSString *charset, *htmlContentType; - NSArray *parts; - NSNumber *codePage; - NGMimeBodyPart *htmlBodyPart; - NGMutableHashMap *headers; - NSUInteger count, max; - - htmlBody = [mailProperties objectForKey: MAPIPropertyKey (PR_HTML)]; - if (htmlBody) - { - /* charset */ - codePage = [mailProperties objectForKey: MAPIPropertyKey (PR_INTERNET_CPID)]; - charset = [Codepages getNameFromCodepage: codePage]; - if (!charset) - charset = @"utf-8"; - htmlContentType = [NSString stringWithFormat: @"text/html; charset=%@", - charset]; - - parts = MakeAttachmentParts (attachmentParts, YES); - max = [parts count]; - if (max > 0) - { - textHtmlBody = [NGMimeMultipartBody new]; - [textHtmlBody autorelease]; - - headers = [[NGMutableHashMap alloc] initWithCapacity: 1]; - [headers setObject: htmlContentType forKey: @"content-type"]; - htmlBodyPart = [NGMimeBodyPart bodyPartWithHeader: headers]; - [htmlBodyPart setBody: htmlBody]; - [headers release]; - [textHtmlBody addBodyPart: htmlBodyPart]; - - for (count = 0; count < max; count++) - [textHtmlBody addBodyPart: [parts objectAtIndex: count]]; - - *contentType = @"multipart/related"; - } - else - { - textHtmlBody = htmlBody; - *contentType = htmlContentType; - } - } - else - textHtmlBody = nil; - - return textHtmlBody; -} - -static inline id -MakeTextPartBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, - NSString **contentType) -{ - id textBody, textPlainBody, textHtmlBody; - NSString *textPlainContentType, *textHtmlContentType; - NGMutableHashMap *headers; - NGMimeBodyPart *bodyPart; - - textPlainBody = MakeTextPlainBody (mailProperties, &textPlainContentType); - textHtmlBody = MakeTextHtmlBody (mailProperties, attachmentParts, &textHtmlContentType); - if (textPlainBody) - { - if (textHtmlBody) - { - textBody = [NGMimeMultipartBody new]; - [textBody autorelease]; - - headers = [[NGMutableHashMap alloc] initWithCapacity: 1]; - [headers setObject: textHtmlContentType forKey: @"content-type"]; - bodyPart = [NGMimeBodyPart bodyPartWithHeader: headers]; - [bodyPart setBody: textHtmlBody]; - [headers release]; - [textBody addBodyPart: bodyPart]; - - headers = [[NGMutableHashMap alloc] initWithCapacity: 1]; - [headers setObject: textPlainContentType forKey: @"content-type"]; - bodyPart = [NGMimeBodyPart bodyPartWithHeader: headers]; - [bodyPart setBody: textPlainBody]; - [headers release]; - [textBody addBodyPart: bodyPart]; - - *contentType = @"multipart/alternative"; - } - else - { - textBody = textPlainBody; - *contentType = textPlainContentType; - } - } - else - { - textBody = textHtmlBody; - *contentType = textHtmlContentType; - } - - return textBody; -} - -// static id -// MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, -// NSString **contentType) -static id -MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NSString **contentType) -{ - id messageBody, textBody; - NSString *textContentType; - NSArray *parts; - NGMimeBodyPart *textBodyPart; - NGMutableHashMap *headers; - NSUInteger count, max; - - textBody = MakeTextPartBody (mailProperties, attachmentParts, - &textContentType); - - parts = MakeAttachmentParts (attachmentParts, NO); - max = [parts count]; - if (max > 0) - { - messageBody = [NGMimeMultipartBody new]; - [messageBody autorelease]; - - if (textBody) - { - headers = [[NGMutableHashMap alloc] initWithCapacity: 1]; - [headers setObject: textContentType forKey: @"content-type"]; - textBodyPart = [NGMimeBodyPart bodyPartWithHeader: headers]; - [textBodyPart setBody: textBody]; - [headers release]; - [messageBody addBodyPart: textBodyPart]; - } - - for (count = 0; count < max; count++) - [messageBody addBodyPart: [parts objectAtIndex: count]]; - - *contentType = @"multipart/mixed"; - } - else - { - messageBody = textBody; - *contentType = textContentType; - } - - return messageBody; -} - -- (NGMimeMessage *) _generateMessageWithBcc: (BOOL) withBcc -{ - NSString *contentType; - NGMimeMessage *message; - NGMutableHashMap *headers; - id messageBody; - - headers = [[NGMutableHashMap alloc] initWithCapacity: 16]; - FillMessageHeadersFromProperties (headers, properties, withBcc, - [[self context] connectionInfo]); - message = [[NGMimeMessage alloc] initWithHeader: headers]; - [message autorelease]; - [headers release]; - - messageBody = MakeMessageBody (properties, attachmentParts, &contentType); - if (messageBody) - { - [message setHeader: contentType forKey: @"content-type"]; - [message setBody: messageBody]; - } - - return message; -} - -- (NSData *) _generateMailDataWithBcc: (BOOL) withBcc -{ - NGMimeMessage *message; - NGMimeMessageGenerator *generator; - NSData *messageData; - - /* mime message generation */ - generator = [NGMimeMessageGenerator new]; - message = [self _generateMessageWithBcc: withBcc]; - messageData = [generator generateMimeFromPart: message]; - [generator release]; - - // [messageData writeToFile: @"/tmp/mimegen.eml" atomically: NO]; - - return messageData; -} - -- (enum mapistore_error) submitWithFlags: (enum SubmitFlags) flags -{ - enum mapistore_error rc = MAPISTORE_SUCCESS; - NSDictionary *recipients; - NSData *messageData; - NSMutableArray *recipientEmails; - NSArray *list; - NSString *recId, *from, *msgClass; - enum ulRecipClass type; - SOGoUser *activeUser; - SOGoDomainDefaults *dd; - NSException *error; - WOContext *woContext; - id authenticator; - - msgClass = [properties objectForKey: MAPIPropertyKey (PidTagMessageClass)]; - if ([msgClass isEqualToString: @"IPM.Note"] || [msgClass isEqualToString: @"IPM.Sharing"]) /* we skip invitation replies */ - { - /* send mail */ - - messageData = [self _generateMailDataWithBcc: NO]; - - recipientEmails = [NSMutableArray arrayWithCapacity: 32]; - recipients = [properties objectForKey: @"recipients"]; - for (type = MAPI_ORIG; type <= MAPI_BCC; type++) - { - recId = recTypes[type]; - list = [recipients objectForKey: recId]; - [recipientEmails - addObjectsFromArray: [list objectsForKey: @"email" - notFoundMarker: nil]]; - } - - activeUser = [[self context] activeUser]; - - [self logWithFormat: @"recipients: %@", recipientEmails]; - dd = [activeUser domainDefaults]; - from = [[activeUser allEmails] objectAtIndex: 0]; - - [[self userContext] activate]; - woContext = [[self userContext] woContext]; - authenticator = [sogoObject authenticatorInContext: woContext]; - error = [[SOGoMailer mailerWithDomainDefaults: dd] - sendMailData: messageData - toRecipients: recipientEmails - sender: from - withAuthenticator: authenticator - inContext: woContext]; - if (error) - { - [self errorWithFormat: @"an error occurred: '%@'", error]; - rc = MAPISTORE_ERR_MSG_SEND; - } - - // mapping = [self mapping]; - // [mapping unregisterURLWithID: [self objectId]]; - // [self setIsNew: NO]; - // [properties removeAllObjects]; - [(MAPIStoreMailFolder *) [self container] cleanupCaches]; - } - else - [self logWithFormat: @"skipping submit of message with class '%@'", - msgClass]; - - return rc; -} - -- (void) save: (TALLOC_CTX *) memCtx -{ - BOOL updatedMetadata; - NSString *folderName, *flag, *newIdString, *messageKey, *changeNumber; - NSData *changeKey, *messageData; - NGImap4Connection *connection; - NGImap4Client *client; - SOGoMailFolder *containerFolder; - NSDictionary *result, *responseResult; - MAPIStoreMapping *mapping; - uint64_t mid; - - messageData = [self _generateMailDataWithBcc: YES]; - - /* appending to imap folder */ - containerFolder = [container sogoObject]; - connection = [containerFolder imap4Connection]; - client = [connection client]; - folderName = [connection imap4FolderNameForURL: [containerFolder imap4URL]]; - result = [client append: messageData toFolder: folderName - withFlags: [NSArray arrayWithObjects: @"seen", nil]]; - if ([[result objectForKey: @"result"] boolValue]) - { - /* we reregister the new message URL with the id mapper */ - responseResult = [[result objectForKey: @"RawResponse"] - objectForKey: @"ResponseResult"]; - flag = [responseResult objectForKey: @"flag"]; - - newIdString = [[flag componentsSeparatedByString: @" "] - objectAtIndex: 2]; - mapping = [self mapping]; - mid = [self objectId]; - [mapping unregisterURLWithID: mid]; - // [sogoObject setNameInContainer: ]; - - messageKey = [NSString stringWithFormat: @"%@.eml", newIdString]; - [sogoObject setNameInContainer: messageKey]; - [mapping registerURL: [self url] withID: mid]; - - /* synchronise the cache and update the predecessor change list - with the change key provided by the client. Before doing - this, lets issue a unselect/select combo because of timing - issues with Dovecot in obtaining the latest modseq. - Sometimes, Dovecot doesn't return the newly appended UID if - we do a "UID SORT (DATE) UTF-8 (MODSEQ XYZ) (NOT DELETED)" - command (where XYZ is the HIGHESTMODSEQ+1) immediately after - IMAP APPEND */ - [client unselect]; - [client select: folderName]; - - [(MAPIStoreMailFolder *) container synchroniseCache]; - changeKey = [properties objectForKey: MAPIPropertyKey (PR_CHANGE_KEY)]; - if (changeKey) - { - updatedMetadata = [(MAPIStoreMailFolder *) container updatePredecessorChangeListWith: changeKey - forMessageWithKey: messageKey]; - if (!updatedMetadata) - [self warnWithFormat: @"Predecessor change list not updated with client data"]; - } - - /* Update version property (PR_CHANGE_KEY indeed) as it is - requested once it is saved */ - changeNumber = [(MAPIStoreMailFolder *) container changeNumberForMessageUID: newIdString]; - if (changeNumber) - [properties setObject: [NSNumber numberWithUnsignedLongLong: [changeNumber unsignedLongLongValue] >> 16] - forKey: @"version"]; - } -} - -@end diff --git a/Attic/OpenChange/MAPIStoreMapping.h b/Attic/OpenChange/MAPIStoreMapping.h deleted file mode 100644 index 55c2e944a..000000000 --- a/Attic/OpenChange/MAPIStoreMapping.h +++ /dev/null @@ -1,68 +0,0 @@ -/* MAPIStoreMapping.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 MAPISTOREMAPPING_H -#define MAPISTOREMAPPING_H - -#import - -@class NSMutableDictionary; -@class NSString; - -@interface MAPIStoreMapping : NSObject -{ - void *memCtx; - NSString *username; - struct indexing_context *indexing; - NSUInteger useCount; -} - -+ (id) mappingForUsername: (NSString *) username - withIndexing: (struct indexing_context *) indexing; - -- (id) initForUsername: (NSString *) username - withIndexing: (struct indexing_context *) indexing; - - -- (void) increaseUseCount; -- (void) decreaseUseCount; - -- (NSString *) urlFromID: (uint64_t) idKey; - -- (uint64_t) idFromURL: (NSString *) url; -- (uint64_t) idFromURL: (NSString *) url - isSoftDeleted: (bool *) softDeleted; -- (BOOL) registerURL: (NSString *) urlString - withID: (uint64_t) idNbr; -- (void) registerURLs: (NSArray *) urlString - withIDs: (NSArray *) idNbrs; -- (void) unregisterURLWithID: (uint64_t) idNbr; -- (void) unregisterURLWithID: (uint64_t) idNbr - andFlags: (uint8_t) flags; -- (void) updateID: (uint64_t) idNbr - withURL: (NSString *) urlString; -- (BOOL) updateURL: (NSString *) urlString - withID: (uint64_t) idNbr; - -@end - -#endif /* MAPISTOREMAPPING_H */ diff --git a/Attic/OpenChange/MAPIStoreMapping.m b/Attic/OpenChange/MAPIStoreMapping.m deleted file mode 100644 index 2e2c9a66d..000000000 --- a/Attic/OpenChange/MAPIStoreMapping.m +++ /dev/null @@ -1,327 +0,0 @@ -/* MAPIStoreMapping.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 - -#import -#import -#import -#import -#import - -#import -#import - -#import - -#undef DEBUG -#include -#include - -#import "MAPIStoreTypes.h" - -#import "MAPIStoreMapping.h" - -#include - -static NSMutableDictionary *mappingRegistry = nil; - -@implementation MAPIStoreMapping - -+ (void) initialize -{ - mappingRegistry = [NSMutableDictionary new]; -} - -static inline id -MAPIStoreMappingKeyFromId (uint64_t idNbr) -{ - return [NSString stringWithUnsignedLongLong: idNbr]; -} - - -+ (id) mappingForUsername: (NSString *) username - withIndexing: (struct indexing_context *) indexing -{ - id mapping; - - mapping = [mappingRegistry objectForKey: username]; - if (!mapping) - { - mapping = [[self alloc] initForUsername: username - withIndexing: indexing]; - [mapping autorelease]; - } - - return mapping; -} - -- (id) init -{ - if ((self = [super init])) - { - memCtx = talloc_zero (NULL, TALLOC_CTX); - indexing = NULL; - useCount = 0; - } - - return self; -} - -- (void) increaseUseCount -{ - if (useCount == 0) - { - [mappingRegistry setObject: self forKey: username]; - [self logWithFormat: @"mapping registered (%@)", username]; - } - useCount++; -} - -- (void) decreaseUseCount -{ - useCount--; - if (useCount == 0) - { - [mappingRegistry removeObjectForKey: username]; - [self logWithFormat: @"mapping deregistered (%@)", username]; - } -} - -- (id) initForUsername: (NSString *) newUsername - withIndexing: (struct indexing_context *) newIndexing -{ - if ((self = [self init])) - { - ASSIGN (username, newUsername); - indexing = newIndexing; - /* Workaround so all indexing context are valid and won't be freed. */ - // TODO refactor indexing interface - talloc_reference(memCtx, indexing); - } - - return self; -} - -- (void) dealloc -{ - [username release]; - talloc_free (memCtx); - [super dealloc]; -} - -- (NSString *) urlFromID: (uint64_t) idNbr -{ - char* url = NULL; - enum mapistore_error ret; - bool soft_delete = false; - - ret = indexing->get_uri(indexing, [username UTF8String], - memCtx, idNbr, &url, &soft_delete); - if (ret != MAPISTORE_SUCCESS) - return NULL; - NSString *res = [[[NSString alloc] initWithUTF8String:url] autorelease]; - talloc_free(url); - - return res; -} - -- (uint64_t) idFromURL: (NSString *) url -{ - enum mapistore_error ret; - uint64_t idNbr; - bool softDeleted; - - ret = indexing->get_fmid(indexing, [username UTF8String], [url UTF8String], - false, &idNbr, &softDeleted); - - if (ret == MAPISTORE_SUCCESS && !softDeleted) - return idNbr; - else - return NSNotFound; -} - -- (uint64_t) idFromURL: (NSString *) url - isSoftDeleted: (bool *) softDeleted -{ - enum mapistore_error ret; - uint64_t idNbr; - - ret = indexing->get_fmid(indexing, [username UTF8String], [url UTF8String], - false, &idNbr, softDeleted); - - if (ret != MAPISTORE_SUCCESS) - return NSNotFound; - - return idNbr; -} - -- (void) _updateFolderWithURL: (NSString *) oldURL - withURL: (NSString *) urlString -{ - const char *searchURL; - uint64_t idNbr; - bool softDeleted; - NSString *current; - NSString *newURL; - - if ([oldURL isEqualToString: urlString]) return; - - searchURL = [[oldURL stringByAppendingString:@"*"] UTF8String]; - - while (indexing->get_fmid(indexing, [username UTF8String], - searchURL,true, &idNbr, &softDeleted) == MAPISTORE_SUCCESS) - { - // Ignore deleted - if (softDeleted) continue; - - current = [self urlFromID:idNbr]; - newURL = [current stringByReplacingPrefix: oldURL withPrefix: urlString]; - indexing->update_fmid(indexing, [username UTF8String], idNbr, [newURL UTF8String]); - } -} - -- (void) updateID: (uint64_t) idNbr - withURL: (NSString *) urlString -{ - NSString *oldURL; - - oldURL = [self urlFromID: idNbr]; - if (oldURL) - { - if ([oldURL hasSuffix: @"/"]) /* is container ? */ - { - if (![urlString hasSuffix: @"/"]) - [NSException raise: NSInvalidArgumentException - format: @"a container url must have an ending '/'"]; - [self _updateFolderWithURL: oldURL withURL: urlString]; - } - else - { - if ([urlString hasSuffix: @"/"]) - [NSException raise: NSInvalidArgumentException - format: @"a leaf url must not have an ending '/'"]; - - indexing->update_fmid(indexing, [username UTF8String], - idNbr, [urlString UTF8String]); - } - } -} - -- (BOOL) updateURL: (NSString *) urlString - withID: (uint64_t) idNbr -{ - BOOL rc = NO; - uint64_t oldIDNbr; - - oldIDNbr = [self idFromURL: urlString]; - if (oldIDNbr) - { - [self logWithFormat: @"Updating URL: %@ with id %.16"PRIx64" from old id %.16"PRIx64, - urlString, idNbr, oldIDNbr]; - [self unregisterURLWithID: oldIDNbr]; - [self registerURL: urlString - withID: idNbr]; - rc = YES; - } - - return rc; -} - -- (BOOL) registerURL: (NSString *) urlString - withID: (uint64_t) idNbr -{ - NSString *oldURL; - uint64_t oldIdNbr; - bool softDeleted; - - oldURL = [self urlFromID: idNbr]; - if (oldURL != NULL) - { - [self errorWithFormat: - @"url with idNbr already registered: (oldUrl='%@', newUrl='%@', id=0x%.16"PRIx64")", - oldURL, urlString, idNbr]; - return NO; - } - - oldIdNbr = [self idFromURL: urlString isSoftDeleted: &softDeleted]; - if (oldIdNbr != NSNotFound) - { - if (softDeleted) - [self logWithFormat: @"Attempt to register a soft-deleted %@", urlString]; - else - [self errorWithFormat: - @"attempt to double register an entry with idNbr ('%@', %lld," - @" 0x%.16"PRIx64", oldid=0x%.16"PRIx64")", - urlString, idNbr, idNbr, oldIdNbr]; - return NO; - } - else - { - // [self logWithFormat: @"registered url '%@' with id %lld (0x%.16"PRIx64")", - // urlString, idNbr, idNbr]; - - /* Add the record given its fid and mapistore_uri */ - indexing->add_fmid(indexing, [username UTF8String], - idNbr, [urlString UTF8String]); - } - - return YES; -} - -- (void) registerURLs: (NSArray *) urlStrings - withIDs: (NSArray *) idNbrs -{ - uint64_t count, max, newID; - - max = [urlStrings count]; - if (max == [idNbrs count]) - { - for (count = 0; count < max; count++) - { - newID = [[idNbrs objectAtIndex: count] - unsignedLongLongValue]; - [self registerURL: [urlStrings objectAtIndex: count] - withID: newID]; - } - } - else - [NSException raise: NSInvalidArgumentException - format: @"number of urls (%d) and ids (%d) do not match", max, [idNbrs count]]; -} - -- (void) unregisterURLWithID: (uint64_t) idNbr -{ - indexing->del_fmid(indexing, [username UTF8String], - idNbr, MAPISTORE_PERMANENT_DELETE); -} - -- (void) unregisterURLWithID: (uint64_t) idNbr - andFlags: (uint8_t) flags -{ - indexing->del_fmid(indexing, [username UTF8String], - idNbr, - (flags == MAPISTORE_SOFT_DELETE) ? MAPISTORE_SOFT_DELETE : MAPISTORE_PERMANENT_DELETE); -} - - -@end diff --git a/Attic/OpenChange/MAPIStoreMessage.h b/Attic/OpenChange/MAPIStoreMessage.h deleted file mode 100644 index b7441a74c..000000000 --- a/Attic/OpenChange/MAPIStoreMessage.h +++ /dev/null @@ -1,90 +0,0 @@ -/* MAPIStoreMessage.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTOREMESSAGE_H -#define MAPISTOREMESSAGE_H - -#import - -@class NSArray; -@class NSMutableArray; -@class NSMutableDictionary; - -@class EOQualifier; - -@class MAPIStoreAttachment; -@class MAPIStoreAttachmentTable; -@class MAPIStoreFolder; - -#import "MAPIStoreSOGoObject.h" - -@interface MAPIStoreMessage : MAPIStoreSOGoObject -{ - NSArray *attachmentKeys; - NSMutableDictionary *attachmentParts; - NSMutableArray *activeTables; - NSArray *activeUserRoles; -} - -- (void) getMessageData: (struct mapistore_message **) dataPtr - inMemCtx: (TALLOC_CTX *) memCtx; - -- (enum mapistore_error) modifyRecipientsWithRecipients: (struct mapistore_message_recipient *) recipients - andCount: (NSUInteger) max - andColumns: (struct SPropTagArray *) columns; -- (NSArray *) attachmentKeys; -- (NSArray *) attachmentKeysMatchingQualifier: (EOQualifier *) qualifier - andSortOrderings: (NSArray *) sortOrderings; -- (id) lookupAttachment: (NSString *) childKey; - -/* backend methods */ -- (enum mapistore_error) createAttachment: (MAPIStoreAttachment **) attachmentPtr - inAID: (uint32_t *) aidPtr; -- (enum mapistore_error) getAttachment: (MAPIStoreAttachment **) attachmentPtr - withAID: (uint32_t) aid; -- (enum mapistore_error) getAttachmentTable: (MAPIStoreAttachmentTable **) tablePtr - andRowCount: (uint32_t *) countPtr; -- (enum mapistore_error) setReadFlag: (uint8_t) flag; -- (enum mapistore_error) saveMessage: (TALLOC_CTX *) memCtx; - -- (NSArray *) activeContainerMessageTables; - -- (NSArray *) activeUserRoles; -- (NSArray *) expandRoles: (NSArray *) roles; - -/* move & copy internal ops */ -- (void) copyToMessage: (MAPIStoreMessage *) newMessage inMemCtx: (TALLOC_CTX *) memCtx; - -/* subclasses */ -- (void) save: (TALLOC_CTX *) memCtx; - -/* attachments (subclasses) */ -- (MAPIStoreAttachment *) createAttachment; -- (MAPIStoreAttachmentTable *) attachmentTable; - -- (BOOL) subscriberCanReadMessage; -- (BOOL) subscriberCanModifyMessage; -- (BOOL) subscriberCanDeleteMessage; - -@end - -#endif /* MAPISTOREMESSAGE_H */ diff --git a/Attic/OpenChange/MAPIStoreMessage.m b/Attic/OpenChange/MAPIStoreMessage.m deleted file mode 100644 index 3e303e5a3..000000000 --- a/Attic/OpenChange/MAPIStoreMessage.m +++ /dev/null @@ -1,1018 +0,0 @@ -/* MAPIStoreMessage.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#import "MAPIStoreActiveTables.h" -#import "MAPIStoreAttachment.h" -#import "MAPIStoreAttachmentTable.h" -#import "MAPIStoreContext.h" -#import "MAPIStoreEmbeddedMessage.h" -#import "MAPIStoreFolder.h" -#import "MAPIStoreMessageTable.h" -#import "MAPIStorePropertySelectors.h" -#import "MAPIStoreSamDBUtils.h" -#import "MAPIStoreTypes.h" -#import "MAPIStoreUserContext.h" -#import "NSData+MAPIStore.h" -#import "NSObject+MAPIStore.h" -#import "NSString+MAPIStore.h" -#import "RTFHandler.h" - -#import "MAPIStoreMessage.h" - -#undef DEBUG -#include -#include -#include -#include - -static Class MAPIStoreFolderK, MAPIStoreEmbeddedMessageK; - -static NSString *resourcesDir = nil; - -static NSData * -uncompressRTF (NSData *compressedRTF) -{ - NSData *rtfData = nil; - DATA_BLOB *rtf; - TALLOC_CTX *mem_ctx; - - mem_ctx = talloc_zero (NULL, TALLOC_CTX); - rtf = talloc_zero (mem_ctx, DATA_BLOB); - - if (uncompress_rtf (mem_ctx, - (uint8_t *) [compressedRTF bytes], [compressedRTF length], - rtf) - == MAPI_E_SUCCESS) - rtfData = [NSData dataWithBytes: rtf->data length: rtf->length]; - - talloc_free (mem_ctx); - - return rtfData; -} - -static NSData * -rtf2html (NSData *compressedRTF) -{ - NSData *rtf; - NSMutableData *html = nil; - - rtf = uncompressRTF (compressedRTF); - if (rtf) - { - //html = [NSMutableData data]; - RTFHandler *handler; - - handler = [[RTFHandler alloc] initWithData: rtf]; - AUTORELEASE(handler); - - html = [handler parse]; - } - - return html; -} - -@interface SOGoObject (MAPIStoreProtocol) - -- (NSString *) davContentLength; - -@end - -@implementation MAPIStoreMessage - -+ (void) initialize -{ - if (!resourcesDir) - { - resourcesDir = [[NSBundle bundleForClass: self] resourcePath]; - [resourcesDir retain]; - } - MAPIStoreFolderK = [MAPIStoreFolder class]; - MAPIStoreEmbeddedMessageK = [MAPIStoreEmbeddedMessage class]; -} - -- (id) init -{ - //[self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self]; - - if ((self = [super init])) - { - attachmentParts = [NSMutableDictionary new]; - activeTables = [NSMutableArray new]; - activeUserRoles = nil; - } - - return self; -} - -- (void) dealloc -{ - //[self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self]; - [activeUserRoles release]; - [attachmentKeys release]; - [attachmentParts release]; - [activeTables release]; - [super dealloc]; -} - -- (void) getMessageData: (struct mapistore_message **) dataPtr - inMemCtx: (TALLOC_CTX *) memCtx -{ - void *propValue; - struct mapistore_message *msgData; - - // [self logWithFormat: @"INCOMPLETE METHOD '%s' (%d): no recipient handling", - // __FUNCTION__, __LINE__]; - - msgData = talloc_zero (memCtx, struct mapistore_message); - - if ([self getPidTagSubjectPrefix: &propValue - inMemCtx: msgData] == MAPISTORE_SUCCESS - && propValue) - msgData->subject_prefix = propValue; - else - msgData->subject_prefix = ""; - - if ([self getPidTagNormalizedSubject: &propValue - inMemCtx: msgData] == MAPISTORE_SUCCESS - && propValue) - msgData->normalized_subject = propValue; - else - msgData->normalized_subject = ""; - - msgData->columns = talloc_zero(msgData, struct SPropTagArray); - msgData->recipients_count = 0; - *dataPtr = msgData; -} - -- (NSDictionary *) _convertRecipient: (struct mapistore_message_recipient *) recipient - andColumns: (struct SPropTagArray *) columns -{ - NSMutableDictionary *recipientProperties; - enum MAPITAGS prop_tag; - char *displayName = NULL; - char *email = NULL; - enum MAPI_OBJTYPE object_type = 0; - char *smtpAddress = NULL; - SOGoUser *recipientUser; - NSUInteger count; - NSString *recipientEmail = nil; - NSString *recipientFullName = nil; - id value; - - recipientProperties = [NSMutableDictionary dictionaryWithCapacity: columns->cValues + 2]; - - for (count = 0; count < columns->cValues; count++) - { - prop_tag = columns->aulPropTag[count]; - switch(prop_tag) { - case PidTagDisplayName: - displayName = recipient->data[count]; - break; - case PidTagEmailAddress: - email = recipient->data[count]; - break; - case PidTagObjectType: - if (recipient->data[count]) - object_type = *((uint8_t*) recipient->data[count]); - break; - case PidTagSmtpAddress: - smtpAddress = recipient->data[count]; - break; - default: - break; - } - - if (recipient->data[count]) - { - value = NSObjectFromValuePointer (prop_tag, - recipient->data[count]); - if (value) - [recipientProperties setObject: value - forKey: MAPIPropertyKey (prop_tag)]; - } - } - - if (recipient->username) - { - value = [NSString stringWithUTF8String: recipient->username]; - [recipientProperties setObject: value forKey: @"x500dn"]; - } - - if (object_type == MAPI_MAILUSER && recipient->username) - { - /* values from user object have priority over data sent by the client */ - recipientUser = [SOGoUser userWithLogin: [value lowercaseString]]; - if (recipientUser) - { - value = [recipientUser cn]; - if ([value length] > 0) - recipientFullName = value; - - value = [[recipientUser allEmails] objectAtIndex: 0]; - if ([value length] > 0) - recipientEmail = value; - } - } - - /* If we do not have values from the user object we try to get them from the parameters */ - if (!recipientFullName && displayName) - { - value = [NSString stringWithUTF8String: displayName]; - if ([value length] > 0) - recipientFullName = value; - } - - if (!recipientEmail && email) - { - value = [NSString stringWithUTF8String: email]; - if ([value length] > 0) - recipientEmail = value; - } - - if (!recipientEmail && smtpAddress) - { - value = [NSString stringWithUTF8String: smtpAddress]; - if ([value length] > 0) - recipientEmail = value; - } - - /* Now we can set the properties if we have them */ - if (recipientFullName) - [recipientProperties setObject: recipientFullName forKey: @"fullName"]; - - if (recipientEmail) - [recipientProperties setObject: recipientEmail forKey: @"email"]; - - return recipientProperties; -} - -- (enum mapistore_error) modifyRecipientsWithRecipients: (struct mapistore_message_recipient *) newRecipients - andCount: (NSUInteger) max - andColumns: (struct SPropTagArray *) columns; -{ - static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" }; - NSDictionary *recipientProperties; - NSMutableDictionary *recipients; - NSMutableArray *list; - NSString *recType; - struct mapistore_message_recipient *recipient; - NSUInteger count; - - //[self logWithFormat: @"METHOD '%s'", __FUNCTION__]; - - recipients = [NSMutableDictionary new]; - recipientProperties = [NSDictionary dictionaryWithObject: recipients - forKey: @"recipients"]; - [recipients release]; - - for (count = 0; count < max; count++) - { - recipient = newRecipients + count; - - if (recipient->type >= MAPI_ORIG && recipient->type <= MAPI_BCC) - { - recType = recTypes[recipient->type]; - list = [recipients objectForKey: recType]; - if (!list) - { - list = [NSMutableArray new]; - [recipients setObject: list forKey: recType]; - [list release]; - } - [list addObject: - [self _convertRecipient: recipient andColumns: columns]]; - } - } - [self addProperties: recipientProperties]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) addPropertiesFromRow: (struct SRow *) aRow -{ - enum mapistore_error rc; - MAPIStoreContext *context; - SOGoUser *ownerUser; - BOOL userIsOwner; - MAPIStoreMessage *mainMessage; - - context = [self context]; - ownerUser = [[self userContext] sogoUser]; - userIsOwner = [[context activeUser] isEqual: ownerUser]; - if (userIsOwner) - mainMessage = nil; - else if ([self isKindOfClass: MAPIStoreEmbeddedMessageK]) - mainMessage = (MAPIStoreMessage *) [[self container] container]; - else - mainMessage = self; - - if (userIsOwner || [mainMessage subscriberCanModifyMessage]) - rc = [super addPropertiesFromRow: aRow]; - else - rc = MAPISTORE_ERR_DENIED; - - return rc; -} - -- (void) addProperties: (NSDictionary *) newNewProperties -{ - NSData *htmlData, *rtfData; - static NSNumber *htmlKey = nil, *rtfKey = nil; - - /* we intercept any RTF content and convert it to HTML */ - [super addProperties: newNewProperties]; - - if (!htmlKey) - { - htmlKey = MAPIPropertyKey (PR_HTML); - [htmlKey retain]; - } - - if (!rtfKey) - { - rtfKey = MAPIPropertyKey (PR_RTF_COMPRESSED); - [rtfKey retain]; - } - - if (![properties objectForKey: htmlKey]) - { - rtfData = [properties objectForKey: rtfKey]; - if (rtfData) - { - htmlData = rtf2html (rtfData); - [properties setObject: htmlData forKey: htmlKey]; - [properties removeObjectForKey: rtfKey]; - [properties removeObjectForKey: MAPIPropertyKey (PR_RTF_IN_SYNC)]; - } - } -} - -- (MAPIStoreAttachment *) createAttachment -{ - MAPIStoreAttachment *newAttachment; - uint32_t newAid; - NSString *newKey; - - newAid = [[self attachmentKeys] count]; - - newAttachment = [MAPIStoreAttachment mapiStoreObjectInContainer: self]; - // [newAttachment setIsNew: YES]; - [newAttachment setAID: newAid]; - newKey = [NSString stringWithFormat: @"%ul", newAid]; - [attachmentParts setObject: newAttachment - forKey: newKey]; - [attachmentKeys release]; - attachmentKeys = nil; - - return newAttachment; -} - -- (enum mapistore_error) createAttachment: (MAPIStoreAttachment **) attachmentPtr - inAID: (uint32_t *) aidPtr -{ - MAPIStoreAttachment *attachment; - enum mapistore_error rc = MAPISTORE_SUCCESS; - - attachment = [self createAttachment]; - if (attachment) - { - *attachmentPtr = attachment; - *aidPtr = [attachment AID]; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (id) lookupAttachment: (NSString *) childKey -{ - [self subclassResponsibility: _cmd]; - - return nil; -} - -- (enum mapistore_error) getAttachment: (MAPIStoreAttachment **) attachmentPtr - withAID: (uint32_t) aid -{ - MAPIStoreAttachment *attachment; - NSArray *keys; - enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND; - - keys = [self attachmentKeys]; - if (aid < [keys count]) - { - attachment = [self lookupAttachment: [keys objectAtIndex: aid]]; - if (attachment) - { - *attachmentPtr = attachment; - rc = MAPISTORE_SUCCESS; - } - } - - return rc; -} - -- (enum mapistore_error) getAttachmentTable: (MAPIStoreAttachmentTable **) tablePtr - andRowCount: (uint32_t *) countPtr -{ - MAPIStoreAttachmentTable *attTable; - enum mapistore_error rc = MAPISTORE_SUCCESS; - - attTable = [self attachmentTable]; - if (attTable) - { - *tablePtr = attTable; - *countPtr = [[attTable childKeys] count]; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (NSArray *) activeContainerMessageTables -{ - return [[MAPIStoreActiveTables activeTables] - activeTablesForFMID: [container objectId] - andType: MAPISTORE_MESSAGE_TABLE]; -} - -- (void) copyToMessage: (MAPIStoreMessage *) newMessage inMemCtx: (TALLOC_CTX *) memCtx; - -{ - //TALLOC_CTX *memCtx; - struct mapistore_message *messageData; - NSArray *keys; - NSUInteger count, max; - NSString *key; - MAPIStoreAttachment *attachment, *newAttachment; - - //[self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self]; - - //memCtx = talloc_zero (NULL, TALLOC_CTX); - - /* message headers and recipients */ - [self getMessageData: &messageData inMemCtx: memCtx]; - [newMessage modifyRecipientsWithRecipients: messageData->recipients - andCount: messageData->recipients_count - andColumns: messageData->columns]; - - /* properties */ - [self copyPropertiesToObject: newMessage inMemCtx: memCtx]; - - /* attachments */ - keys = [self attachmentKeys]; - max = [keys count]; - for (count = 0; count < max; count++) - { - key = [keys objectAtIndex: count]; - attachment = [self lookupAttachment: key]; - newAttachment = [newMessage createAttachment]; - [attachment copyToAttachment: newAttachment inMemCtx: memCtx]; - } - - //talloc_free (memCtx); -} - -- (enum mapistore_error) saveMessage: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - NSArray *containerTables; - NSUInteger count, max; - MAPIStoreContext *context; - SOGoUser *ownerUser; - BOOL userIsOwner; - MAPIStoreMessage *mainMessage; - - //[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__]; - - containerTables = nil; - max = 0; - context = [self context]; - ownerUser = [[self userContext] sogoUser]; - userIsOwner = [[context activeUser] isEqual: ownerUser]; - if (userIsOwner) - mainMessage = nil; - else if ([self isKindOfClass: MAPIStoreEmbeddedMessageK]) - mainMessage = (MAPIStoreMessage *) [[self container] container]; - else - mainMessage = self; - - if (userIsOwner - || ([self isKindOfClass: MAPIStoreEmbeddedMessageK] - && [mainMessage subscriberCanModifyMessage]) - || (![self isKindOfClass: MAPIStoreEmbeddedMessageK] - && ((isNew - && [(MAPIStoreFolder *) container subscriberCanCreateMessages]) - || (!isNew && [self subscriberCanModifyMessage])))) - { - /* notifications */ - if ([container isKindOfClass: MAPIStoreFolderK]) - { - /* we ensure the table caches are loaded so that old and new state - can be compared */ - containerTables = [self activeContainerMessageTables]; - max = [containerTables count]; - for (count = 0; count < max; count++) - [[containerTables objectAtIndex: count] restrictedChildKeys]; - } - - /* TODO: Check the save process succeeded */ - [self save: memCtx]; - /* We make sure that any change-related properties are removed from the - properties dictionary, to make sure that related methods will be - invoked the next time they are requested. */ - [properties removeObjectForKey: MAPIPropertyKey (PidTagChangeKey)]; - [properties removeObjectForKey: MAPIPropertyKey (PidTagChangeNumber)]; - [properties removeObjectForKey: MAPIPropertyKey (PidTagPredecessorChangeList)]; - - if ([container isKindOfClass: MAPIStoreFolderK]) - { - /* table modified */ - for (count = 0; count < max; count++) - { - id table; - - table = [containerTables objectAtIndex: count]; - - /* Safety check here as we could have MAPIStorePermissionsTable instances - in our containerTables array. This code might need to be reworked later */ - if ([table respondsToSelector: @selector(notifyChangesForChild:)]) - [table notifyChangesForChild: self]; - } - [container cleanupCaches]; - } - [self setIsNew: NO]; - rc = MAPISTORE_SUCCESS; - } - else - rc = MAPISTORE_ERR_DENIED; - - return rc; -} - -/* getters */ -- (enum mapistore_error) getPidTagInstID: (void **) data // TODO: DOUBT - inMemCtx: (TALLOC_CTX *) memCtx -{ - /* we return a unique id based on the key */ - *data = MAPILongLongValue (memCtx, [[sogoObject nameInContainer] hash]); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagInstanceNum: (void **) data // TODO: DOUBT - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getLongZero: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagRowType: (void **) data // TODO: DOUBT - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, TBL_LEAF_ROW); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagDepth: (void **) data // TODO: DOUBT - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongLongValue (memCtx, 0); - - return MAPISTORE_SUCCESS; -} - -/* - Possible values are: - - 0x00000001 Modify - 0x00000002 Read - 0x00000004 Delete - 0x00000008 Create Hierarchy Table - 0x00000010 Create Contents Table - 0x00000020 Create Associated Contents Table -*/ -- (enum mapistore_error) getPidTagAccess: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - uint32_t access = 0; - BOOL userIsOwner; - MAPIStoreContext *context; - SOGoUser *ownerUser; - MAPIStoreMessage *mainMessage; - - context = [self context]; - ownerUser = [[self userContext] sogoUser]; - userIsOwner = [[context activeUser] isEqual: ownerUser]; - if (userIsOwner) - mainMessage = nil; - else if ([self isKindOfClass: MAPIStoreEmbeddedMessageK]) - mainMessage = (MAPIStoreMessage *) [[self container] container]; - else - mainMessage = self; - - if (userIsOwner || [mainMessage subscriberCanModifyMessage]) - access |= 0x01; - if (userIsOwner || [mainMessage subscriberCanReadMessage]) - access |= 0x02; - if (userIsOwner - || ([self isKindOfClass: MAPIStoreEmbeddedMessageK] - && [mainMessage subscriberCanModifyMessage]) - || [mainMessage subscriberCanDeleteMessage]) - access |= 0x04; - - *data = MAPILongValue (memCtx, access); - - return MAPISTORE_SUCCESS; -} - -/* - Possible values are: - - 0x00000000 Read-Only - 0x00000001 Modify -*/ -- (enum mapistore_error) getPidTagAccessLevel: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - uint32_t access = 0; - BOOL userIsOwner; - MAPIStoreContext *context; - SOGoUser *ownerUser; - - context = [self context]; - ownerUser = [[self userContext] sogoUser]; - userIsOwner = [[context activeUser] isEqual: ownerUser]; - if (userIsOwner || [self subscriberCanModifyMessage]) - access = 0x01; - else - access = 0; - *data = MAPILongValue (memCtx, access); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagHasNamedProperties: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getYes: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidSideEffects: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getLongZero: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidCurrentVersion: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - // *data = MAPILongValue (memCtx, 115608); // Outlook 11.5608 - *data = MAPILongValue (memCtx, 0x1ce3a); // Outlook 11.8330 - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidCurrentVersionName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [@"11.0" asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidAutoProcessState: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, 0x00000000); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagFolderId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongLongValue (memCtx, [container objectId]); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagMid: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - uint64_t obId; - - obId = [self objectId]; - if (obId == ULLONG_MAX) - rc = MAPISTORE_ERR_NOT_FOUND; - else - { - *data = MAPILongLongValue (memCtx, obId); - rc = MAPISTORE_SUCCESS; - } - - return rc; -} - -- (enum mapistore_error) getPidTagMessageLocaleId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, 0x0409); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagMessageFlags: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, MSGFLAG_FROMME | MSGFLAG_READ | MSGFLAG_UNMODIFIED); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagMessageSize: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - /* TODO: choose another name in SOGo for that method */ - *data = MAPILongValue (memCtx, [[sogoObject davContentLength] intValue]); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagImportance: (void **) data // TODO -> subclass? - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, 1); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagPriority: (void **) data // TODO -> subclass? - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getLongZero: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagSensitivity: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getLongZero: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagSubject: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - TALLOC_CTX *localMemCtx; - char *prefix, *normalizedSubject; - - localMemCtx = talloc_zero (memCtx, TALLOC_CTX); - if ([self getProperty: (void **) &prefix - withTag: PidTagSubjectPrefix - inMemCtx: localMemCtx] - != MAPISTORE_SUCCESS) - prefix = ""; - rc = [self getProperty: (void **) &normalizedSubject - withTag: PidTagNormalizedSubject - inMemCtx: localMemCtx]; - if (rc == MAPISTORE_SUCCESS) - *data = talloc_asprintf (memCtx, "%s%s", prefix, normalizedSubject); - - talloc_free(localMemCtx); - - return rc; -} - -- (enum mapistore_error) getPidTagNormalizedSubject: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidTagOriginalSubject: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagSubject: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagConversationTopic: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagNormalizedSubject: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagSubjectPrefix: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getEmptyString: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagDeleteAfterSubmit: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getNo: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagDisplayTo: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getEmptyString: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagDisplayCc: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getEmptyString: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagDisplayBcc: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getEmptyString: data inMemCtx: memCtx]; -} - -// - (enum mapistore_error) getPidTagOriginalDisplayTo: (void **) data -// { -// return [self getPidTagDisplayTo: data]; -// } - -// - (enum mapistore_error) getPidTagOriginalDisplayCc: (void **) data -// { -// return [self getPidTagDisplayCc: data]; -// } - -// - (enum mapistore_error) getPidTagOriginalDisplayBcc: (void **) data -// { -// return [self getPidTagDisplayBcc: data]; -// } - -- (enum mapistore_error) getPidTagLastModifierName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSURL *contextUrl; - - contextUrl = (NSURL *) [[self context] url]; - *data = [[contextUrl user] asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagMessageClass: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - [self subclassResponsibility: _cmd]; - - return MAPISTORE_ERR_NOT_FOUND; -} - -- (enum mapistore_error) getPidTagOriginalMessageClass: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getProperty: data withTag: PidTagMessageClass inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagHasAttachments: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPIBoolValue (memCtx, - [[self attachmentKeys] count] > 0); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagAssociated: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getNo: data inMemCtx: memCtx];; -} - -- (enum mapistore_error) setReadFlag: (uint8_t) flag -{ - // [self subclassResponsibility: _cmd]; - - return MAPISTORE_ERROR; -} - -- (void) save: (TALLOC_CTX *) memCtx -{ - [self subclassResponsibility: _cmd]; -} - -- (NSArray *) attachmentKeys -{ - if (!attachmentKeys) - { - attachmentKeys = [self attachmentKeysMatchingQualifier: nil - andSortOrderings: nil]; - [attachmentKeys retain]; - } - - return attachmentKeys; -} - -- (NSArray *) attachmentKeysMatchingQualifier: (EOQualifier *) qualifier - andSortOrderings: (NSArray *) sortOrderings -{ - if (qualifier) - [self errorWithFormat: @"qualifier is not used for attachments"]; - if (sortOrderings) - [self errorWithFormat: @"sort orderings are not used for attachments"]; - - return [attachmentParts allKeys]; -} - -- (MAPIStoreAttachmentTable *) attachmentTable -{ - return [MAPIStoreAttachmentTable tableForContainer: self]; -} - -- (void) addActiveTable: (MAPIStoreTable *) activeTable -{ - [activeTables addObject: activeTable]; -} - -- (void) removeActiveTable: (MAPIStoreTable *) activeTable -{ - [activeTables removeObject: activeTable]; -} - -- (NSArray *) activeUserRoles -{ - MAPIStoreContext *context; - MAPIStoreUserContext *userContext; - - if (!activeUserRoles) - { - context = [self context]; - userContext = [self userContext]; - activeUserRoles = [[context activeUser] - rolesForObject: sogoObject - inContext: [userContext woContext]]; - /* We use in this library the roles as flags, so we expand high - access rights with the lower ones */ - activeUserRoles = [self expandRoles: activeUserRoles]; - [activeUserRoles retain]; - } - - return activeUserRoles; -} - -/* Expand current roles with lower access roles to transform them to - flags */ -- (NSArray *) expandRoles: (NSArray *) roles -{ - return roles; -} - -/* Can the current active user read the message? */ -- (BOOL) subscriberCanReadMessage -{ - return NO; -} - -/* Can the current active user modify the message? */ -- (BOOL) subscriberCanModifyMessage -{ - return NO; -} - -/* Can the current active user delete the message? */ -- (BOOL) subscriberCanDeleteMessage -{ - return NO; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreMessageTable.h b/Attic/OpenChange/MAPIStoreMessageTable.h deleted file mode 100644 index 9b1473325..000000000 --- a/Attic/OpenChange/MAPIStoreMessageTable.h +++ /dev/null @@ -1,35 +0,0 @@ -/* MAPIStoreMessageTable.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 MAPISTOREMESSAGETABLE_H -#define MAPISTOREMESSAGETABLE_H - -#import "MAPIStoreTable.h" - -@interface MAPIStoreMessageTable : MAPIStoreTable - -- (void) setSortOrder: (const struct SSortOrderSet *) set; -- (void) notifyChangesForChild: (MAPIStoreMessage *) child; - -@end - -#endif /* MAPISTOREMESSAGETABLE_H */ diff --git a/Attic/OpenChange/MAPIStoreMessageTable.m b/Attic/OpenChange/MAPIStoreMessageTable.m deleted file mode 100644 index f978a5ea6..000000000 --- a/Attic/OpenChange/MAPIStoreMessageTable.m +++ /dev/null @@ -1,93 +0,0 @@ -/* MAPIStoreMessageTable.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -#import - -#import - -#import -#import - -#import "MAPIStoreContext.h" -#import "MAPIStoreFolder.h" -#import "MAPIStoreMessage.h" -#import "MAPIStoreTypes.h" -#import "NSData+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreMessageTable.h" - -@implementation MAPIStoreMessageTable - -- (void) setSortOrder: (const struct SSortOrderSet *) set -{ - [self logWithFormat: @"unimplemented method: %@", NSStringFromSelector (_cmd)]; -} - -- (NSArray *) childKeys -{ - if (!childKeys) - { - childKeys = [(MAPIStoreFolder *) - container messageKeysMatchingQualifier: nil - andSortOrderings: sortOrderings]; - [childKeys retain]; - } - - return childKeys; -} - -- (NSArray *) restrictedChildKeys -{ - NSArray *keys; - - if (!restrictedChildKeys) - { - if (restrictionState != MAPIRestrictionStateAlwaysTrue) - { - if (restrictionState == MAPIRestrictionStateNeedsEval) - keys = [(MAPIStoreFolder *) - container messageKeysMatchingQualifier: restriction - andSortOrderings: sortOrderings]; - else - keys = [NSArray array]; - } - else - keys = [self childKeys]; - - ASSIGN (restrictedChildKeys, keys); - } - - return restrictedChildKeys; -} - -- (id) lookupChild: (NSString *) childKey -{ - return [(MAPIStoreFolder *) container lookupMessage: childKey]; -} - -- (void) notifyChangesForChild: (MAPIStoreMessage *) child -{ - -} - -@end diff --git a/Attic/OpenChange/MAPIStoreNotesContext.h b/Attic/OpenChange/MAPIStoreNotesContext.h deleted file mode 100644 index 0c2f58261..000000000 --- a/Attic/OpenChange/MAPIStoreNotesContext.h +++ /dev/null @@ -1,32 +0,0 @@ -/* MAPIStoreNotesContext.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 MAPISTORENOTESCONTEXT_H -#define MAPISTORENOTESCONTEXT_H - -#import "MAPIStoreDBBaseContext.h" - -@interface MAPIStoreNotesContext : MAPIStoreDBBaseContext - -@end - -#endif /* MAPISTORENOTESCONTEXT_H */ diff --git a/Attic/OpenChange/MAPIStoreNotesContext.m b/Attic/OpenChange/MAPIStoreNotesContext.m deleted file mode 100644 index f5b8b1be3..000000000 --- a/Attic/OpenChange/MAPIStoreNotesContext.m +++ /dev/null @@ -1,77 +0,0 @@ -/* MAPIStoreNotesContext.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 Inverse inc. - * Copyright (C) 2016 Enrique J. Hernandez - * - * 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. - */ - -#import - -#import "MAPIStoreNotesFolder.h" -#import "MAPIStoreMapping.h" - -#import "MAPIStoreNotesContext.h" - -#undef DEBUG -#include - -static Class MAPIStoreNotesFolderK; - -@implementation MAPIStoreNotesContext - -+ (void) initialize -{ - MAPIStoreNotesFolderK = [MAPIStoreNotesFolder class]; -} - -+ (NSString *) MAPIModuleName -{ - return @"notes"; -} - -+ (enum mapistore_context_role) MAPIContextRole -{ - return MAPISTORE_NOTES_ROLE; -} - -- (Class) MAPIStoreFolderClass -{ - return MAPIStoreNotesFolderK; -} - -+ (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName - withIndexing: (struct indexing_context *) indexing - inMemCtx: (TALLOC_CTX *) memCtx -{ - struct mapistore_contexts_list *context; - - context = talloc_zero(memCtx, struct mapistore_contexts_list); - context->url = talloc_asprintf (context, "sogo://%s@notes/", - [[userName stringByReplacingOccurrencesOfString: @"@" - withString: @"%40"] UTF8String]); - // context->name = "Notes personnelles"; - context->main_folder = true; - context->role = MAPISTORE_NOTES_ROLE; - context->tag = "tag"; - context->prev = context; - - return context; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreNotesFolder.h b/Attic/OpenChange/MAPIStoreNotesFolder.h deleted file mode 100644 index 4f049fb4f..000000000 --- a/Attic/OpenChange/MAPIStoreNotesFolder.h +++ /dev/null @@ -1,31 +0,0 @@ -/* MAPIStoreNotesFolder.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTORENOTESFOLDER_H -#define MAPISTORENOTESFOLDER_H - -#import "MAPIStoreDBFolder.h" - -@interface MAPIStoreNotesFolder : MAPIStoreDBFolder -@end - -#endif /* MAPISTORENOTESFOLDER_H */ diff --git a/Attic/OpenChange/MAPIStoreNotesFolder.m b/Attic/OpenChange/MAPIStoreNotesFolder.m deleted file mode 100644 index c3c1c4777..000000000 --- a/Attic/OpenChange/MAPIStoreNotesFolder.m +++ /dev/null @@ -1,41 +0,0 @@ -/* MAPIStoreNotesFolder.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import "MAPIStoreNotesFolder.h" -#import "MAPIStoreNotesMessage.h" -#import "NSString+MAPIStore.h" - -#include - -#import "MAPIStoreNotesFolder.h" - -@implementation MAPIStoreNotesFolder - -- (enum mapistore_error) getPidTagDefaultPostMessageClass: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [@"IPM.StickyNote" asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreNotesMessage.h b/Attic/OpenChange/MAPIStoreNotesMessage.h deleted file mode 100644 index 08c1223d0..000000000 --- a/Attic/OpenChange/MAPIStoreNotesMessage.h +++ /dev/null @@ -1,31 +0,0 @@ -/* MAPIStoreNotesMessage.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTORENOTESMESSAGE_H -#define MAPISTORENOTESMESSAGE_H - -#import "MAPIStoreDBMessage.h" - -@interface MAPIStoreNotesMessage : MAPIStoreDBMessage -@end - -#endif /* MAPISTORENOTESMESSAGE_H */ diff --git a/Attic/OpenChange/MAPIStoreNotesMessage.m b/Attic/OpenChange/MAPIStoreNotesMessage.m deleted file mode 100644 index f594b6c27..000000000 --- a/Attic/OpenChange/MAPIStoreNotesMessage.m +++ /dev/null @@ -1,56 +0,0 @@ -/* MAPIStoreNotesMessage.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import - -#import "MAPIStoreTypes.h" -#import "NSObject+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreNotesMessage.h" - -#include - -@implementation MAPIStoreNotesMessage - -- (enum mapistore_error) getPidTagIconIndex: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - /* 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; -} - -- (enum mapistore_error) getPidTagMessageClass: (void **) data inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [@"IPM.StickyNote" asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreObject.h b/Attic/OpenChange/MAPIStoreObject.h deleted file mode 100644 index abf126658..000000000 --- a/Attic/OpenChange/MAPIStoreObject.h +++ /dev/null @@ -1,103 +0,0 @@ -/* MAPIStoreObject.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTOREOBJECT_H -#define MAPISTOREOBJECT_H - -#include - -#import - -@class NSDate; -@class NSData; -@class NSString; -@class NSMutableArray; -@class NSMutableDictionary; - -@class MAPIStoreContext; -@class MAPIStoreMapping; -@class MAPIStoreObjectProxy; -@class MAPIStoreUserContext; -@class MAPIStoreSOGoObject; - -@interface MAPIStoreObject : NSObject -{ - const IMP *classGetters; - - NSMutableArray *parentContainersBag; - NSMutableArray *proxies; - id container; - NSMutableDictionary *properties; -} - -+ (id) mapiStoreObjectInContainer: (MAPIStoreObject *) newContainer; -- (id) initInContainer: (MAPIStoreObject *) newContainer; - -- (void) addProxy: (MAPIStoreObjectProxy *) newProxy; - -- (MAPIStoreObject *) container; - -- (MAPIStoreContext *) context; -- (MAPIStoreUserContext *) userContext; -- (MAPIStoreMapping *) mapping; - -- (NSString *) url; - -/* properties */ - -- (void) addProperties: (NSDictionary *) newProperties; -- (NSMutableDictionary *) properties; - -/* ops */ -- (enum mapistore_error) getProperties: (struct mapistore_property_data *) data - withTags: (enum MAPITAGS *) tags - andCount: (uint16_t) columnCount - inMemCtx: (TALLOC_CTX *) localMemCtx; - -- (enum mapistore_error) addPropertiesFromRow: (struct SRow *) aRow; - -- (enum mapistore_error) getProperty: (void **) data - withTag: (enum MAPITAGS) propTag - inMemCtx: (TALLOC_CTX *) localMemCtx; - -/* helper getters */ -- (NSData *) getReplicaKeyFromGlobCnt: (uint64_t) objectCnt; -- (enum mapistore_error) getReplicaKey: (void **) data - fromGlobCnt: (uint64_t) objectCnt - inMemCtx: (TALLOC_CTX *) memCtx; - -- (enum mapistore_error) getPidTagCreationTime: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagLastModificationTime: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; - -/* move and copy operations */ -- (void) copyPropertiesToObject: (MAPIStoreObject *) newObject inMemCtx: (TALLOC_CTX *) memCtx; - -/* subclasses */ -- (NSString *) nameInContainer; -- (NSDate *) creationTime; -- (NSDate *) lastModificationTime; - -@end - -#endif /* MAPISTOREOBJECT_H */ diff --git a/Attic/OpenChange/MAPIStoreObject.m b/Attic/OpenChange/MAPIStoreObject.m deleted file mode 100644 index c5c8cacb2..000000000 --- a/Attic/OpenChange/MAPIStoreObject.m +++ /dev/null @@ -1,395 +0,0 @@ -/* MAPIStoreObject.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import -#import -#import -#import -#import -#import -#import - -#import "MAPIStoreContext.h" -#import "MAPIStoreFolder.h" -#import "MAPIStorePropertySelectors.h" -#import "MAPIStoreTypes.h" -#import "MAPIStoreUserContext.h" -#import "NSDate+MAPIStore.h" -#import "NSData+MAPIStore.h" -#import "NSObject+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreObject.h" - -#undef DEBUG -#include -#include -#include -#include -#include - -@implementation MAPIStoreObject - -static Class NSExceptionK, MAPIStoreFolderK; - -+ (void) initialize -{ - NSExceptionK = [NSExceptionK class]; - MAPIStoreFolderK = [MAPIStoreFolder class]; -} - -+ (id) mapiStoreObjectInContainer: (MAPIStoreObject *) newContainer -{ - id newObject; - - newObject = [[self alloc] initInContainer: newContainer]; - [newObject autorelease]; - - return newObject; -} - -- (id) init -{ - if ((self = [super init])) - { - classGetters = (IMP *) MAPIStorePropertyGettersForClass (isa); - parentContainersBag = [NSMutableArray new]; - container = nil; - properties = [NSMutableDictionary new]; - proxies = [NSMutableArray new]; - } - - // [self logWithFormat: @"-init"]; - - return self; -} - -- (id) initInContainer: (MAPIStoreObject *) newContainer -{ - if ((self = [self init])) - { - ASSIGN (container, newContainer); - } - - return self; -} - -- (void) dealloc -{ - // [self logWithFormat: @"-dealloc"]; - [proxies release]; - [properties release]; - [parentContainersBag release]; - [container release]; - [super dealloc]; -} - -- (MAPIStoreObject *) container -{ - return container; -} - -- (MAPIStoreContext *) context -{ - return (MAPIStoreContext *) [container context]; -} - -- (MAPIStoreUserContext *) userContext -{ - return [[self context] userContext]; -} - -- (MAPIStoreMapping *) mapping -{ - return [[self userContext] mapping]; -} - -- (NSString *) url -{ - NSString *containerURL, *urlName, *format; - - containerURL = (NSString *) [container url]; - if ([containerURL hasSuffix: @"/"]) - format = @"%@%@"; - else - format = @"%@/%@"; - - urlName = [[self nameInContainer] - stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]; - return [NSString stringWithFormat: format, containerURL, urlName]; -} - -/* helpers */ - -- (void) addProperties: (NSDictionary *) newNewProperties -{ - [properties addEntriesFromDictionary: newNewProperties]; -} - -- (NSMutableDictionary *) properties -{ - return properties; -} - -- (enum mapistore_error) getProperty: (void **) data - withTag: (enum MAPITAGS) propTag - inMemCtx: (TALLOC_CTX *) memCtx -{ - MAPIStorePropertyGetter method = NULL; - uint16_t propValue; - SEL methodSel; - id value; - enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND; - NSUInteger count, max; - - value = [properties objectForKey: MAPIPropertyKey (propTag)]; - if (value) - rc = [value getValue: data forTag: propTag inMemCtx: memCtx]; - else - { - propValue = (propTag & 0xffff0000) >> 16; - methodSel = MAPIStoreSelectorForPropertyGetter (propValue); - method = (MAPIStorePropertyGetter) classGetters[propValue]; - if (method) - rc = method (self, methodSel, data, memCtx); - } - - if (rc == MAPISTORE_ERR_NOT_FOUND) - { - max = [proxies count]; - for (count = 0; rc == MAPISTORE_ERR_NOT_FOUND && count < max; count++) - rc = [[proxies objectAtIndex: count] - getProperty: data - withTag: propTag - inMemCtx: memCtx]; - } - - return rc; -} - -- (enum mapistore_error) getPidTagCreationTime: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [[self creationTime] asFileTimeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagLastModificationTime: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [[self lastModificationTime] asFileTimeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (BOOL) canGetProperty: (enum MAPITAGS) propTag -{ - uint16_t propValue; - BOOL canGetProperty; - NSUInteger count, max; - - propValue = (propTag >> 16) & 0xffff; - - canGetProperty = (classGetters[propValue] - || [properties objectForKey: MAPIPropertyKey (propTag)]); - max = [proxies count]; - for (count = 0; !canGetProperty && count < max; count++) - canGetProperty = [[proxies objectAtIndex: count] canGetProperty: propTag]; - - return canGetProperty; -} - -- (enum mapistore_error) getProperties: (struct mapistore_property_data *) data - withTags: (enum MAPITAGS *) tags - andCount: (uint16_t) columnCount - inMemCtx: (TALLOC_CTX *) memCtx -{ - uint16_t count; - - for (count = 0; count < columnCount; count++) - data[count].error = [self getProperty: &data[count].data - withTag: tags[count] - inMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (void) addProxy: (MAPIStoreObjectProxy *) newProxy -{ - [proxies addObject: newProxy]; -} - -- (enum mapistore_error) addPropertiesFromRow: (struct SRow *) aRow -{ - struct SPropValue *cValue; - NSUInteger counter; - NSMutableDictionary *newProperties; - id value; - - newProperties = [NSMutableDictionary dictionaryWithCapacity: aRow->cValues]; - for (counter = 0; counter < aRow->cValues; counter++) - { - cValue = aRow->lpProps + counter; - value = NSObjectFromSPropValue (cValue); - if (value == nil) - continue; - - switch (cValue->ulPropTag & 0xffff) - { - case PT_STRING8: - case PT_MV_STRING8: - [self warnWithFormat: - @"attempting to set string property as PR_STRING8: %.8x", - cValue->ulPropTag]; - break; - } - [newProperties setObject: value - forKey: MAPIPropertyKey (cValue->ulPropTag)]; - } - - [self addProperties: newProperties]; - - return MAPISTORE_SUCCESS; -} - -// -// The GlobCnt is 6 bytes long. -// -- (NSData *) getReplicaKeyFromGlobCnt: (uint64_t) objectCnt -{ - struct mapistore_connection_info *connInfo; - NSMutableData *replicaKey; - char buffer[6]; - NSUInteger count; - - connInfo = [[self context] connectionInfo]; - - for (count = 0; count < 6; count++) - { - buffer[count] = objectCnt & 0xff; - objectCnt >>= 8; - } - - replicaKey = [NSMutableData dataWithCapacity: 22]; - [replicaKey appendBytes: &connInfo->replica_guid - length: sizeof (struct GUID)]; - [replicaKey appendBytes: buffer length: 6]; - - return replicaKey; -} - -- (enum mapistore_error) getReplicaKey: (void **) data - fromGlobCnt: (uint64_t) objectCnt - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [[self getReplicaKeyFromGlobCnt: objectCnt] asBinaryInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -/* move and copy operations */ -- (void) copyPropertiesToObject: (MAPIStoreObject *) newObject inMemCtx: (TALLOC_CTX *) memCtx -{ - //TALLOC_CTX *memCtx; - struct SPropTagArray *availableProps; - struct SRow row; - enum MAPITAGS propTag; - bool *exclusions; - NSUInteger count; - enum mapistore_error error; - void *data; - - //memCtx = talloc_zero (NULL, TALLOC_CTX); - - [self getAvailableProperties: &availableProps inMemCtx: memCtx]; - - /* We exclude identity and versioning properties to facilitate copy - operations. If they need to be set (move operations), the caller will need - to take care of them. */ - exclusions = talloc_array (memCtx, bool, 65536); - exclusions[(PidTagRowType >> 16) & 0xffff] = true; - exclusions[(PidTagInstanceKey >> 16) & 0xffff] = true; - exclusions[(PidTagInstanceNum >> 16) & 0xffff] = true; - exclusions[(PidTagInstID >> 16) & 0xffff] = true; - exclusions[(PidTagAttachNumber >> 16) & 0xffff] = true; - exclusions[(PidTagFolderId >> 16) & 0xffff] = true; - exclusions[(PidTagMid >> 16) & 0xffff] = true; - exclusions[(PidTagSourceKey >> 16) & 0xffff] = true; - exclusions[(PidTagParentSourceKey >> 16) & 0xffff] = true; - exclusions[(PidTagParentFolderId >> 16) & 0xffff] = true; - exclusions[(PidTagChangeKey >> 16) & 0xffff] = true; - exclusions[(PidTagChangeNumber >> 16) & 0xffff] = true; - exclusions[(PidTagPredecessorChangeList >> 16) & 0xffff] = true; - - row.cValues = 0; - row.lpProps = talloc_array (memCtx, struct SPropValue, 65535); - - for (count = 0; count < availableProps->cValues; count++) - { - propTag = availableProps->aulPropTag[count]; - if (!exclusions[(propTag >> 16) & 0xffff]) - { - error = [self getProperty: &data withTag: propTag inMemCtx: memCtx]; - if (error == MAPISTORE_SUCCESS && data) - { - set_SPropValue_proptag (row.lpProps + row.cValues, propTag, - data); - row.cValues++; - } - } - } - [newObject addPropertiesFromRow: &row]; - - //talloc_free (memCtx); -} - -/* subclasses */ -- (NSString *) nameInContainer -{ - [self subclassResponsibility: _cmd]; - - return nil; -} - -- (NSDate *) creationTime -{ - [self subclassResponsibility: _cmd]; - - return nil; -} - -- (NSDate *) lastModificationTime -{ - [self subclassResponsibility: _cmd]; - - return nil; -} - -/* logging */ -- (NSString *) loggingPrefix -{ - return [NSString stringWithFormat:@"<%@:%p:%@>", - NSStringFromClass (isa), self, [self nameInContainer]]; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreObjectProxy.h b/Attic/OpenChange/MAPIStoreObjectProxy.h deleted file mode 100644 index 6e9aee13e..000000000 --- a/Attic/OpenChange/MAPIStoreObjectProxy.h +++ /dev/null @@ -1,41 +0,0 @@ -/* MAPIStoreObjectProxy.h - this file is part of SOGo - * - * Copyright (C) 2012 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. - */ - -#ifndef MAPISTOREOBJECTPROXY_H -#define MAPISTOREOBJECTPROXY_H - -#include - -#import - -@interface MAPIStoreObjectProxy : NSObject -{ - const IMP *classGetters; -} - -- (enum mapistore_error) getProperty: (void **) data - withTag: (enum MAPITAGS) propTag - inMemCtx: (TALLOC_CTX *) localMemCtx; - -@end - -#endif /* MAPISTOREOBJECTPROXY_H */ diff --git a/Attic/OpenChange/MAPIStoreObjectProxy.m b/Attic/OpenChange/MAPIStoreObjectProxy.m deleted file mode 100644 index 1fc6157e6..000000000 --- a/Attic/OpenChange/MAPIStoreObjectProxy.m +++ /dev/null @@ -1,67 +0,0 @@ -/* MAPIStoreObjectProxy.m - this file is part of SOGo - * - * Copyright (C) 2012 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 "MAPIStorePropertySelectors.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreObjectProxy.h" - -#undef DEBUG -#include -#include -#include -#include -#include - -@implementation MAPIStoreObjectProxy - -- (id) init -{ - if ((self = [super init])) - { - classGetters = (IMP *) MAPIStorePropertyGettersForClass (isa); - } - - return self; -} - -- (enum mapistore_error) getProperty: (void **) data - withTag: (enum MAPITAGS) propTag - inMemCtx: (TALLOC_CTX *) memCtx -{ - MAPIStorePropertyGetter method; - uint16_t propValue; - SEL methodSel; - enum mapistore_error rc; - - propValue = (propTag & 0xffff0000) >> 16; - methodSel = MAPIStoreSelectorForPropertyGetter (propValue); - method = (MAPIStorePropertyGetter) classGetters[propValue]; - if (method) - rc = method (self, methodSel, data, memCtx); - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -@end diff --git a/Attic/OpenChange/MAPIStorePermissionsTable.h b/Attic/OpenChange/MAPIStorePermissionsTable.h deleted file mode 100644 index 3f951f50c..000000000 --- a/Attic/OpenChange/MAPIStorePermissionsTable.h +++ /dev/null @@ -1,55 +0,0 @@ -/* MAPIStorePermissionsTable.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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 MAPISTOREPERMISSIONSTABLE_H -#define MAPISTOREPERMISSIONSTABLE_H - -#import "MAPIStoreTable.h" - -struct ldb_context; - -@interface MAPIStorePermissionEntry : MAPIStoreObject -{ - NSString *userId; - uint64_t memberId; -} - -+ (id) entryWithUserId: (NSString *) newUserId - andMemberId: (uint64_t) newMemberId - forFolder: (MAPIStoreFolder *) newFolder; -- (id) initWithUserId: (NSString *) newUserId - andMemberId: (uint64_t) newMemberId - forFolder: (MAPIStoreFolder *) newFolder; - -- (NSString *) userId; -- (uint64_t) memberId; - -@end - -@interface MAPIStorePermissionsTable : MAPIStoreTable -{ - NSMutableDictionary *entries; -} - -@end - -#endif /* MAPISTOREPERMISSIONSTABLE_H */ diff --git a/Attic/OpenChange/MAPIStorePermissionsTable.m b/Attic/OpenChange/MAPIStorePermissionsTable.m deleted file mode 100644 index 3bd2f84b7..000000000 --- a/Attic/OpenChange/MAPIStorePermissionsTable.m +++ /dev/null @@ -1,195 +0,0 @@ -/* MAPIStorePermissionsTable.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import -#import -#import -#import -#import -#import - -#import "MAPIStoreContext.h" -#import "MAPIStoreFolder.h" -#import "MAPIStoreTypes.h" -#import "MAPIStoreSamDBUtils.h" -#import "NSData+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStorePermissionsTable.h" - -#undef DEBUG -#include -#include - -@implementation MAPIStorePermissionEntry - -+ (id) entryWithUserId: (NSString *) newUserId - andMemberId: (uint64_t) newMemberId - forFolder: (MAPIStoreFolder *) newFolder -{ - MAPIStorePermissionEntry *newEntry; - - newEntry = [[self alloc] initWithUserId: newUserId andMemberId: newMemberId - forFolder: newFolder]; - [newEntry autorelease]; - - return newEntry; -} - -- (id) initWithUserId: (NSString *) newUserId - andMemberId: (uint64_t) newMemberId - forFolder: (MAPIStoreFolder *) newFolder -{ - if ((self = [self initInContainer: newFolder])) - { - ASSIGN (userId, newUserId); - memberId = newMemberId; - } - - return self; -} - -- (void) dealloc -{ - [userId release]; - [super dealloc]; -} - -- (NSString *) userId -{ - return userId; -} - -- (uint64_t) memberId -{ - return memberId; -} - -- (enum mapistore_error) getPidTagMemberId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongLongValue (memCtx, memberId); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagEntryId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSData *entryId; - struct mapistore_connection_info *connInfo; - - if (memberId == 0 || memberId == ULLONG_MAX) - entryId = [NSData data]; - else - { - connInfo = [(MAPIStoreContext *) [container context] connectionInfo]; - entryId = MAPIStoreInternalEntryId (connInfo, userId); - } - *data = [entryId asBinaryInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagMemberName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *displayName; - - if (memberId == 0) - displayName = @""; - else if (memberId == ULLONG_MAX) - displayName = @"Anonymous"; - else - displayName = [[SOGoUser userWithLogin: userId] cn]; - - *data = [displayName asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagMemberRights: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - uint32_t rights; - NSArray *roles; - - roles = [[(MAPIStoreFolder *) container aclFolder] aclsForUser: userId]; - roles = [(MAPIStoreFolder *) container expandRoles: roles]; - rights = [(MAPIStoreFolder *) container exchangeRightsForRoles: roles]; - - *data = MAPILongValue (memCtx, rights); - - return MAPISTORE_SUCCESS; -} - -@end - -@implementation MAPIStorePermissionsTable - -- (void) dealloc -{ - [entries release]; - [super dealloc]; -} - -- (void) _fetchEntries -{ - NSArray *permEntries; - NSUInteger count, max; - MAPIStorePermissionEntry *entry; - - entries = [NSMutableDictionary new]; - permEntries = [(MAPIStoreFolder *) container permissionEntries]; - max = [permEntries count]; - for (count = 0; count < max; count++) - { - entry = [permEntries objectAtIndex: count]; - [entries setObject: entry forKey: [entry userId]]; - } - - childKeys = [entries allKeys]; - [childKeys retain]; -} - -- (NSArray *) childKeys -{ - if (!entries) - [self _fetchEntries]; - - return childKeys; -} - -- (NSArray *) restrictedChildKeys -{ - return [self childKeys]; -} - -- (id) lookupChild: (NSString *) childKey -{ - if (!entries) - [self _fetchEntries]; - - return [entries objectForKey: childKey]; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreRecurrenceUtils.h b/Attic/OpenChange/MAPIStoreRecurrenceUtils.h deleted file mode 100644 index dbb2f0c19..000000000 --- a/Attic/OpenChange/MAPIStoreRecurrenceUtils.h +++ /dev/null @@ -1,58 +0,0 @@ -/* MAPIStoreRecurrenceUtils.h - this file is part of $PROJECT_NAME_HERE$ - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTORERECURRENCEUTILS_H -#define MAPISTORERECURRENCEUTILS_H - -#include - -#import -#import -#import - -@class iCalEvent; -@class iCalRepeatableEntityObject; -@class iCalRecurrenceRule; - -#define SOGoMinutesPerHour 60 -#define SOGoHoursPerDay 24 -#define SOGoMinutesPerDay (SOGoMinutesPerHour * SOGoHoursPerDay) - -@interface iCalCalendar (MAPIStoreRecurrence) - -- (void) setupRecurrenceWithMasterEntity: (iCalRepeatableEntityObject *) entity - fromRecurrencePattern: (struct RecurrencePattern *) rp - withExceptions: (struct ExceptionInfo *) exInfos - andExceptionCount: (uint16_t) exInfoCount - inTimeZone: (iCalTimeZone *) tz; - -@end - -@interface iCalRecurrenceRule (MAPIStoreRecurrence) - -- (void) fillRecurrencePattern: (struct RecurrencePattern *) rp - withEvent: (iCalEvent *) event - inMemCtx: (TALLOC_CTX *) memCtx; - -@end - -#endif /* MAPISTORERECURRENCEUTILS_H */ diff --git a/Attic/OpenChange/MAPIStoreRecurrenceUtils.m b/Attic/OpenChange/MAPIStoreRecurrenceUtils.m deleted file mode 100644 index 90052474a..000000000 --- a/Attic/OpenChange/MAPIStoreRecurrenceUtils.m +++ /dev/null @@ -1,483 +0,0 @@ -/* MAPIStoreRecurrenceUtils.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import -#import -#import -#import - -#import -#import - -#import -#import -#import -#import -#import -#import -#import - -#import "NSDate+MAPIStore.h" -#import "MAPIStoreRecurrenceUtils.h" -#import "MAPIStoreTypes.h" - -#include -#include -#include -#include - -@implementation iCalCalendar (MAPIStoreRecurrence) - -- (void) setupRecurrenceWithMasterEntity: (iCalRepeatableEntityObject *) entity - fromRecurrencePattern: (struct RecurrencePattern *) rp - withExceptions: (struct ExceptionInfo *) exInfos - andExceptionCount: (uint16_t) exInfoCount - inTimeZone: (iCalTimeZone *) tz - -{ - NSCalendarDate *startDate, *olEndDate, *untilDate, *exDate; - NSString *monthDay, *month; - NSMutableSet *exceptionDates; - NSArray *realExDates; - iCalRecurrenceRule *rule; - iCalByDayMask *byDayMask; - iCalWeekOccurrence weekOccurrence; - iCalWeekOccurrences dayMaskDays; - NSUInteger count, max; - NSInteger bySetPos, tzOffset; - unsigned char maskValue; - - [entity removeAllRecurrenceRules]; - [entity removeAllExceptionRules]; - [entity removeAllExceptionDates]; - - rule = [iCalRecurrenceRule elementWithTag: @"rrule"]; - [entity addToRecurrenceRules: rule]; - - startDate = [entity startDate]; - // DEBUG(5, ("From client:\n")); - // NDR_PRINT_DEBUG(AppointmentRecurrencePattern, pattern); - - memset (&dayMaskDays, 0, sizeof (iCalWeekOccurrences)); - if (rp->PatternType == PatternType_Day) - { - [rule setFrequency: iCalRecurrenceFrequenceDaily]; - [rule setRepeatInterval: rp->Period / SOGoMinutesPerDay]; - } - else if (rp->PatternType == PatternType_Week) - { - [rule setFrequency: iCalRecurrenceFrequenceWeekly]; - [rule setRepeatInterval: rp->Period]; - /* MAPI values for days are the same as in NGCards */ - for (count = 0; count < 7; count++) - { - maskValue = 1 << count; - if ((rp->PatternTypeSpecific.WeekRecurrencePattern & maskValue)) - dayMaskDays[count] = iCalWeekOccurrenceAll; - } - byDayMask = [iCalByDayMask byDayMaskWithDays: dayMaskDays]; - [rule setByDayMask: byDayMask]; - } - else - { - if (rp->RecurFrequency - == RecurFrequency_Monthly) - { - [rule setFrequency: iCalRecurrenceFrequenceMonthly]; - [rule setRepeatInterval: rp->Period]; - } - else if (rp->RecurFrequency - == RecurFrequency_Yearly) - { - [rule setFrequency: iCalRecurrenceFrequenceYearly]; - [rule setRepeatInterval: rp->Period / 12]; - month = [NSString stringWithFormat: @"%d", [startDate monthOfYear]]; - [rule setSingleValue: month forKey: @"bymonth"]; - } - else - [self errorWithFormat: - @"unhandled frequency case for Month pattern type: %d", - rp->RecurFrequency]; - - if ((rp->PatternType & 3) == 3) - { - /* HjMonthNth and MonthNth */ - if (rp->PatternTypeSpecific.MonthRecurrencePattern.WeekRecurrencePattern - == 0x7f) - { - /* firsts or last day of month */ - if (rp->PatternTypeSpecific.MonthRecurrencePattern.N - == RecurrenceN_Last) - monthDay = @"-1"; - else - monthDay = [NSString stringWithFormat: @"%d", - rp->PatternTypeSpecific.MonthRecurrencePattern.N]; - [rule setSingleValue: monthDay forKey: @"bymonthday"]; - } - else if ((rp->PatternTypeSpecific.MonthRecurrencePattern.WeekRecurrencePattern - == 0x3e) /* Nth week day */ - || (rp->PatternTypeSpecific.MonthRecurrencePattern.WeekRecurrencePattern - == 0x41)) /* Nth week-end day */ - { - for (count = 0; count < 7; count++) - { - maskValue = 1 << count; - if ((rp->PatternTypeSpecific.MonthRecurrencePattern.WeekRecurrencePattern - & maskValue)) - dayMaskDays[count] = iCalWeekOccurrenceAll; - } - byDayMask = [iCalByDayMask byDayMaskWithDays: dayMaskDays]; - [rule setByDayMask: byDayMask]; - - if (rp->PatternTypeSpecific.MonthRecurrencePattern.N - == RecurrenceN_Last) - bySetPos = -1; - else - bySetPos = rp->PatternTypeSpecific.MonthRecurrencePattern.N; - - [rule - setSingleValue: [NSString stringWithFormat: @"%d", bySetPos] - forKey: @"bysetpos"]; - } - else - { - if (rp->PatternTypeSpecific.MonthRecurrencePattern.N - < RecurrenceN_Last) - weekOccurrence = (1 - << (rp->PatternTypeSpecific.MonthRecurrencePattern.N - - 1)); - else - weekOccurrence = iCalWeekOccurrenceLast; - - for (count = 0; count < 7; count++) - { - maskValue = 1 << count; - if ((rp->PatternTypeSpecific.MonthRecurrencePattern.WeekRecurrencePattern - & maskValue)) - dayMaskDays[count] = weekOccurrence; - } - byDayMask = [iCalByDayMask byDayMaskWithDays: dayMaskDays]; - [rule setByDayMask: byDayMask]; - } - } - else if ((rp->PatternType & 2) == 2 - || (rp->PatternType & 4) == 4) - { - /* MonthEnd, HjMonth and HjMonthEnd */ - [rule - setSingleValue: [NSString stringWithFormat: @"%d", - rp->PatternTypeSpecific.Day] - forKey: @"bymonthday"]; - } - else - [self errorWithFormat: @"invalid value for PatternType: %.4x", - rp->PatternType]; - } - - switch (rp->EndType) - { - case END_NEVER_END: - case NEVER_END: - break; - case END_AFTER_N_OCCURRENCES: - [rule setRepeatCount: rp->OccurrenceCount]; - break; - case END_AFTER_DATE: - olEndDate = [NSCalendarDate dateFromMinutesSince1601: rp->EndDate]; - untilDate = [NSCalendarDate dateWithYear: [olEndDate yearOfCommonEra] - month: [olEndDate monthOfYear] - day: [olEndDate dayOfMonth] - hour: [startDate hourOfDay] - minute: [startDate minuteOfHour] - second: [startDate secondOfMinute] - timeZone: [startDate timeZone]]; - [rule setUntilDate: untilDate]; - break; - default: - [self errorWithFormat: @"invalid value for EndType: %.4x", - rp->EndType]; - } - - /* exception dates: - - take all deleted instances - - remove all modified instances available in ExceptionInfo from the above set - - add remaining instances, in chronological order - */ - - /* Heuristic to avoid these loops */ - if (rp->DeletedInstanceCount != rp->ModifiedInstanceCount) { - exceptionDates = [NSMutableSet set]; - for (count = 0; count < rp->DeletedInstanceCount; count++) - { - exDate - = [NSDate dateFromMinutesSince1601: rp->DeletedInstanceDates[count]]; - exDate = [exDate hour: [startDate hourOfDay] - minute: [startDate minuteOfHour] - second: [startDate secondOfMinute]]; - [exceptionDates addObject: exDate]; - } - /* Read the exceptions to remove the instances that are modified and not deleted */ - if (exInfos && exInfoCount > 0) - { - for (count = 0; count < exInfoCount; count++) - { - /* The OriginalStartDate is in local time */ - exDate = [NSDate dateFromMinutesSince1601: exInfos[count].OriginalStartDate]; - tzOffset = -[[tz periodForDate: exDate] secondsOffsetFromGMT]; - exDate = [exDate dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: tzOffset]; - [exceptionDates removeObject: exDate]; - } - } - - realExDates = [[exceptionDates allObjects] - sortedArrayUsingSelector: @selector (compare:)]; - max = [realExDates count]; - for (count = 0; count < max; count++) - [entity addToExceptionDates: [realExDates objectAtIndex: count]]; - } -} - -@end - -@implementation iCalRecurrenceRule (MAPIStoreRecurrence) - -- (void) fillRecurrencePattern: (struct RecurrencePattern *) rp - withEvent: (iCalEvent *) event - inMemCtx: (TALLOC_CTX *) memCtx -{ - iCalRecurrenceFrequency freq; - iCalByDayMask *byDayMask; - NSString *byMonthDay, *bySetPos; - NSCalendarDate *startDate, *endDate, *untilDate, *beginOfWeek, *minimumDate, - *moduloDate, *midnight; - iCalWeekOccurrences *days; - NSInteger dayOfWeek, repeatInterval, repeatCount, count, firstOccurrence, - max; - uint32_t nbrMonths, mask; - NSArray *events; - NSMutableArray *deletedDates, *modifiedDates; - - startDate = [event firstRecurrenceStartDate]; - endDate = [event lastPossibleRecurrenceStartDate]; - - rp->ReaderVersion = 0x3004; - rp->WriterVersion = 0x3004; - - rp->StartDate = [[startDate beginOfDay] asMinutesSince1601]; - - untilDate = [self untilDate]; - if (untilDate) - { - rp->EndDate = [untilDate asMinutesSince1601]; - rp->EndType = END_AFTER_DATE; - } - else - { - repeatCount = [self repeatCount]; - if (repeatCount > 0) - { - rp->EndDate = [endDate asMinutesSince1601]; - rp->OccurrenceCount = repeatCount; - rp->EndType = END_AFTER_N_OCCURRENCES; - } - else - { - rp->EndDate = 0x5ae980df; - rp->OccurrenceCount = 0xa; - rp->EndType = END_NEVER_END; - } - } - - freq = [self frequency]; - repeatInterval = [self repeatInterval]; - if (freq == iCalRecurrenceFrequenceDaily) - { - rp->RecurFrequency = RecurFrequency_Daily; - rp->PatternType = PatternType_Day; - rp->Period = repeatInterval * SOGoMinutesPerDay; - rp->FirstDateTime = rp->StartDate % rp->Period; - } - else if (freq == iCalRecurrenceFrequenceWeekly) - { - rp->RecurFrequency = RecurFrequency_Weekly; - rp->PatternType = PatternType_Week; - rp->Period = repeatInterval; - - dayOfWeek = [startDate dayOfWeek]; - - mask = 0; - byDayMask = [self byDayMask]; - if (byDayMask) - { - for (count = 0; count < 7; count++) - if ([byDayMask occursOnDay: count]) - mask |= 1 << count; - } - else - { - /* Set the recurrence pattern using start date */ - mask |= 1 << dayOfWeek; - } - rp->PatternTypeSpecific.WeekRecurrencePattern = mask; - - /* FirstDateTime */ - if (dayOfWeek) - beginOfWeek = [startDate dateByAddingYears: 0 months: 0 - days: -dayOfWeek - hours: 0 minutes: 0 - seconds: 0]; - else - beginOfWeek = startDate; - rp->FirstDateTime = ([[beginOfWeek beginOfDay] asMinutesSince1601] - % (repeatInterval * 10080)); - } - else - { - if (freq == iCalRecurrenceFrequenceMonthly) - { - rp->RecurFrequency = RecurFrequency_Monthly; - rp->Period = repeatInterval; - } - else if (freq == iCalRecurrenceFrequenceYearly) - { - rp->RecurFrequency = RecurFrequency_Yearly; - rp->Period = 12; - if (repeatInterval != 1) - [self errorWithFormat: - @"yearly interval '%d' cannot be converted", - repeatInterval]; - } - else - [self errorWithFormat: @"frequency '%d' cannot be converted", freq]; - - /* FirstDateTime */ - midnight = [[startDate firstDayOfMonth] beginOfDay]; - minimumDate = [NSCalendarDate dateFromMinutesSince1601: 0]; - nbrMonths = (([midnight yearOfCommonEra] - - [minimumDate yearOfCommonEra]) * 12 - + [midnight monthOfYear] - 1); - moduloDate = [minimumDate dateByAddingYears: 0 - months: (nbrMonths % rp->Period) - days: 0 hours: 0 minutes: 0 - seconds: 0]; - rp->FirstDateTime = [moduloDate asMinutesSince1601]; - - byMonthDay = [[self byMonthDay] objectAtIndex: 0]; - if (!byMonthDay && (freq == iCalRecurrenceFrequenceYearly)) - { - byMonthDay = [NSString stringWithFormat: @"%d", [startDate dayOfMonth]]; - [self warnWithFormat: @"no month day specified in yearly" - @" recurrence: we deduce it from the start date: %@", - byMonthDay]; - } - - if (byMonthDay) - { - if ([byMonthDay intValue] < 0) - { - /* This means we cannot handle values of BYMONTHDAY that are < - -7. */ - rp->PatternType = PatternType_MonthNth; - rp->PatternTypeSpecific.MonthRecurrencePattern.WeekRecurrencePattern = 0x7f; - rp->PatternTypeSpecific.MonthRecurrencePattern.N = RecurrenceN_Last; - } - else - { - rp->PatternType = PatternType_Month; - rp->PatternTypeSpecific.Day = [byMonthDay intValue]; - } - } - else - { - rp->PatternType = PatternType_MonthNth; - byDayMask = [self byDayMask]; - mask = 0; - days = [byDayMask weekDayOccurrences]; - if (days) - { - for (count = 0; count < 7; count++) - if (days[0][count]) - mask |= 1 << count; - } - if (mask) - { - rp->PatternTypeSpecific.MonthRecurrencePattern.WeekRecurrencePattern = mask; - bySetPos = [self flattenedValuesForKey: @"bysetpos"]; - if ([bySetPos length]) - rp->PatternTypeSpecific.MonthRecurrencePattern.N - = ([bySetPos hasPrefix: @"-"] - ? RecurrenceN_Last : [bySetPos intValue]); - else - { - firstOccurrence = [byDayMask firstOccurrence]; - if (firstOccurrence) - rp->PatternTypeSpecific.MonthRecurrencePattern.N - = ((firstOccurrence > -1) - ? firstOccurrence : RecurrenceN_Last); - } - } - else - [self errorWithFormat: @"rule for an event that never occurs"]; - } - } - - events = [[event parent] events]; - max = [events count]; - modifiedDates = [NSMutableArray arrayWithCapacity: max]; - for (count = 1; count < max; count++) - { - startDate = [[events objectAtIndex: count] recurrenceId]; - if (startDate) - [modifiedDates addObject: startDate]; - else - [self errorWithFormat: @"missing recurrence-id for event %d", count]; - } - max = [modifiedDates count]; - rp->ModifiedInstanceCount = max; - rp->ModifiedInstanceDates = talloc_array (memCtx, uint32_t, max); - for (count = 0; count < max; count++) - { - startDate = [[modifiedDates objectAtIndex: count] - hour: 0 minute: 0 second: 0]; - *(rp->ModifiedInstanceDates + count) = [startDate asMinutesSince1601]; - } - - deletedDates = [modifiedDates mutableCopy]; - [deletedDates autorelease]; - [deletedDates - addObjectsFromArray: [event exceptionDatesWithTimeZone: utcTZ]]; - [deletedDates sortUsingFunction: NSDateCompare context: NULL]; - - max = [deletedDates count]; - rp->DeletedInstanceCount = max; - rp->DeletedInstanceDates = talloc_array (memCtx, uint32_t, max); - for (count = 0; count < max; count++) - { - startDate = [[deletedDates objectAtIndex: count] - hour: 0 minute: 0 second: 0]; - *(rp->DeletedInstanceDates + count) = [startDate asMinutesSince1601]; - } -} - -@end diff --git a/Attic/OpenChange/MAPIStoreSOGo.m b/Attic/OpenChange/MAPIStoreSOGo.m deleted file mode 100644 index 604482ee7..000000000 --- a/Attic/OpenChange/MAPIStoreSOGo.m +++ /dev/null @@ -1,1751 +0,0 @@ -/* MAPIStoreSOGo.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -/* OpenChange SOGo storage backend */ - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#import "MAPIApplication.h" -#import "MAPIStoreAttachment.h" -#import "MAPIStoreAttachmentTable.h" -#import "MAPIStoreContext.h" -#import "MAPIStoreEmbeddedMessage.h" -#import "MAPIStoreFolder.h" -#import "MAPIStoreMessage.h" -#import "MAPIStoreMailVolatileMessage.h" -#import "MAPIStoreObject.h" -#import "MAPIStoreTable.h" -#import "NSObject+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#include -#include -#include -#include - -static Class MAPIStoreContextK = Nil; -static BOOL leakDebugging = NO; -static BOOL initialization_done = NO; - -#define NS_CURRENT_THREAD_REGISTER() \ - BOOL __nsrct_thread_registered = GSRegisterCurrentThread(); \ - if (!initialization_done) { \ - OC_DEBUG(5, "[SOGo] You should call sogo_backend_init() first. Current thread: %p, pid: %d\n", \ - GSCurrentThread(), getpid()); \ - } \ - OC_DEBUG(5, "[SOGo] --->"); - -#define NS_CURRENT_THREAD_TRY_UNREGISTER(rc) \ - if (__nsrct_thread_registered) { \ - GSUnregisterCurrentThread(); \ - } \ - OC_DEBUG(6, "[SOGo] <--- [%s]", mapistore_errstr (rc)); - -#define TRYCATCH_START @try { -#define TRYCATCH_END(pool) \ - } @catch (NSException * e) { \ - enum mapistore_error ret = sogo_backend_handle_objc_exception(e, __PRETTY_FUNCTION__, __LINE__); \ - mapiapp_cleanup(); \ - [pool release]; \ - NS_CURRENT_THREAD_TRY_UNREGISTER(ret); \ - return ret; \ - } \ - mapiapp_cleanup(); - - -static enum mapistore_error -sogo_backend_unexpected_error() -{ - NSLog (@" UNEXPECTED WEIRDNESS: RECEIVED NO OBJECT"); - abort(); - return MAPISTORE_SUCCESS; -} - -static enum mapistore_error -sogo_backend_handle_objc_exception(NSException *e, const char *fn_name, const int line_no) -{ - NSString *callStackSymbols = nil; - if ([e respondsToSelector:@selector(callStackSymbols)]) - { - callStackSymbols = [[e callStackSymbols] componentsJoinedByString:@"\n\t"]; - } - NSLog(@"[SOGo: %s:%d] - EXCEPTION: %@, reason: %@, backtrace: \n\t%@\n", - fn_name, line_no, [e name], [e reason], callStackSymbols); - - // Another point of view on the stack trace - { - void *frames[128]; - int i, len = backtrace(frames, 128); - char **symbols = backtrace_symbols(frames, len); - NSLog(@"Backtrace using execinfo.h:\n"); - for (i = 0; i < len; ++i) - NSLog(@"\t%s", symbols[i]); - free(symbols); - } - - if ([[e name] isEqual:@"NotImplementedException"]) - { - return MAPISTORE_ERR_NOT_IMPLEMENTED; - } - return MAPISTORE_ERROR; -} - -static void -sogo_backend_atexit (void) -{ - NSAutoreleasePool *pool; - - GSRegisterCurrentThread (); - pool = [NSAutoreleasePool new]; - //NSLog (@"allocated classes:\n%s", GSDebugAllocationList (YES)); - [pool release]; - GSUnregisterCurrentThread (); -} - - -/** - \details Initialize sogo mapistore backend - - \return MAPISTORE_SUCCESS on success -*/ -static enum mapistore_error -sogo_backend_init (void) -{ - NSAutoreleasePool *pool; - SOGoProductLoader *loader; - Class MAPIApplicationK; - NSUserDefaults *ud; - SoProductRegistry *registry; - char *argv[] = { SAMBA_PREFIX "/sbin/samba", NULL }; - NSString *debugLevel; - uint8_t parentLogLevel; - - GSRegisterCurrentThread(); - - if (initialization_done) { - OC_DEBUG(5, "[SOGo] SOGo backend already initialized.\n"); - return MAPISTORE_SUCCESS; - } - - pool = [NSAutoreleasePool new]; - - /* Here we work around a bug in GNUstep which decodes XML user - defaults using the system encoding rather than honouring - the encoding specified in the file. */ - putenv ("GNUSTEP_STRING_ENCODING=NSUTF8StringEncoding"); - //putenv ("NSZombieEnabled=YES"); - - [NSProcessInfo initializeWithArguments: argv - count: 1 - environment: environ]; - - [SOGoSystemDefaults sharedSystemDefaults]; - - /* We force the plugin to base its configuration on the SOGo tree. */ - ud = [NSUserDefaults standardUserDefaults]; - - /* Ensure imap4Connection calls raise Exception if - IMAP connection is not established. See NGImap4Connection.m */ - [ud setBool: YES forKey: @"SoIMAP4ExceptionsEnabled"]; - - if (!leakDebugging && [ud boolForKey: @"SOGoDebugLeaks"]) - { - NSLog (@" leak debugging on"); - GSDebugAllocationActive (YES); - atexit (sogo_backend_atexit); - leakDebugging = YES; - } - - /* Set debug level according to samba */ - parentLogLevel = DEBUGLEVEL_CLASS[DBGC_ALL]; // FIXME: samba logger specific code - if (parentLogLevel >= 4) - debugLevel = @"DEBUG"; - else if (parentLogLevel >= 3) - debugLevel = @"INFO"; - else if (parentLogLevel >= 2) - debugLevel = @"WARN"; - else if (parentLogLevel >= 1) - debugLevel = @"ERROR"; - else - debugLevel = @"FATAL"; - OC_DEBUG(3, "[SOGo] Setting log level to %s", [debugLevel UTF8String]); - [ud setObject: debugLevel forKey: @"NGLogDefaultLogLevel"]; - [ud synchronize]; - - registry = [SoProductRegistry sharedProductRegistry]; - [registry scanForProductsInDirectory: SOGO_BUNDLES_DIR]; - - loader = [SOGoProductLoader productLoader]; - [loader loadProducts: [NSArray arrayWithObject: BACKEND_BUNDLE_NAME]]; - - MAPIApplicationK = NSClassFromString (@"MAPIApplication"); - if (MAPIApplicationK) - [[MAPIApplicationK new] activateApplication]; - - [[SOGoCache sharedCache] disableRequestsCache]; - [[SOGoCache sharedCache] disableLocalCache]; - - MAPIStoreContextK = NSClassFromString (@"MAPIStoreContext"); - - [pool release]; - - OC_DEBUG(5, "[SOGo] backend init SUCCESS. Current thread: %p, pid: %d\n", GSCurrentThread(), getpid()); - initialization_done = YES; - - return MAPISTORE_SUCCESS; -} - -/** - \details Cleanup operation to execute after an action has been performed - so there won't be any conflicts with future calls. - In practice this will deactivate the current user context set on MAPIApp - (which is the current WOApplication), this means two things: (1) set nil - as current user context on MAPIApp and (2) remove woContext from current - thread dictionary (this is used on WOContext.m). -*/ -static void mapiapp_cleanup(void) -{ - Class MAPIApplicationK; - MAPIApplicationK = NSClassFromString (@"MAPIApplication"); - if (MAPIApplicationK) - [[MAPIApplicationK application] cleanup]; -} - -/** - \details Create a connection context to the sogo backend - - \param mem_ctx pointer to the memory context - \param conn_info pointer to the connection information available for this context - (database connection, connected user, replica server info) - \param indexing pointer to the indexing database connection - \param uri pointer to the sogo path - \param private_data pointer to the private backend context - - \note the developer must free allocated private_data -*/ - -static enum mapistore_error -sogo_backend_create_context(TALLOC_CTX *mem_ctx, - struct mapistore_connection_info *conn_info, - struct indexing_context *indexing, - const char *uri, void **context_object) -{ - NSAutoreleasePool *pool; - MAPIStoreContext *context; - enum mapistore_error rc; - - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - if (MAPIStoreContextK) - { - TRYCATCH_START - rc = [MAPIStoreContextK openContext: &context - withURI: uri - connectionInfo: conn_info - andTDBIndexing: indexing]; - if (rc == MAPISTORE_SUCCESS) - *context_object = [context tallocWrapper: mem_ctx]; - TRYCATCH_END(pool) - } - else - rc = MAPISTORE_ERROR; - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - - return rc; -} - -static enum mapistore_error -sogo_backend_create_root_folder (const char *username, - enum mapistore_context_role role, - uint64_t fid, const char *name, - // struct indexing_context *indexing, - TALLOC_CTX *mem_ctx, char **mapistore_urip) -{ - NSAutoreleasePool *pool; - NSString *userName, *folderName; - NSString *mapistoreUri; - enum mapistore_error rc; - - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - if (MAPIStoreContextK) - { - TRYCATCH_START - userName = [NSString stringWithUTF8String: username]; - folderName = [NSString stringWithUTF8String: name]; - rc = [MAPIStoreContextK createRootFolder: &mapistoreUri - withFID: fid - andName: folderName - forUser: userName - withRole: role]; - if (rc == MAPISTORE_SUCCESS) - *mapistore_urip = [mapistoreUri asUnicodeInMemCtx: mem_ctx]; - TRYCATCH_END(pool) - } - else - rc = MAPISTORE_ERROR; - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - - return rc; -} - -static enum mapistore_error -sogo_backend_list_contexts(const char *username, struct indexing_context *indexing, - TALLOC_CTX *mem_ctx, - struct mapistore_contexts_list **contexts_listp) -{ - NSAutoreleasePool *pool; - NSString *userName; - enum mapistore_error rc; - - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - if (MAPIStoreContextK) - { - TRYCATCH_START - userName = [NSString stringWithUTF8String: username]; - *contexts_listp = [MAPIStoreContextK listAllContextsForUser: userName - withIndexing: indexing - inMemCtx: mem_ctx]; - rc = MAPISTORE_SUCCESS; - TRYCATCH_END(pool) - } - else - rc = MAPISTORE_ERROR; - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - - return rc; -} - -// andFID: fid -// uint64_t fid, -// void **private_data) - -/** - \details return the mapistore path associated to a given message or - folder ID - - \param private_data pointer to the current sogo context - \param fmid the folder/message ID to lookup - \param type whether it is a folder or message - \param path pointer on pointer to the path to return - - \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error -*/ -static enum mapistore_error -sogo_context_get_path(void *backend_object, TALLOC_CTX *mem_ctx, - uint64_t fmid, char **path) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreContext *context; - enum mapistore_error rc; - - if (backend_object) - { - wrapper = backend_object; - context = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [context getPath: path ofFMID: fmid inMemCtx: mem_ctx]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_context_get_root_folder(void *backend_object, TALLOC_CTX *mem_ctx, - uint64_t fid, void **folder_object) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreContext *context; - MAPIStoreFolder *folder; - enum mapistore_error rc; - - if (backend_object) - { - wrapper = backend_object; - context = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [context getRootFolder: &folder withFID: fid]; - if (rc == MAPISTORE_SUCCESS) - *folder_object = [folder tallocWrapper: mem_ctx]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -/** - \details Open a folder from the sogo backend - - \param private_data pointer to the current sogo context - \param parent_fid the parent folder identifier - \param fid the identifier of the colder to open - - \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR -*/ -static enum mapistore_error -sogo_folder_open_folder(void *folder_object, TALLOC_CTX *mem_ctx, uint64_t fid, void **childfolder_object) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreFolder *folder, *childFolder; - enum mapistore_error rc; - - if (folder_object) - { - wrapper = folder_object; - folder = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [folder openFolder: &childFolder withFID: fid]; - if (rc == MAPISTORE_SUCCESS) - *childfolder_object = [childFolder tallocWrapper: mem_ctx]; - // [context tearDownRequest]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -/** - \details Create a folder in the sogo backend - - \param private_data pointer to the current sogo context - - \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR -*/ -static enum mapistore_error -sogo_folder_create_folder(void *folder_object, TALLOC_CTX *mem_ctx, - uint64_t fid, struct SRow *aRow, - void **childfolder_object) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreFolder *folder, *childFolder; - enum mapistore_error rc; - - if (folder_object) - { - wrapper = folder_object; - folder = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [folder createFolder: &childFolder withRow: aRow andFID: fid]; - if (rc == MAPISTORE_SUCCESS) - *childfolder_object = [childFolder tallocWrapper: mem_ctx]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -/** - \details Delete a folder from the sogo backend - - \param private_data pointer to the current sogo context - \param parent_fid the FID for the parent of the folder to delete - \param fid the FID for the folder to delete - - \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR -*/ -static enum mapistore_error -sogo_folder_delete(void *folder_object) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreFolder *folder; - enum mapistore_error rc; - - if (folder_object) - { - wrapper = folder_object; - folder = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [folder deleteFolder]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_folder_get_child_count(void *folder_object, enum mapistore_table_type table_type, uint32_t *child_count) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreFolder *folder; - enum mapistore_error rc; - - if (folder_object) - { - wrapper = folder_object; - folder = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [folder getChildCount: child_count ofTableType: table_type]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_folder_open_message(void *folder_object, - TALLOC_CTX *mem_ctx, - uint64_t mid, bool write_access, - void **message_object) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreFolder *folder; - MAPIStoreMessage *message; - enum mapistore_error rc; - - if (folder_object) - { - wrapper = folder_object; - folder = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [folder openMessage: &message - withMID: mid - forWriting: write_access - inMemCtx: mem_ctx]; - if (rc == MAPISTORE_SUCCESS) - *message_object = [message tallocWrapper: mem_ctx]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_folder_create_message(void *folder_object, - TALLOC_CTX *mem_ctx, - uint64_t mid, - uint8_t associated, - void **message_object) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreFolder *folder; - MAPIStoreMessage *message; - enum mapistore_error rc; - - if (folder_object) - { - wrapper = folder_object; - folder = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [folder createMessage: &message - withMID: mid - isAssociated: associated]; - if (rc == MAPISTORE_SUCCESS) - *message_object = [message tallocWrapper: mem_ctx]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_folder_delete_message(void *folder_object, uint64_t mid, uint8_t flags) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreFolder *folder; - enum mapistore_error rc; - - if (folder_object) - { - wrapper = folder_object; - folder = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [folder deleteMessageWithMID: mid andFlags: flags]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_folder_move_copy_messages(void *folder_object, - void *source_folder_object, - TALLOC_CTX *mem_ctx, - uint32_t mid_count, - uint64_t *src_mids, uint64_t *t_mids, - struct Binary_r **target_change_keys, - struct Binary_r **target_predecessor_change_lists, - uint8_t want_copy) -{ - MAPIStoreFolder *sourceFolder, *targetFolder; - NSAutoreleasePool *pool; - struct MAPIStoreTallocWrapper *wrapper; - enum mapistore_error rc; - - if (folder_object) - { - wrapper = folder_object; - targetFolder = wrapper->instance; - - wrapper = source_folder_object; - sourceFolder = wrapper->instance; - - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [targetFolder moveCopyMessagesWithMIDs: src_mids - andCount: mid_count - fromFolder: sourceFolder - withMIDs: t_mids - andChangeKeys: target_change_keys - andPredecessorChangeLists: target_predecessor_change_lists - wantCopy: want_copy - inMemCtx: mem_ctx]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_folder_move_folder(void *folder_object, void *target_folder_object, - TALLOC_CTX *mem_ctx, const char *new_folder_name) -{ - NSAutoreleasePool *pool; - MAPIStoreFolder *moveFolder, *targetFolder; - NSString *newFolderName; - struct MAPIStoreTallocWrapper *wrapper; - enum mapistore_error rc; - - if (folder_object) - { - wrapper = folder_object; - moveFolder = wrapper->instance; - - wrapper = target_folder_object; - if (wrapper) - targetFolder = wrapper->instance; - else - targetFolder = nil; - - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - if (new_folder_name) - newFolderName = [NSString stringWithUTF8String: new_folder_name]; - else - newFolderName = nil; - - TRYCATCH_START - rc = [moveFolder moveCopyToFolder: targetFolder - withNewName: newFolderName - isMove: YES - isRecursive: YES - inMemCtx: mem_ctx]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_folder_copy_folder(void *folder_object, void *target_folder_object, TALLOC_CTX *mem_ctx, - bool recursive, const char *new_folder_name) -{ - NSAutoreleasePool *pool; - MAPIStoreFolder *copyFolder, *targetFolder; - NSString *newFolderName; - struct MAPIStoreTallocWrapper *wrapper; - enum mapistore_error rc; - - if (folder_object) - { - wrapper = folder_object; - copyFolder = wrapper->instance; - - wrapper = target_folder_object; - targetFolder = wrapper->instance; - - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - newFolderName = [NSString stringWithUTF8String: new_folder_name]; - - TRYCATCH_START - rc = [copyFolder moveCopyToFolder: targetFolder - withNewName: newFolderName - isMove: NO - isRecursive: recursive - inMemCtx: mem_ctx]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_folder_get_deleted_fmids(void *folder_object, TALLOC_CTX *mem_ctx, - enum mapistore_table_type table_type, uint64_t change_num, - struct UI8Array_r **fmidsp, uint64_t *cnp) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreFolder *folder; - enum mapistore_error rc; - - if (folder_object) - { - wrapper = folder_object; - folder = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [folder getDeletedFMIDs: fmidsp - andCN: cnp - fromChangeNumber: change_num - inTableType: table_type - inMemCtx: mem_ctx]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_folder_open_table(void *folder_object, TALLOC_CTX *mem_ctx, - enum mapistore_table_type table_type, uint32_t handle_id, - void **table_object, uint32_t *row_count) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreFolder *folder; - MAPIStoreTable *table; - enum mapistore_error rc; - - if (folder_object) - { - wrapper = folder_object; - folder = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [folder getTable: &table - andRowCount: row_count - tableType: table_type - andHandleId: handle_id]; - if (rc == MAPISTORE_SUCCESS) - *table_object = [table tallocWrapper: mem_ctx]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_folder_modify_permissions(void *folder_object, uint8_t flags, - uint16_t pcount, - struct PermissionData *permissions) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreFolder *folder; - enum mapistore_error rc; - - if (folder_object) - { - wrapper = folder_object; - folder = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [folder modifyPermissions: permissions - withCount: pcount - andFlags: flags]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_folder_preload_message_bodies(void *folder_object, enum mapistore_table_type table_type, const struct UI8Array_r *mids) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreFolder *folder; - enum mapistore_error rc; - - if (folder_object) - { - wrapper = folder_object; - folder = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [folder preloadMessageBodiesWithMIDs: mids - ofTableType: table_type]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_message_get_message_data(void *message_object, - TALLOC_CTX *mem_ctx, - struct mapistore_message **msg_dataP) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreMessage *message; - enum mapistore_error rc; - - if (message_object) - { - wrapper = message_object; - message = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - [message getMessageData: msg_dataP - inMemCtx: mem_ctx]; - TRYCATCH_END(pool) - - [pool release]; - rc = MAPISTORE_SUCCESS; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_message_create_attachment (void *message_object, TALLOC_CTX *mem_ctx, void **attachment_object, uint32_t *aidp) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreMessage *message; - MAPIStoreAttachment *attachment; - enum mapistore_error rc; - - if (message_object) - { - wrapper = message_object; - message = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [message createAttachment: &attachment inAID: aidp]; - if (rc == MAPISTORE_SUCCESS) - *attachment_object = [attachment tallocWrapper: mem_ctx]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_message_open_attachment (void *message_object, TALLOC_CTX *mem_ctx, - uint32_t aid, void **attachment_object) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreMessage *message; - MAPIStoreAttachment *attachment; - enum mapistore_error rc; - - if (message_object) - { - wrapper = message_object; - message = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [message getAttachment: &attachment withAID: aid]; - if (rc == MAPISTORE_SUCCESS) - *attachment_object = [attachment tallocWrapper: mem_ctx]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_message_get_attachment_table (void *message_object, TALLOC_CTX *mem_ctx, void **table_object, uint32_t *row_count) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreMessage *message; - MAPIStoreAttachmentTable *table; - enum mapistore_error rc; - - if (message_object) - { - wrapper = message_object; - message = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [message getAttachmentTable: &table - andRowCount: row_count]; - if (rc == MAPISTORE_SUCCESS) - *table_object = [table tallocWrapper: mem_ctx]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_message_modify_recipients (void *message_object, - struct SPropTagArray *columns, - uint16_t count, - struct mapistore_message_recipient *recipients) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreMessage *message; - enum mapistore_error rc; - - if (message_object) - { - wrapper = message_object; - message = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [message modifyRecipientsWithRecipients: recipients - andCount: count - andColumns: columns]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_message_set_read_flag (void *message_object, uint8_t flag) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreMessage *message; - enum mapistore_error rc; - - if (message_object) - { - wrapper = message_object; - message = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [message setReadFlag: flag]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_message_save (void *message_object, TALLOC_CTX *mem_ctx) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreMessage *message; - enum mapistore_error rc; - - if (message_object) - { - wrapper = message_object; - message = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [message saveMessage: mem_ctx]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_message_submit (void *message_object, enum SubmitFlags flags) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreMailVolatileMessage *message; - enum mapistore_error rc; - - if (message_object) - { - wrapper = message_object; - message = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [message submitWithFlags: flags]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_message_attachment_open_embedded_message (void *attachment_object, - TALLOC_CTX *mem_ctx, - void **message_object, - uint64_t *midP, - struct mapistore_message **msg) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreAttachment *attachment; - MAPIStoreEmbeddedMessage *message; - enum mapistore_error rc; - - if (attachment_object) - { - wrapper = attachment_object; - attachment = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [attachment openEmbeddedMessage: &message - withMID: midP - withMAPIStoreMsg: msg - inMemCtx: mem_ctx]; - if (rc == MAPISTORE_SUCCESS) - *message_object = [message tallocWrapper: mem_ctx]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_message_attachment_create_embedded_message (void *attachment_object, - TALLOC_CTX *mem_ctx, - void **message_object, - struct mapistore_message **msg) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreAttachment *attachment; - MAPIStoreEmbeddedMessage *message; - enum mapistore_error rc; - - if (attachment_object) - { - wrapper = attachment_object; - attachment = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [attachment createEmbeddedMessage: &message - withMAPIStoreMsg: msg - inMemCtx: mem_ctx]; - if (rc == MAPISTORE_SUCCESS) - *message_object = [message tallocWrapper: mem_ctx]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error sogo_table_get_available_properties(void *table_object, - TALLOC_CTX *mem_ctx, struct SPropTagArray **propertiesP) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreTable *table; - enum mapistore_error rc; - - if (table_object) - { - wrapper = table_object; - table = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [table getAvailableProperties: propertiesP inMemCtx: mem_ctx]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_table_set_columns (void *table_object, uint16_t count, enum MAPITAGS *properties) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreTable *table; - enum mapistore_error rc; - - if (table_object) - { - wrapper = table_object; - table = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [table setColumns: properties - withCount: count]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_table_set_restrictions (void *table_object, struct mapi_SRestriction *restrictions, uint8_t *table_status) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreTable *table; - enum mapistore_error rc; - - if (table_object) - { - wrapper = table_object; - table = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - [table setRestrictions: restrictions]; - //[table cleanupCaches]; - rc = MAPISTORE_SUCCESS; - *table_status = TBLSTAT_COMPLETE; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_table_set_sort_order (void *table_object, struct SSortOrderSet *sort_order, uint8_t *table_status) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreTable *table; - enum mapistore_error rc; - - if (table_object) - { - wrapper = table_object; - table = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - [table setSortOrder: sort_order]; - [table cleanupCaches]; - rc = MAPISTORE_SUCCESS; - *table_status = TBLSTAT_COMPLETE; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_table_get_row (void *table_object, TALLOC_CTX *mem_ctx, - enum mapistore_query_type query_type, uint32_t row_id, - struct mapistore_property_data **data) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreTable *table; - enum mapistore_error rc; - - if (table_object) - { - wrapper = table_object; - table = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [table getRow: data withRowID: row_id andQueryType: query_type - inMemCtx: mem_ctx]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_table_get_row_count (void *table_object, - enum mapistore_query_type query_type, - uint32_t *row_countp) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreTable *table; - enum mapistore_error rc; - - if (table_object) - { - wrapper = table_object; - table = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [table getRowCount: row_countp - withQueryType: query_type]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_table_handle_destructor (void *table_object, uint32_t handle_id) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreTable *table; - enum mapistore_error rc; - - if (table_object) - { - wrapper = table_object; - table = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - [table destroyHandle: handle_id]; - TRYCATCH_END(pool) - - [pool release]; - rc = MAPISTORE_SUCCESS; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error sogo_properties_get_available_properties(void *object, - TALLOC_CTX *mem_ctx, - struct SPropTagArray **propertiesP) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreObject *propObject; - enum mapistore_error rc; - - if (object) - { - wrapper = object; - propObject = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [propObject getAvailableProperties: propertiesP inMemCtx: mem_ctx]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_properties_get_properties (void *object, - TALLOC_CTX *mem_ctx, - uint16_t count, enum MAPITAGS *properties, - struct mapistore_property_data *data) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreObject *propObject; - enum mapistore_error rc; - - if (object) - { - wrapper = object; - propObject = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [propObject getProperties: data withTags: properties - andCount: count - inMemCtx: mem_ctx]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_properties_set_properties (void *object, struct SRow *aRow) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - MAPIStoreObject *propObject; - enum mapistore_error rc; - - if (object) - { - wrapper = object; - propObject = wrapper->instance; - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - rc = [propObject addPropertiesFromRow: aRow]; - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(rc); - } - else - { - rc = sogo_backend_unexpected_error(); - } - - return rc; -} - -static enum mapistore_error -sogo_manager_generate_uri (TALLOC_CTX *mem_ctx, - const char *user, - const char *folder, - const char *message, - const char *rootURI, - char **uri) -{ - NSAutoreleasePool *pool; - NSString *partialURLString, *username, *directory; - - if (uri == NULL) return MAPISTORE_ERR_INVALID_PARAMETER; - - /* This fixes a crash occurring during the instantiation of the - NSAutoreleasePool below. */ - NS_CURRENT_THREAD_REGISTER(); - pool = [NSAutoreleasePool new]; - - TRYCATCH_START - // printf("rootURI = %s\n", rootURI); - if (rootURI) - partialURLString = [NSString stringWithUTF8String: rootURI]; - else - { - /* sogo uri are of type: sogo://[username]:[password]@[folder type]/folder/id */ - username = [NSString stringWithUTF8String: (user ? user : "*")]; - /* Do proper directory lookup here */ - directory = [NSString stringWithUTF8String: (folder ? folder : "*")]; - partialURLString = [NSString stringWithFormat: @"sogo://%@:*@%@", - [username stringByReplacingOccurrencesOfString: @"@" - withString: @"%40"], - directory]; - } - if (![partialURLString hasSuffix: @"/"]) - partialURLString = [partialURLString stringByAppendingString: @"/"]; - - if (message) - partialURLString = [partialURLString stringByAppendingFormat: @"%s.eml", message]; - - // printf("uri = %s\n", [partialURLString UTF8String]); - *uri = talloc_strdup (mem_ctx, [partialURLString UTF8String]); - TRYCATCH_END(pool) - - [pool release]; - NS_CURRENT_THREAD_TRY_UNREGISTER(MAPISTORE_SUCCESS); - - return MAPISTORE_SUCCESS; -} - -/** - \details Entry point for mapistore SOGO backend - - \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error -*/ -enum mapistore_error mapistore_init_backend(void) -{ - struct mapistore_backend backend; - enum mapistore_error ret; - static BOOL registered = NO; - - if (registered) - ret = MAPISTORE_SUCCESS; - else - { - registered = YES; - - backend.backend.name = "SOGo"; - backend.backend.description = "mapistore SOGo backend"; - backend.backend.namespace = "sogo://"; - backend.backend.init = sogo_backend_init; - backend.backend.create_context = sogo_backend_create_context; - backend.backend.create_root_folder = sogo_backend_create_root_folder; - backend.backend.list_contexts = sogo_backend_list_contexts; - backend.context.get_path = sogo_context_get_path; - backend.context.get_root_folder = sogo_context_get_root_folder; - backend.folder.open_folder = sogo_folder_open_folder; - backend.folder.create_folder = sogo_folder_create_folder; - backend.folder.delete = sogo_folder_delete; - backend.folder.open_message = sogo_folder_open_message; - backend.folder.create_message = sogo_folder_create_message; - backend.folder.delete_message = sogo_folder_delete_message; - backend.folder.move_copy_messages = sogo_folder_move_copy_messages; - backend.folder.move_folder = sogo_folder_move_folder; - backend.folder.copy_folder = sogo_folder_copy_folder; - backend.folder.get_deleted_fmids = sogo_folder_get_deleted_fmids; - backend.folder.get_child_count = sogo_folder_get_child_count; - backend.folder.open_table = sogo_folder_open_table; - backend.folder.modify_permissions = sogo_folder_modify_permissions; - backend.folder.preload_message_bodies = sogo_folder_preload_message_bodies; - backend.message.create_attachment = sogo_message_create_attachment; - backend.message.get_attachment_table = sogo_message_get_attachment_table; - backend.message.open_attachment = sogo_message_open_attachment; - backend.message.open_embedded_message = sogo_message_attachment_open_embedded_message; - backend.message.create_embedded_message = sogo_message_attachment_create_embedded_message; - backend.message.get_message_data = sogo_message_get_message_data; - backend.message.modify_recipients = sogo_message_modify_recipients; - backend.message.set_read_flag = sogo_message_set_read_flag; - backend.message.save = sogo_message_save; - backend.message.submit = sogo_message_submit; - backend.table.get_available_properties = sogo_table_get_available_properties; - backend.table.set_restrictions = sogo_table_set_restrictions; - backend.table.set_sort_order = sogo_table_set_sort_order; - backend.table.set_columns = sogo_table_set_columns; - backend.table.get_row = sogo_table_get_row; - backend.table.get_row_count = sogo_table_get_row_count; - backend.table.handle_destructor = sogo_table_handle_destructor; - backend.properties.get_available_properties = sogo_properties_get_available_properties; - backend.properties.get_properties = sogo_properties_get_properties; - backend.properties.set_properties = sogo_properties_set_properties; - backend.manager.generate_uri = sogo_manager_generate_uri; - - /* Register ourselves with the MAPISTORE subsystem */ - ret = mapistore_backend_register (&backend); - if (ret != MAPISTORE_SUCCESS) - OC_DEBUG(0, "[SOGo] Failed to register the '%s' mapistore backend!\n", backend.backend.name); - } - - return ret; -} diff --git a/Attic/OpenChange/MAPIStoreSOGoObject.h b/Attic/OpenChange/MAPIStoreSOGoObject.h deleted file mode 100644 index dc9748371..000000000 --- a/Attic/OpenChange/MAPIStoreSOGoObject.h +++ /dev/null @@ -1,86 +0,0 @@ -/* MAPIStoreObject.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTORESOGOOBJECT_H -#define MAPISTORESOGOOBJECT_H - -#include - -#import "MAPIStoreObject.h" - -@class NSDate; -@class NSData; -@class NSString; -@class NSMutableArray; -@class NSMutableDictionary; - -@class EOQualifier; - -@class MAPIStoreContext; -@class MAPIStoreFolder; -@class MAPIStoreMapping; -@class MAPIStoreTable; -@class MAPIStoreUserContext; - -@interface MAPIStoreSOGoObject : MAPIStoreObject -{ - id sogoObject; - BOOL isNew; -} - -+ (id) mapiStoreObjectWithSOGoObject: (id) newSOGoObject - inContainer: (MAPIStoreObject *) newContainer; - -- (id) initWithSOGoObject: (id) newSOGoObject - inContainer: (MAPIStoreObject *) newFolder; - -- (void) setIsNew: (BOOL) newIsNew; -- (BOOL) isNew; - -- (id) sogoObject; - -- (MAPIStoreObject *) container; - -- (void) cleanupCaches; - -- (uint64_t) objectId; - -/* implemented getters */ -- (enum mapistore_error) getPidTagDisplayName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagSearchKey: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagGenerateExchangeViews: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagParentSourceKey: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagSourceKey: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTagChangeKey: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; - -/* subclasses */ -- (uint64_t) objectVersion; - -@end - -#endif /* MAPISTORESOGOOBJECT_H */ diff --git a/Attic/OpenChange/MAPIStoreSOGoObject.m b/Attic/OpenChange/MAPIStoreSOGoObject.m deleted file mode 100644 index 497ee5116..000000000 --- a/Attic/OpenChange/MAPIStoreSOGoObject.m +++ /dev/null @@ -1,232 +0,0 @@ -/* MAPIStoreObject.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import -#import -#import -#import -#import -#import -#import -#import - -#import "MAPIStoreContext.h" -#import "MAPIStoreFolder.h" -#import "MAPIStorePropertySelectors.h" -#import "MAPIStoreTypes.h" -#import "MAPIStoreUserContext.h" -#import "NSDate+MAPIStore.h" -#import "NSData+MAPIStore.h" -#import "NSObject+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreSOGoObject.h" - -#undef DEBUG -#include -#include -#include -#include -#include - -@implementation MAPIStoreSOGoObject - -static Class MAPIStoreFolderK; - -+ (void) initialize -{ - MAPIStoreFolderK = [MAPIStoreFolder class]; -} - -+ (id) mapiStoreObjectWithSOGoObject: (id) newSOGoObject - inContainer: (MAPIStoreObject *) newContainer -{ - id newObject; - - newObject = [[self alloc] initWithSOGoObject: newSOGoObject - inContainer: newContainer]; - [newObject autorelease]; - - return newObject; -} - -- (id) init -{ - if ((self = [super init])) - { - sogoObject = nil; - isNew = NO; - } - - // [self logWithFormat: @"-init"]; - - return self; -} - -- (id) initWithSOGoObject: (id) newSOGoObject - inContainer: (MAPIStoreObject *) newContainer -{ - if ((self = [self initInContainer: newContainer])) - { - ASSIGN (sogoObject, newSOGoObject); - } - - return self; -} - -- (void) dealloc -{ - // [self logWithFormat: @"-dealloc"]; - [sogoObject release]; - [super dealloc]; -} - -- (void) setIsNew: (BOOL) newIsNew -{ - isNew = newIsNew; -} - -- (BOOL) isNew -{ - return isNew; -} - -- (id) sogoObject -{ - return sogoObject; -} - -- (MAPIStoreObject *) container -{ - return container; -} - -- (NSString *) nameInContainer -{ - return [sogoObject nameInContainer]; -} - -- (void) cleanupCaches -{ -} - -/* helpers */ -- (uint64_t) objectId -{ - return [container idForObjectWithKey: [sogoObject nameInContainer]]; -} - -/* getters */ -- (enum mapistore_error) getPidTagDisplayName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [[sogoObject displayName] asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagSearchKey: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *stringValue; - - stringValue = [sogoObject nameInContainer]; - *data = [[stringValue dataUsingEncoding: NSASCIIStringEncoding] - asBinaryInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagGenerateExchangeViews: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getNo: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagParentSourceKey: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getReplicaKey: data fromGlobCnt: [container objectId] >> 16 - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagSourceKey: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getReplicaKey: data fromGlobCnt: [self objectId] >> 16 - inMemCtx: memCtx]; -} - -/* helper getters */ -- (enum mapistore_error) getPidTagChangeKey: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - uint64_t obVersion; - - obVersion = [self objectVersion]; - if (obVersion == ULLONG_MAX) - rc = MAPISTORE_ERR_NOT_FOUND; - else - rc = [self getReplicaKey: data fromGlobCnt: obVersion - inMemCtx: memCtx]; - - return rc; -} - -- (enum mapistore_error) getPidTagChangeNumber: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc; - struct mapistore_connection_info *connInfo; - uint64_t obVersion; - - obVersion = [self objectVersion]; - if (obVersion == ULLONG_MAX) - rc = MAPISTORE_ERR_NOT_FOUND; - else - { - connInfo = [[self context] connectionInfo]; - *data = MAPILongLongValue (memCtx, ((obVersion << 16) - | connInfo->repl_id)); - rc = MAPISTORE_SUCCESS; - } - - return rc; -} - -/* subclasses */ -- (uint64_t) objectVersion -{ - [self subclassResponsibility: _cmd]; - - return ULLONG_MAX; -} - -/* logging */ -- (NSString *) loggingPrefix -{ - return [NSString stringWithFormat:@"<%@:%p:%@>", - NSStringFromClass (isa), self, [self nameInContainer]]; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreSamDBUtils.h b/Attic/OpenChange/MAPIStoreSamDBUtils.h deleted file mode 100644 index 84825332b..000000000 --- a/Attic/OpenChange/MAPIStoreSamDBUtils.h +++ /dev/null @@ -1,37 +0,0 @@ -/* MAPIStoreSamDBUtils.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTORESAMDBUTILS_H -#define MAPISTORESAMDBUTILS_H - -@class NSString; - -#include - -NSString *MAPIStoreSamDBUserAttribute (struct mapistore_connection_info *connInfo, - NSString *userKey, - NSString *value, - NSString *attributeName); -NSData *MAPIStoreInternalEntryId (struct mapistore_connection_info *connInfo, NSString *username); -NSData *MAPIStoreExternalEntryId (NSString *cn, NSString *email); - -#endif /* MAPISTORESAMDBUTILS_H */ diff --git a/Attic/OpenChange/MAPIStoreSamDBUtils.m b/Attic/OpenChange/MAPIStoreSamDBUtils.m deleted file mode 100644 index f26d173c2..000000000 --- a/Attic/OpenChange/MAPIStoreSamDBUtils.m +++ /dev/null @@ -1,183 +0,0 @@ -/* MAPIStoreSamDBUtils.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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 -#include -#include -#include -#include - -#import "NSData+MAPIStore.h" - -#import "MAPIStoreSamDBUtils.h" - - - - -NSString * -MAPIStoreSamDBUserAttribute (struct mapistore_connection_info *connInfo, - NSString *userKey, - NSString *value, - NSString *attributeName) -{ - NSString *resultValue = nil; - const char *attrs[] = { "", NULL }; - NSString *searchFormat; - const char *result; - struct ldb_result *res = NULL; - TALLOC_CTX *memCtx; - int ret; - - memCtx = talloc_zero(NULL, TALLOC_CTX); - - attrs[0] = [attributeName UTF8String]; - searchFormat - = [NSString stringWithFormat: @"(&(objectClass=user)(%@=%%s))", userKey]; -#if SAMBA_VERSION_MAJOR <= 4 && SAMBA_VERSION_MINOR < 3 - ret = ldb_search (connInfo->sam_ctx, memCtx, &res, - ldb_get_default_basedn(connInfo->sam_ctx), - LDB_SCOPE_SUBTREE, attrs, - [searchFormat UTF8String], - [value UTF8String]); -#else - ret = safe_ldb_search (&connInfo->sam_ctx, memCtx, &res, - ldb_get_default_basedn(connInfo->sam_ctx), - LDB_SCOPE_SUBTREE, attrs, - [searchFormat UTF8String], - [value UTF8String]); -#endif - - if (ret == LDB_SUCCESS && res->count == 1) - { - result = ldb_msg_find_attr_as_string (res->msgs[0], attrs[0], NULL); - if (result) - resultValue = [NSString stringWithUTF8String: result]; - } - - talloc_free (memCtx); - - return resultValue; -} - -NSData * -MAPIStoreInternalEntryId (struct mapistore_connection_info *connInfo, NSString *username) -{ - static const uint8_t const providerUid[] = { 0xdc, 0xa7, 0x40, 0xc8, - 0xc0, 0x42, 0x10, 0x1a, - 0xb4, 0xb9, 0x08, 0x00, - 0x2b, 0x2f, 0xe1, 0x82 }; - NSMutableData *entryId; - NSData *legacyDNData; - NSString *legacyDN; - - /* structure: - flags: 32 - provideruid: 32 * 4 - version: 32 - type: 32 - X500DN: variable */ - - legacyDN = MAPIStoreSamDBUserAttribute (connInfo, @"sAMAccountName", username, - @"legacyExchangeDN"); - if (legacyDN) - { - entryId = [NSMutableData dataWithCapacity: 256]; - [entryId appendUInt32: 0]; // flags - [entryId appendBytes: providerUid length: 16]; // provideruid - [entryId appendUInt32: 1]; // version - [entryId appendUInt32: 0]; // type (local mail user) - legacyDNData = [legacyDN dataUsingEncoding: NSASCIIStringEncoding]; - [entryId appendData: legacyDNData]; // x500dn - [entryId appendUInt8: 0]; // end of string - } - else - { - NSLog (@"Error trying to generate EntryId for `%@`", username); - entryId = nil; - } - - return entryId; -} - -NSData * -MAPIStoreExternalEntryId (NSString *cn, NSString *email) -{ - NSMutableData *entryId; - static uint8_t providerUid[] = { 0x81, 0x2b, 0x1f, 0xa4, - 0xbe, 0xa3, 0x10, 0x19, - 0x9d, 0x6e, 0x00, 0xdd, - 0x01, 0x0f, 0x54, 0x02 }; - uint8_t flags21, flags22; - - /* structure: - flags: 32 - provideruid: 32 * 4 - version: 16 - { - PaD: 1 - MAE: 2 - Format: 4 - M: 1 - U: 1 - R: 2 - L: 1 - Pad: 4 - } - DisplayName: variable - AddressType: variable - EmailAddress: variable */ - - entryId = [NSMutableData dataWithCapacity: 256]; - [entryId appendUInt32: 0]; // flags - [entryId appendBytes: providerUid length: 16]; // provideruid - [entryId appendUInt16: 0]; // version - - flags21 = 0; /* PaD, MAE, R, Pad = 0 */ - flags21 |= 0x16; /* Format: text and HTML */ - flags21 |= 0x01; /* M: mime format */ - - flags22 = 0x90; /* U: unicode, L: no lookup */ - [entryId appendUInt8: flags21]; - [entryId appendUInt8: flags22]; - - /* DisplayName */ - if (!cn) - cn = @""; - [entryId - appendData: [cn dataUsingEncoding: NSUTF16LittleEndianStringEncoding]]; - [entryId appendUInt16: 0]; - - /* AddressType */ - [entryId - appendData: [@"SMTP" dataUsingEncoding: NSUTF16LittleEndianStringEncoding]]; - [entryId appendUInt16: 0]; - - /* EMailAddress */ - if (!email) - email = @""; - [entryId - appendData: [email dataUsingEncoding: NSUTF16LittleEndianStringEncoding]]; - [entryId appendUInt16: 0]; - - return entryId; -} diff --git a/Attic/OpenChange/MAPIStoreSharingMessage.h b/Attic/OpenChange/MAPIStoreSharingMessage.h deleted file mode 100644 index 101a64d6d..000000000 --- a/Attic/OpenChange/MAPIStoreSharingMessage.h +++ /dev/null @@ -1,101 +0,0 @@ -/* MAPIStoreSharingMessage.h - this file is part of SOGo-OpenChange - * - * Copyright (C) 2015-2016 Enrique J. Hernández - * - * Author: Enrique J. Hernández - * - * 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. - */ - -#ifndef MAPISTORESHARINGMESSAGE_H -#define MAPISTORESHARINGMESSAGE_H - -#import "MAPIStoreMailMessage.h" -#import "MAPIStoreObjectProxy.h" - -#define SHARING_SPECIAL_FOLDER 0x40290 - -@interface MAPIStoreSharingMessage : MAPIStoreObjectProxy -{ - struct mapistore_connection_info *connInfo; - NSMutableDictionary *properties; -} - -- (id) initWithMailHeaders: (NSDictionary *) mailHeaders - andConnectionInfo: (struct mapistore_connection_info *) newConnInfo - fromMessage: (MAPIStoreMailMessage *) msg; - -/* getters */ -- (enum mapistore_error) getPidLidSharingCapabilities: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidNameXSharingCapabilities: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidSharingConfigurationUrl: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidNameXSharingConfigUrl: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidSharingFlavor: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidNameXSharingFlavor: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidSharingInitiatorEntryId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidSharingInitiatorName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidSharingInitiatorSmtp: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidSharingLocalType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidNameXSharingLocalType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidSharingProviderGuid: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidNameXSharingProviderGuid: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidSharingProviderName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidNameXSharingProviderName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidSharingProviderUrl: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidNameXSharingProviderUrl: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidSharingRemoteName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidNameXSharingRemoteName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidSharingRemoteStoreUid: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidNameXSharingRemoteStoreUid: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidSharingRemoteType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidTypeXSharingRemoteType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidSharingResponseTime: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidLidSharingResponseType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getPidNameContentClass: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; - -/* Save */ -- (void) saveWithMessage: (MAPIStoreMailMessage *) msg - andSOGoObject: (SOGoMailObject *) sogoObject; - -@end - -#endif /* MAPISTORECALENDARWRAPPER_H */ diff --git a/Attic/OpenChange/MAPIStoreSharingMessage.m b/Attic/OpenChange/MAPIStoreSharingMessage.m deleted file mode 100644 index 27ecbd47b..000000000 --- a/Attic/OpenChange/MAPIStoreSharingMessage.m +++ /dev/null @@ -1,463 +0,0 @@ -/* MAPIStoreSharingMessage.m - this file is part of SOGo-OpenChange - * - * Copyright (C) 2015-2016 Enrique J. Hernández - * - * Author: Enrique J. Hernández - * - * 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. - */ - -#include - -#import -#import -#import - -#import -#import - -#import "NSData+MAPIStore.h" -#import "NSDate+MAPIStore.h" -#import "NSString+MAPIStore.h" -#import "NSValue+MAPIStore.h" - -#import "MAPIStoreMailFolder.h" -#import "MAPIStoreSharingMessage.h" -#import "MAPIStoreTypes.h" - -#include -#include -#include - -@implementation MAPIStoreSharingMessage - -- (id) init -{ - if ((self = [super init])) - { - connInfo = NULL; - properties = nil; - } - - return self; -} - -- (id) initWithMailHeaders: (NSDictionary *) mailHeaders - andConnectionInfo: (struct mapistore_connection_info *) newConnInfo - fromMessage: (MAPIStoreMailMessage *) msg -{ - NSEnumerator *enumerator; - NSString *key; - - if ((self = [self init])) - { - connInfo = newConnInfo; - enumerator = [mailHeaders keyEnumerator]; - properties = [NSMutableDictionary new]; - while ((key = [enumerator nextObject])) - { - if ([key hasPrefix: @"x-ms-sharing-"]) - [properties setObject: [mailHeaders objectForKey: key] - forKey: key]; - } - - /* Set request properties from container folder */ - NSDictionary *requestProps = [(MAPIStoreMailFolder *)[msg container] - extraPropertiesForMessage: [msg nameInContainer]]; - if (requestProps) - [properties addEntriesFromDictionary: requestProps]; - } - - return self; -} - -- (void) dealloc -{ - [properties release]; - [super dealloc]; -} - -- (enum mapistore_error) _getStringProperty: (NSString *) propertyName - inData: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND; - id value; - - value = [properties objectForKey: propertyName]; - if (value) - { - *data = [value asUnicodeInMemCtx: memCtx]; - rc = MAPISTORE_SUCCESS; - } - - return rc; - -} - -- (enum mapistore_error) getPidLidSharingCapabilities: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - - enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND; - id value; - - value = [properties objectForKey: @"x-ms-sharing-capabilities"]; - if (value) - { - *data = MAPILongValue (memCtx, [value intValue]); - rc = MAPISTORE_SUCCESS; - } - - return rc; -} - -- (enum mapistore_error) getPidNameXSharingCapabilities: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - - enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND; - id value; - - value = [properties objectForKey: @"x-ms-sharing-capabilities"]; - if (value) - { - *data = [[NSString stringWithFormat:@"%X", [value intValue]] - asUnicodeInMemCtx: memCtx]; - rc = MAPISTORE_SUCCESS; - } - - return rc; -} - -- (enum mapistore_error) getPidLidSharingConfigurationUrl: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - - *data = [@"" asUnicodeInMemCtx: memCtx]; - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidNameXSharingConfigUrl: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidLidSharingConfigurationUrl: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidSharingFlavor: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - /* See [MS-OXSHARE] Section 2.2.2.5 for details */ - enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND; - id value, auxValue; - - value = [properties objectForKey: @"x-ms-sharing-flavor"]; - if (value) - { - *data = MAPILongValue (memCtx, [value intValue]); - rc = MAPISTORE_SUCCESS; - } - else - { - /* Guess its value required by old clients based on other properties */ - value = [properties objectForKey: @"x-ms-sharing-capabilities"]; - if (value) - { - if ([value intValue] == SHARING_SPECIAL_FOLDER) - { - value = [properties objectForKey: @"x-ms-sharing-responsetime"]; - auxValue = [properties objectForKey: @"x-ms-sharing-remoteuid"]; - if (value) /* A sharing request */ - { - if (auxValue) - *data = MAPILongValue (memCtx, SHARING_INVITATION_REQUEST_FOLDER); - else - *data = MAPILongValue (memCtx, SHARING_REQUEST_SPECIAL_FOLDER); - } - else - { - if (auxValue) /* It SHOULD be an invitation or response */ - *data = MAPILongValue (memCtx, SHARING_INVITATION_SPECIAL_FOLDER); - else /* No remote info, then denial */ - *data = MAPILongValue (memCtx, SHARING_DENY_REQUEST); - } - } - else - { - *data = MAPILongValue (memCtx, SHARING_INVITATION_FOLDER); - } - rc = MAPISTORE_SUCCESS; - } - } - - return rc; -} - -- (enum mapistore_error) getPidNameXSharingFlavor: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND; - id value; - - value = [properties objectForKey: @"x-ms-sharing-flavor"]; - if (value) - { - *data = [[NSString stringWithFormat:@"%X", [value intValue]] - asUnicodeInMemCtx: memCtx]; - rc = MAPISTORE_SUCCESS; - } - - return rc; -} - -- (enum mapistore_error) getPidLidSharingInitiatorEntryId: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND; - id value; - NSData *entryId; - - value = [properties objectForKey: @"x-ms-sharing-initiatorentryid"]; - if (value) - { - entryId = [value dataByDecodingBase64]; - if (entryId) - { - *data = [entryId asBinaryInMemCtx: memCtx]; - rc = MAPISTORE_SUCCESS; - } - } - - return rc; -} - -- (enum mapistore_error) getPidLidSharingInitiatorName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getStringProperty: @"x-ms-sharing-initiatorname" - inData: data - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidSharingInitiatorSmtp: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getStringProperty: @"x-ms-sharing-initiatorsmtp" - inData: data - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidSharingLocalType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getStringProperty: @"x-ms-sharing-localtype" - inData: data - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidNameXSharingLocalType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidLidSharingLocalType: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidSharingProviderGuid: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - const unsigned char providerGuidBytes[] = {0xAE, 0xF0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}; - NSData *providerGuid = [NSData dataWithBytes: providerGuidBytes length: 16]; - *data = [providerGuid asBinaryInMemCtx: memCtx]; - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidNameXSharingProviderGuid: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [@"AEF0060000000000C000000000000046" asUnicodeInMemCtx: memCtx]; - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidSharingProviderName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - - return [self _getStringProperty: @"x-ms-sharing-providername" - inData: data - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidNameXSharingProviderName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidLidSharingProviderName: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidSharingProviderUrl: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getStringProperty: @"x-ms-sharing-providerurl" - inData: data - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidNameXSharingProviderUrl: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidLidSharingProviderUrl: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidSharingRemoteName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getStringProperty: @"x-ms-sharing-remotename" - inData: data - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidNameXSharingRemoteName: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidLidSharingRemoteName: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidSharingRemoteStoreUid: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getStringProperty: @"x-ms-sharing-remotestoreuid" - inData: data - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidNameXSharingRemoteStoreUid: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidLidSharingRemoteStoreUid: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidSharingRemoteType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getStringProperty: @"x-ms-sharing-remotetype" - inData: data - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTypeXSharingRemoteType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidLidSharingRemoteType: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidSharingRemoteUid: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self _getStringProperty: @"x-ms-sharing-remoteuid" - inData: data - inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidUidXSharingRemoteUid: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidLidSharingRemoteUid: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidSharingResponseTime: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND; - id value; - - value = [properties objectForKey: MAPIPropertyKey (PidLidSharingResponseTime)]; - if (!value) - { - value = [properties objectForKey: @"x-ms-sharing-responsetime"]; - if (value) - { - /* Here the value is a GSCBufferString */ - NSString * responseTime = [NSString stringWithUTF8String: [value UTF8String]]; - value = [NSDate dateWithString: responseTime]; - } - } - - if (value) - { - *data = [value asFileTimeInMemCtx: memCtx]; - rc = MAPISTORE_SUCCESS; - } - - return rc; -} - -- (enum mapistore_error) getPidLidSharingResponseType: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - - enum mapistore_error rc = MAPISTORE_ERR_NOT_FOUND; - id value; - - value = [properties objectForKey: MAPIPropertyKey (PidLidSharingResponseType)]; - if (!value) - value = [properties objectForKey: @"x-ms-sharing-responsetype"]; - - if (value) - { - *data = MAPILongValue (memCtx, [value intValue]); - rc = MAPISTORE_SUCCESS; - } - - return rc; -} - -- (enum mapistore_error) getPidNameContentClass: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = talloc_strdup (memCtx, "Sharing"); - return MAPISTORE_SUCCESS; -} - -- (void) saveWithMessage: (MAPIStoreMailMessage *) msg - andSOGoObject: (SOGoMailObject *) sogoObject -{ - /* Store PidLidSharingResponseType and PidLidSharingResponseTime if - required in versions message from the container as I don't see - other straightforward place to put that information */ - id response; - NSDictionary *propsToStore; - - response = [[msg properties] objectForKey: MAPIPropertyKey (PidLidSharingResponseType)]; - if (response) - { - /* FIXME: Is there any better way to increase the modseq? */ - [sogoObject addFlags: @"\\Draft"]; - [sogoObject removeFlags: @"\\Draft"]; - - /* Store this modification in container folder along the property values */ - propsToStore = [NSDictionary dictionaryWithObjects: - [NSArray arrayWithObjects: response, - [[msg properties] objectForKey: MAPIPropertyKey (PidLidSharingResponseTime)], - nil] - forKeys: - [NSArray arrayWithObjects: MAPIPropertyKey (PidLidSharingResponseType), - MAPIPropertyKey (PidLidSharingResponseTime), nil]]; - - [(MAPIStoreMailFolder *)[msg container] setExtraProperties: propsToStore - forMessage: [msg nameInContainer]]; - } -} - -@end diff --git a/Attic/OpenChange/MAPIStoreTable.h b/Attic/OpenChange/MAPIStoreTable.h deleted file mode 100644 index 63e39dc79..000000000 --- a/Attic/OpenChange/MAPIStoreTable.h +++ /dev/null @@ -1,129 +0,0 @@ -/* MAPIStoreTable.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -#ifndef MAPISTORETABLE_H -#define MAPISTORETABLE_H - -#include - -#import "NSObject+MAPIStore.h" - -#undef DEBUG -#include - -#define SENSITIVITY_NONE 0 -#define SENSITIVITY_PERSONAL 1 -#define SENSITIVITY_PRIVATE 2 -#define SENSITIVITY_COMPANY_CONFIDENTIAL 3 - -typedef enum { - MAPIRestrictionStateAlwaysFalse = NO, - MAPIRestrictionStateAlwaysTrue = YES, - MAPIRestrictionStateNeedsEval, /* needs passing of qualifier to underlying - database */ -} MAPIRestrictionState; - -@class NSArray; -@class NSMutableArray; -@class NSString; -@class EOQualifier; - -@class MAPIStoreObject; - -@interface MAPIStoreTable : NSObject -{ - MAPIStoreObject *container; - - uint32_t handleId; /* hack for identifying tables during notifications */ - - NSArray *childKeys; - NSArray *restrictedChildKeys; - - EOQualifier *restriction; /* should probably be a dictionary too */ - MAPIRestrictionState restrictionState; - NSMutableArray *sortOrderings; - - uint32_t currentRow; - MAPIStoreObject *currentChild; - - enum mapistore_table_type tableType; /* mapistore */ - - /* proof of concept */ - uint16_t columnsCount; - enum MAPITAGS *columns; -} - -+ (id) tableForContainer: (MAPIStoreObject *) newContainer; -+ (Class) childObjectClass; - -- (id) initForContainer: (MAPIStoreObject *) newContainer; - -- (id) container; -- (enum mapistore_table_type) tableType; - -- (void) setHandleId: (uint32_t) newHandleId; -- (void) destroyHandle: (uint32_t) handleId; - -- (id) childAtRowID: (uint32_t) rowId - forQueryType: (enum mapistore_query_type) queryType; - -- (void) cleanupCaches; - -- (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP - inMemCtx: (TALLOC_CTX *) localMemCtx; -- (void) setRestrictions: (const struct mapi_SRestriction *) res; -- (enum mapistore_error) setColumns: (enum MAPITAGS *) newColumns - withCount: (uint16_t) newColumCount; -- (enum mapistore_error) getRow: (struct mapistore_property_data **) dataP - withRowID: (uint32_t) rowId - andQueryType: (enum mapistore_query_type) queryType - inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getRowCount: (uint32_t *) countP - withQueryType: (enum mapistore_query_type) queryType; - -/* helpers */ - -- (SEL) operatorFromRestrictionOperator: (uint32_t) resOp; -- (void) warnUnhandledProperty: (enum MAPITAGS) property - inFunction: (const char *) function; - -/* subclasses */ -- (NSArray *) childKeys; -- (NSArray *) restrictedChildKeys; - -- (id) lookupChild: (NSString *) childKey; - -- (void) setSortOrder: (const struct SSortOrderSet *) set; - -- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property; -- (MAPIRestrictionState) evaluateContentRestriction: (const struct mapi_SContentRestriction *) res - intoQualifier: (EOQualifier **) qualifier; -- (MAPIRestrictionState) evaluatePropertyRestriction: (const struct mapi_SPropertyRestriction *) res - intoQualifier: (EOQualifier **) qualifier; -- (MAPIRestrictionState) evaluateBitmaskRestriction: (const struct mapi_SBitmaskRestriction *) res - intoQualifier: (EOQualifier **) qualifier; -- (MAPIRestrictionState) evaluateExistRestriction: (const struct mapi_SExistRestriction *) res - intoQualifier: (EOQualifier **) qualifier; - -@end - -#endif /* MAPISTORETABLE_H */ diff --git a/Attic/OpenChange/MAPIStoreTable.m b/Attic/OpenChange/MAPIStoreTable.m deleted file mode 100644 index 5bcba670e..000000000 --- a/Attic/OpenChange/MAPIStoreTable.m +++ /dev/null @@ -1,889 +0,0 @@ -/* MAPIStoreTable.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -#import - -#import -#import - -#import -#import "MAPIStoreActiveTables.h" -#import "MAPIStoreObject.h" -#import "MAPIStoreTypes.h" -#import "NSData+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreContext.h" -#import "MAPIStoreObject.h" - -#import "MAPIStoreTable.h" - -#undef DEBUG -#include -#include -#include - -@interface MAPIStoreTable (Private) - -- (MAPIRestrictionState) evaluateRestriction: (const struct mapi_SRestriction *) res - intoQualifier: (EOQualifier **) qualifier; -@end - -static Class NSDataK, NSStringK; - -// static NSString * -// MAPIStringForRestrictionState (MAPIRestrictionState state) -// { -// NSString *stateStr; - -// if (state == MAPIRestrictionStateAlwaysTrue) -// stateStr = @"always true"; -// else if (state == MAPIRestrictionStateAlwaysFalse) -// stateStr = @"always false"; -// else -// stateStr = @"needs eval"; - -// return stateStr; -// } - -// static NSString * -// MAPIStringForRestriction (const struct mapi_SRestriction *resPtr); - -// static NSString * -// _MAPIIndentString(int indent) -// { -// NSString *spaces; -// char *buffer; - -// if (indent > 0) -// { -// buffer = malloc (indent + 1); -// memset (buffer, 32, indent); -// *(buffer+indent) = 0; -// spaces = [NSString stringWithFormat: @"%s", buffer]; -// free (buffer); -// } -// else -// spaces = @""; - -// return spaces; -// } - -// static NSString * -// MAPIStringForAndRestriction (const struct mapi_SAndRestriction *resAnd) -// { -// NSMutableArray *restrictions; -// uint16_t count; - -// restrictions = [NSMutableArray arrayWithCapacity: 8]; -// for (count = 0; count < resAnd->cRes; count++) -// [restrictions addObject: MAPIStringForRestriction ((struct mapi_SRestriction *) resAnd->res + count)]; - -// return [NSString stringWithFormat: @"(%@)", [restrictions componentsJoinedByString: @" && "]]; -// } - -// static NSString * -// MAPIStringForOrRestriction (const struct mapi_SOrRestriction *resOr) -// { -// NSMutableArray *restrictions; -// uint16_t count; - -// restrictions = [NSMutableArray arrayWithCapacity: 8]; -// for (count = 0; count < resOr->cRes; count++) -// [restrictions addObject: MAPIStringForRestriction ((struct mapi_SRestriction *) resOr->res + count)]; - -// return [NSString stringWithFormat: @"(%@)", [restrictions componentsJoinedByString: @" || "]]; -// } - -// static NSString * -// MAPIStringForNotRestriction (const struct mapi_SNotRestriction *resNot) -// { -// return [NSString stringWithFormat: @"!(%@)", -// MAPIStringForRestriction ((struct mapi_SRestriction *) &resNot->res)]; -// } - -// static NSString * -// MAPIStringForContentRestriction (const struct mapi_SContentRestriction *resContent) -// { -// NSString *eqMatch, *caseMatch; -// id value; -// const char *propName; - -// switch (resContent->fuzzy & 0xf) -// { -// case 0: eqMatch = @"eq"; break; -// case 1: eqMatch = @"substring"; break; -// case 2: eqMatch = @"prefix"; break; -// default: eqMatch = @"[unknown]"; -// } - -// switch (((resContent->fuzzy) >> 16) & 0xf) -// { -// case 0: caseMatch = @"fl"; break; -// case 1: caseMatch = @"nc"; break; -// case 2: caseMatch = @"ns"; break; -// case 4: caseMatch = @"lo"; break; -// default: caseMatch = @"[unknown]"; -// } - -// propName = get_proptag_name (resContent->ulPropTag); -// if (!propName) -// propName = ""; - -// value = NSObjectFromMAPISPropValue (&resContent->lpProp); - -// return [NSString stringWithFormat: @"%s(0x%.8x) %@,%@ %@", -// propName, resContent->ulPropTag, eqMatch, caseMatch, value]; -// } - -// static NSString * -// MAPIStringForExistRestriction (const struct mapi_SExistRestriction *resExist) -// { -// const char *propName; - -// propName = get_proptag_name (resExist->ulPropTag); -// if (!propName) -// propName = ""; - -// return [NSString stringWithFormat: @"%s(0x%.8x) IS NOT NULL", propName, resExist->ulPropTag]; -// } - -// static NSString * -// MAPIStringForPropertyRestriction (const struct mapi_SPropertyRestriction *resProperty) -// { -// static NSString *operators[] = { @"<", @"<=", @">", @">=", @"==", @"!=", -// @"=~" }; -// NSString *operator; -// id value; -// const char *propName; - -// propName = get_proptag_name (resProperty->ulPropTag); -// if (!propName) -// propName = ""; - -// if (resProperty->relop >= 0 && resProperty->relop < 7) -// operator = operators[resProperty->relop]; -// else -// operator = [NSString stringWithFormat: @"", resProperty->relop]; -// value = NSObjectFromMAPISPropValue (&resProperty->lpProp); - -// return [NSString stringWithFormat: @"%s(0x%.8x) %@ %@", -// propName, resProperty->ulPropTag, operator, value]; -// } - -// static NSString * -// MAPIStringForBitmaskRestriction (const struct mapi_SBitmaskRestriction *resBitmask) -// { -// NSString *format; -// const char *propName; - -// propName = get_proptag_name (resBitmask->ulPropTag); -// if (!propName) -// propName = ""; - -// if (resBitmask->relMBR == 0) -// format = @"((%s(0x%.8x) & 0x%.8x) == 0)"; -// else -// format = @"((%s(0x%.8x) & 0x%.8x) != 0)"; - -// return [NSString stringWithFormat: format, -// propName, resBitmask->ulPropTag, resBitmask->ulMask]; -// } - -// static NSString * -// MAPIStringForRestriction (const struct mapi_SRestriction *resPtr) -// { -// NSString *restrictionStr; - -// if (resPtr) -// { -// switch (resPtr->rt) -// { -// // RES_CONTENT=(int)(0x3), -// // RES_BITMASK=(int)(0x6), -// // RES_EXIST=(int)(0x8), - -// case 0: restrictionStr = MAPIStringForAndRestriction(&resPtr->res.resAnd); break; -// case 1: restrictionStr = MAPIStringForOrRestriction(&resPtr->res.resOr); break; -// case 2: restrictionStr = MAPIStringForNotRestriction(&resPtr->res.resNot); break; -// case 3: restrictionStr = MAPIStringForContentRestriction(&resPtr->res.resContent); break; -// case 4: restrictionStr = MAPIStringForPropertyRestriction(&resPtr->res.resProperty); break; -// case 6: restrictionStr = MAPIStringForBitmaskRestriction(&resPtr->res.resBitmask); break; -// case 8: restrictionStr = MAPIStringForExistRestriction(&resPtr->res.resExist); break; -// // case 5: MAPIStringForComparePropsRestriction(&resPtr->res.resCompareProps); break; -// // case 7: MAPIStringForPropertyRestriction(&resPtr->res.resProperty); break; -// // case 9: MAPIStringForPropertyRestriction(&resPtr->res.resProperty); break; -// // case 10: MAPIStringForPropertyRestriction(&resPtr->res.resProperty); break; -// default: -// restrictionStr -// = [NSString stringWithFormat: @"[unhandled restriction type: %d]", -// resPtr->rt]; -// } -// } -// else -// restrictionStr = @"[unrestricted]"; - -// return restrictionStr; -// } - -@implementation MAPIStoreTable - -+ (void) initialize -{ - NSDataK = [NSData class]; - NSStringK = [NSString class]; -} - -+ (id) tableForContainer: (MAPIStoreObject *) newContainer -{ - MAPIStoreTable *newTable; - - newTable = [[self alloc] initForContainer: newContainer]; - [newTable autorelease]; - - return newTable; -} - -+ (Class) childObjectClass -{ - [self subclassResponsibility: _cmd]; - - return Nil; -} - -- (id) init -{ - if ((self = [super init])) - { - // [self logWithFormat: @"-init"]; - tableType = MAPISTORE_MESSAGE_TABLE; - handleId = -1; - - container = nil; - - childKeys = nil; - restrictedChildKeys = nil; - - currentRow = (uint32_t) -1; - currentChild = nil; - - restriction = nil; - restrictionState = MAPIRestrictionStateAlwaysTrue; - sortOrderings = nil; - - columns = NULL; - columnsCount = 0; - } - - return self; -} - -- (id) initForContainer: (MAPIStoreObject *) newContainer -{ - if ((self = [self init])) - { - container = newContainer; - } - - return self; -} - -// - (id) retain -// { -// [self logWithFormat: @"-retain"]; -// return [super retain]; -// } - -// - (void) release -// { -// [self logWithFormat: @"-release"]; -// [super release]; -// } - -- (void) dealloc -{ - // [self logWithFormat: @"-dealloc"]; - if (columns) - NSZoneFree (NULL, columns); - [currentChild release]; - [childKeys release]; - [restrictedChildKeys release]; - [sortOrderings release]; - [restriction release]; - [super dealloc]; -} - -- (id) container -{ - return container; -} - -- (enum mapistore_table_type) tableType -{ - return tableType; -} - -- (void) setHandleId: (uint32_t) newHandleId -{ - handleId = newHandleId; - if (newHandleId) - [[MAPIStoreActiveTables activeTables] registerTable: self]; -} - -- (void) destroyHandle: (uint32_t) tableHandleId -{ - if (tableHandleId && (handleId == tableHandleId)) - [[MAPIStoreActiveTables activeTables] unregisterTable: self]; -} - -- (void) cleanupCaches -{ - [restrictedChildKeys release]; - restrictedChildKeys = nil; - [childKeys release]; - childKeys = nil; - [currentChild release]; - currentChild = nil; - currentRow = (uint32_t) -1; -} - -- (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [[isa childObjectClass] getAvailableProperties: propertiesP - inMemCtx: memCtx]; -} - -- (void) setRestrictions: (const struct mapi_SRestriction *) res -{ - //EOQualifier *oldRestriction; - - // [self logWithFormat: @"set restriction to (table type: %d): %@", - // type, MAPIStringForRestriction (res)]; - - //oldRestriction = restriction; - [restriction autorelease]; - if (res) - restrictionState = [self evaluateRestriction: res - intoQualifier: &restriction]; - else - restrictionState = MAPIRestrictionStateAlwaysTrue; - - if (restrictionState == MAPIRestrictionStateNeedsEval) - [restriction retain]; - else - restriction = nil; - - // FIXME: we should not flush the caches if the restrictions matches - [self cleanupCaches]; - - //if (restriction) - // [self logWithFormat: @"restriction set to EOQualifier: %@", -// restriction]; - // else if (oldRestriction) - // [self logWithFormat: @"restriction unset (was %@)", oldRestriction]; -} - -- (MAPIRestrictionState) evaluateNotRestriction: (struct mapi_SNotRestriction *) res - intoQualifier: (EOQualifier **) qualifierPtr -{ - MAPIRestrictionState state, subState; - EONotQualifier *qualifier; - EOQualifier *subQualifier; - - subState = [self evaluateRestriction: (struct mapi_SRestriction *)&res->res - intoQualifier: &subQualifier]; - if (subState == MAPIRestrictionStateAlwaysTrue) - state = MAPIRestrictionStateAlwaysFalse; - else if (subState == MAPIRestrictionStateAlwaysFalse) - state = MAPIRestrictionStateAlwaysTrue; - else - { - state = MAPIRestrictionStateNeedsEval; - qualifier = [[EONotQualifier alloc] initWithQualifier: subQualifier]; - [qualifier autorelease]; - *qualifierPtr = qualifier; - } - - return state; -} - -- (MAPIRestrictionState) evaluateAndRestriction: (struct mapi_SAndRestriction *) res - intoQualifier: (EOQualifier **) qualifierPtr -{ - MAPIRestrictionState state, subState; - EOAndQualifier *qualifier; - EOQualifier *subQualifier; - NSMutableArray *subQualifiers; - uint16_t count; - - state = MAPIRestrictionStateNeedsEval; - - subQualifiers = [NSMutableArray arrayWithCapacity: 8]; - for (count = 0; - state == MAPIRestrictionStateNeedsEval && count < res->cRes; - count++) - { - subState = [self evaluateRestriction: (struct mapi_SRestriction *) res->res + count - intoQualifier: &subQualifier]; - if (subState == MAPIRestrictionStateNeedsEval) - [subQualifiers addObject: subQualifier]; - else if (subState == MAPIRestrictionStateAlwaysFalse) - state = MAPIRestrictionStateAlwaysFalse; - } - - if (state == MAPIRestrictionStateNeedsEval) - { - if ([subQualifiers count] == 0) - state = MAPIRestrictionStateAlwaysTrue; - else - { - qualifier = [[EOAndQualifier alloc] - initWithQualifierArray: subQualifiers]; - [qualifier autorelease]; - *qualifierPtr = qualifier; - } - } - - return state; -} - -- (MAPIRestrictionState) evaluateOrRestriction: (struct mapi_SOrRestriction *) res - intoQualifier: (EOQualifier **) qualifierPtr -{ - MAPIRestrictionState state, subState; - EOOrQualifier *qualifier; - EOQualifier *subQualifier; - NSMutableArray *subQualifiers; - uint16_t count, falseCount; - - state = MAPIRestrictionStateNeedsEval; - - falseCount = 0; - subQualifiers = [NSMutableArray arrayWithCapacity: 8]; - for (count = 0; - state == MAPIRestrictionStateNeedsEval && count < res->cRes; - count++) - { - subState = [self evaluateRestriction: (struct mapi_SRestriction *) res->res + count - intoQualifier: &subQualifier]; - if (subState == MAPIRestrictionStateNeedsEval) - [subQualifiers addObject: subQualifier]; - else if (subState == MAPIRestrictionStateAlwaysTrue) - state = MAPIRestrictionStateAlwaysTrue; - else - falseCount++; - } - - if (falseCount == res->cRes) - state = MAPIRestrictionStateAlwaysFalse; - else if ([subQualifiers count] == 0) - state = MAPIRestrictionStateAlwaysTrue; - - if (state == MAPIRestrictionStateNeedsEval) - { - qualifier = [[EOOrQualifier alloc] - initWithQualifierArray: subQualifiers]; - [qualifier autorelease]; - *qualifierPtr = qualifier; - } - - return state; -} - -- (void) warnUnhandledProperty: (enum MAPITAGS) property - inFunction: (const char *) function -{ - const char *propName; - - propName = get_proptag_name (property); - if (!propName) - propName = ""; - [self warnWithFormat: - @"property %s (%.8x) has no matching field name (%@) in '%s'", - propName, property, self, function]; -} - -- (MAPIRestrictionState) evaluateContentRestriction: (struct mapi_SContentRestriction *) res - intoQualifier: (EOQualifier **) qualifier -{ - NSString *property; - // SEL operator; - id value; - MAPIRestrictionState rc; - - property = [self backendIdentifierForProperty: res->ulPropTag]; - if (property) - { - value = NSObjectFromMAPISPropValue (&res->lpProp); - if ([value isKindOfClass: NSDataK]) - { - value = [[NSString alloc] initWithData: value - encoding: NSUTF8StringEncoding]; - [value autorelease]; - } - else if (![value isKindOfClass: NSStringK]) - [NSException raise: @"MAPIStoreTypeConversionException" - format: @"unhandled content restriction for class '%@'", - NSStringFromClass ([value class])]; - - // switch (res->fuzzy & 0xf) - // { - // case 0: - // operator = EOQualifierOperatorEqual; - // break; - // case 1: - // operator = EOQualifierOperatorLike; - // value = [NSString stringWithFormat: @"%%%@%%", value]; - // break; - // case 2: - // operator = EOQualifierOperatorEqual; - // value = [NSString stringWithFormat: @"%@%%", value]; - // break; - // default: [NSException raise: @"MAPIStoreInvalidOperatorException" - // format: @"fuzzy operator value '%.4x' is invalid", - // res->fuzzy]; - // } - - *qualifier = [[EOKeyValueQualifier alloc] initWithKey: property - operatorSelector: EOQualifierOperatorCaseInsensitiveLike - value: value]; - [*qualifier autorelease]; - - [self logWithFormat: @"%s: resulting qualifier: %@", - __PRETTY_FUNCTION__, *qualifier]; - - rc = MAPIRestrictionStateNeedsEval; - } - else - { - [self warnUnhandledProperty: res->ulPropTag - inFunction: __FUNCTION__]; - - rc = MAPIRestrictionStateAlwaysFalse; - } - - return rc; -} - -- (SEL) operatorFromRestrictionOperator: (uint32_t) resOp -{ - static SEL operators[] = { EOQualifierOperatorLessThan, - EOQualifierOperatorLessThanOrEqualTo, - EOQualifierOperatorGreaterThan, - EOQualifierOperatorGreaterThanOrEqualTo, - EOQualifierOperatorEqual, - EOQualifierOperatorNotEqual, - EOQualifierOperatorContains }; - SEL operator; - - if (resOp < 7) - operator = operators[resOp]; - else - { - operator = NULL; - [NSException raise: @"MAPIStoreRestrictionException" - format: @"unhandled operator type number %d", resOp]; - } - - return operator; -} - -- (MAPIRestrictionState) evaluatePropertyRestriction: (struct mapi_SPropertyRestriction *) res - intoQualifier: (EOQualifier **) qualifier -{ - SEL operator; - id value; - NSString *property; - MAPIRestrictionState rc; - - property = [self backendIdentifierForProperty: res->ulPropTag]; - if (property) - { - operator = [self operatorFromRestrictionOperator: res->relop]; - value = NSObjectFromMAPISPropValue (&res->lpProp); - *qualifier = [[EOKeyValueQualifier alloc] initWithKey: property - operatorSelector: operator - value: value]; - [*qualifier autorelease]; - - rc = MAPIRestrictionStateNeedsEval; - } - else - { - [self warnUnhandledProperty: res->ulPropTag - inFunction: __FUNCTION__]; - rc = MAPIRestrictionStateAlwaysFalse; - } - - return rc; -} - -- (MAPIRestrictionState) evaluateBitmaskRestriction: (struct mapi_SBitmaskRestriction *) res - intoQualifier: (EOQualifier **) qualifier -{ - NSString *property; - MAPIRestrictionState rc; - - property = [self backendIdentifierForProperty: res->ulPropTag]; - if (property) - { - *qualifier = [[EOBitmaskQualifier alloc] initWithKey: property - mask: res->ulMask - isZero: (res->relMBR == BMR_EQZ)]; - [*qualifier autorelease]; - - rc = MAPIRestrictionStateNeedsEval; - } - else - { - [self warnUnhandledProperty: res->ulPropTag - inFunction: __FUNCTION__]; - rc = MAPIRestrictionStateAlwaysFalse; - } - - return rc; -} - -- (MAPIRestrictionState) evaluateExistRestriction: (struct mapi_SExistRestriction *) res - intoQualifier: (EOQualifier **) qualifier -{ - NSString *property; - MAPIRestrictionState rc; - - property = [self backendIdentifierForProperty: res->ulPropTag]; - if (property) - { - *qualifier = [[EOKeyValueQualifier alloc] initWithKey: property - operatorSelector: EOQualifierOperatorNotEqual - value: nil]; - [*qualifier autorelease]; - - rc = MAPIRestrictionStateNeedsEval; - } - else - { - [self warnUnhandledProperty: res->ulPropTag - inFunction: __FUNCTION__]; - rc = MAPIRestrictionStateAlwaysFalse; - } - - return rc; -} - -- (MAPIRestrictionState) evaluateRestriction: (struct mapi_SRestriction *) res - intoQualifier: (EOQualifier **) qualifier -{ - MAPIRestrictionState state; - - switch (res->rt) - { - /* basic operators */ - case RES_AND: state = [self evaluateAndRestriction: &res->res.resAnd - intoQualifier: qualifier]; - break; - case RES_OR: state = [self evaluateOrRestriction: &res->res.resOr - intoQualifier: qualifier]; - break; - case RES_NOT: state = [self evaluateNotRestriction: &res->res.resNot - intoQualifier: qualifier]; - break; - - /* content restrictions */ - case RES_CONTENT: state = [self evaluateContentRestriction: &res->res.resContent - intoQualifier: qualifier]; - break; - case RES_PROPERTY: state = [self evaluatePropertyRestriction: &res->res.resProperty - intoQualifier: qualifier]; - break; - case RES_BITMASK: state = [self evaluateBitmaskRestriction: &res->res.resBitmask - intoQualifier: qualifier]; - break; - - case RES_SIZE: state = MAPIRestrictionStateAlwaysTrue; /* let's cheat a little */ - break; - case RES_EXIST: state = [self evaluateExistRestriction: &res->res.resExist - intoQualifier: qualifier]; - break; - - case RES_COMMENT: - if (res->res.resComment.RestrictionPresent) - state = [self evaluateRestriction: (struct mapi_SRestriction *) res->res.resComment.Restriction.res - intoQualifier: qualifier]; - else - state = MAPIRestrictionStateAlwaysTrue; - break; - - // case 5: MAPIStringForComparePropsRestriction(&resPtr->res.resCompareProps); break; - // case 7: MAPIStringForPropertyRestriction(&resPtr->res.resProperty); break; - // case 9: MAPIStringForPropertyRestriction(&resPtr->res.resProperty); break; - // case 10: MAPIStringForPropertyRestriction(&resPtr->res.resProperty); break; - default: - [NSException raise: @"MAPIStoreRestrictionException" - format: @"unhandled restriction type: %.2x", res->rt]; - state = MAPIRestrictionStateAlwaysTrue; - } - - // [self logRestriction: res withState: state]; - - return state; -} - -/* proof of concept */ -- (enum mapistore_error) setColumns: (enum MAPITAGS *) newColumns - withCount: (uint16_t) newColumnsCount -{ - NSUInteger count; - - if (columns) - NSZoneFree (NULL, columns); - columns = NSZoneMalloc (NULL, newColumnsCount * sizeof (enum MAPITAGS)); - for (count = 0; count < newColumnsCount; count++) - columns[count] = newColumns[count]; - columnsCount = newColumnsCount; - - return MAPISTORE_SUCCESS; -} - -- (id) childAtRowID: (uint32_t) rowId - forQueryType: (enum mapistore_query_type) queryType -{ - id child; - NSArray *children, *restrictedChildren; - NSString *childKey; - - if (rowId == currentRow) - child = currentChild; - else - { - [currentChild release]; - child = nil; - - if (queryType == MAPISTORE_PREFILTERED_QUERY) - { - children = [self restrictedChildKeys]; - restrictedChildren = nil; - } - else - { - children = [self childKeys]; - restrictedChildren = [self restrictedChildKeys]; - } - - if ([children count] > rowId) - { - childKey = [children objectAtIndex: rowId]; - - if (queryType == MAPISTORE_PREFILTERED_QUERY - || [restrictedChildren containsObject: childKey]) - child = [self lookupChild: childKey]; - } - - currentChild = child; - [currentChild retain]; - - if (child) - currentRow = rowId; - else - currentRow = (uint32_t) -1; - } - - return child; -} - -- (NSArray *) childKeys -{ - [self subclassResponsibility: _cmd]; - - return nil; -} - -- (NSArray *) restrictedChildKeys -{ - [self subclassResponsibility: _cmd]; - - return nil; -} - -- (id) lookupChild: (NSString *) childKey -{ - [self subclassResponsibility: _cmd]; - - return nil; -} - -- (enum mapistore_error) getRow: (struct mapistore_property_data **) dataP - withRowID: (uint32_t) rowId - andQueryType: (enum mapistore_query_type) queryType - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSUInteger count; - MAPIStoreObject *child; - struct mapistore_property_data *rowData; - enum mapistore_error rc; - - child = [self childAtRowID: rowId forQueryType: queryType]; - if (child) - { - rowData = talloc_array(memCtx, struct mapistore_property_data, columnsCount); - for (count = 0; count < columnsCount; count++) - rowData[count].error = [child getProperty: &rowData[count].data - withTag: columns[count] - inMemCtx: memCtx]; - *dataP = rowData; - rc = MAPISTORE_SUCCESS; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getRowCount: (uint32_t *) countP - withQueryType: (enum mapistore_query_type) queryType -{ - NSArray *children; - - if (queryType == MAPISTORE_PREFILTERED_QUERY) - children = [self restrictedChildKeys]; - else - children = [self childKeys]; - - *countP = [children count]; - - return MAPISTORE_SUCCESS; -} - -/* subclasses */ -- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property -{ - [self subclassResponsibility: _cmd]; - - return nil; -} - -- (void) setSortOrder: (const struct SSortOrderSet *) set -{ - [self subclassResponsibility: _cmd]; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreTasksContext.h b/Attic/OpenChange/MAPIStoreTasksContext.h deleted file mode 100644 index 70d416130..000000000 --- a/Attic/OpenChange/MAPIStoreTasksContext.h +++ /dev/null @@ -1,32 +0,0 @@ -/* MAPIStoreTasksContext.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 MAPISTORETASKSCONTEXT_H -#define MAPISTORETASKSCONTEXT_H - -#import "MAPIStoreGCSBaseContext.h" - -@interface MAPIStoreTasksContext : MAPIStoreGCSBaseContext - -@end - -#endif /* MAPISTORETASKSCONTEXT_H */ diff --git a/Attic/OpenChange/MAPIStoreTasksContext.m b/Attic/OpenChange/MAPIStoreTasksContext.m deleted file mode 100644 index 096ca3711..000000000 --- a/Attic/OpenChange/MAPIStoreTasksContext.m +++ /dev/null @@ -1,63 +0,0 @@ -/* MAPIStoreTasksContext.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -#import -#import - -#import "MAPIStoreTasksFolder.h" -#import "MAPIStoreUserContext.h" - -#import "MAPIStoreTasksContext.h" - -#undef DEBUG -#include - -static Class MAPIStoreTasksFolderK; - -@implementation MAPIStoreTasksContext - -+ (void) initialize -{ - MAPIStoreTasksFolderK = [MAPIStoreTasksFolder class]; -} - -+ (NSString *) MAPIModuleName -{ - return @"tasks"; -} - -+ (enum mapistore_context_role) MAPIContextRole -{ - return MAPISTORE_TASKS_ROLE; -} - -- (Class) MAPIStoreFolderClass -{ - return MAPIStoreTasksFolderK; -} - -+ (NSString *) folderNameSuffix -{ - return @"t"; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreTasksFolder.h b/Attic/OpenChange/MAPIStoreTasksFolder.h deleted file mode 100644 index 3d16a44ae..000000000 --- a/Attic/OpenChange/MAPIStoreTasksFolder.h +++ /dev/null @@ -1,32 +0,0 @@ -/* MAPIStoreTasksFolder.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTORETASKSFOLDER_H -#define MAPISTORETASKSFOLDER_H - -#import "MAPIStoreCalTaskFolder.h" - -@interface MAPIStoreTasksFolder : MAPIStoreCalTaskFolder - -@end - -#endif /* MAPISTORETASKSFOLDER_H */ diff --git a/Attic/OpenChange/MAPIStoreTasksFolder.m b/Attic/OpenChange/MAPIStoreTasksFolder.m deleted file mode 100644 index 4b198d2d1..000000000 --- a/Attic/OpenChange/MAPIStoreTasksFolder.m +++ /dev/null @@ -1,201 +0,0 @@ -/* MAPIStoreTasksFolder.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#import "MAPIApplication.h" -#import "MAPIStoreUserContext.h" -#import "MAPIStoreTasksContext.h" -#import "MAPIStoreTasksMessage.h" -#import "MAPIStoreTasksMessageTable.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreTasksFolder.h" - -#include -#include -#include - -@implementation MAPIStoreTasksFolder - -- (MAPIStoreMessageTable *) messageTable -{ - [self synchroniseCache]; - return [MAPIStoreTasksMessageTable tableForContainer: self]; -} - -- (NSString *) component -{ - return @"vtodo"; -} - -- (MAPIStoreMessage *) createMessage -{ - MAPIStoreMessage *newMessage; - SOGoTaskObject *newEntry; - NSString *name; - - [[[self context] userContext] activate]; - name = [NSString stringWithFormat: @"%@.ics", - [SOGoObject globallyUniqueObjectId]]; - newEntry = [SOGoTaskObject objectWithName: name - inContainer: sogoObject]; - [newEntry setIsNew: YES]; - newMessage = [MAPIStoreTasksMessage mapiStoreObjectWithSOGoObject: newEntry - inContainer: self]; - - - return newMessage; -} - -// -------------------------------------------- -// Permissions and sharing -// -------------------------------------------- - -- (NSArray *) rolesForExchangeRights: (uint32_t) rights -{ - NSMutableArray *roles; - - roles = [NSMutableArray arrayWithCapacity: 6]; - if (rights & RightsCreateItems) - [roles addObject: SOGoRole_ObjectCreator]; - - if (rights & RightsDeleteAll) - [roles addObject: SOGoRole_ObjectEraser]; - if (rights & RightsDeleteOwn) - [roles addObject: MAPIStoreRightDeleteOwn]; - - if (rights & RightsEditAll) - { - [roles addObject: SOGoCalendarRole_PublicModifier]; - [roles addObject: SOGoCalendarRole_PrivateModifier]; - [roles addObject: SOGoCalendarRole_ConfidentialModifier]; - } - if (rights & RightsEditOwn) - [roles addObject: MAPIStoreRightEditOwn]; - - if (rights & RightsReadItems) - { - [roles addObject: SOGoCalendarRole_PublicViewer]; - [roles addObject: SOGoCalendarRole_PrivateViewer]; - [roles addObject: SOGoCalendarRole_ConfidentialViewer]; - } - - if (rights & RightsFolderOwner) - [roles addObject: MAPIStoreRightFolderOwner]; - - if (rights & RightsFolderContact) - [roles addObject: MAPIStoreRightFolderContact]; - - return roles; -} - -- (uint32_t) exchangeRightsForRoles: (NSArray *) roles -{ - uint32_t rights = 0; - - if ([roles containsObject: SOGoRole_ObjectCreator]) - rights |= RightsCreateItems; - if ([roles containsObject: SOGoRole_ObjectEraser]) - rights |= RightsDeleteAll | RightsDeleteOwn; - if ([roles containsObject: SOGoCalendarRole_PublicModifier] - && [roles containsObject: SOGoCalendarRole_PrivateModifier] - && [roles containsObject: SOGoCalendarRole_ConfidentialModifier]) - rights |= RightsReadItems | RightsEditAll | RightsEditOwn; - else if ([roles containsObject: SOGoCalendarRole_PublicViewer] - && [roles containsObject: SOGoCalendarRole_PrivateViewer] - && [roles containsObject: SOGoCalendarRole_ConfidentialViewer]) - rights |= RightsReadItems; - - if ([roles containsObject: MAPIStoreRightEditOwn]) - rights |= RightsEditOwn; - if ([roles containsObject: MAPIStoreRightDeleteOwn]) - rights |= RightsDeleteOwn; - - if (rights != 0) - rights |= RoleNone; /* actually "folder visible" */ - - if ([roles containsObject: MAPIStoreRightFolderOwner]) - rights |= RightsFolderOwner | RoleNone; - - if ([roles containsObject: MAPIStoreRightFolderContact]) - rights |= RightsFolderContact; - - return rights; -} - -- (BOOL) subscriberCanModifyMessages -{ - static NSArray *modifierRoles = nil; - - if (!modifierRoles) - modifierRoles = [[NSArray alloc] initWithObjects: - SOGoCalendarRole_PublicModifier, - SOGoCalendarRole_PrivateModifier, - SOGoCalendarRole_ConfidentialModifier, - nil]; - - return ([[self activeUserRoles] firstObjectCommonWithArray: modifierRoles] - != nil); -} - -- (BOOL) subscriberCanReadMessages -{ - static NSArray *viewerRoles = nil; - - if (!viewerRoles) - viewerRoles = [[NSArray alloc] initWithObjects: - SOGoCalendarRole_PublicViewer, - SOGoCalendarRole_PrivateViewer, - SOGoCalendarRole_ConfidentialViewer, - nil]; - - return ([[self activeUserRoles] firstObjectCommonWithArray: viewerRoles] - != nil); -} - -- (EOQualifier *) aclQualifier -{ - return [EOQualifier qualifierWithQualifierFormat: - [(SOGoAppointmentFolder *) sogoObject aclSQLListingFilter]]; -} - -// -------------------------------------------- -// Property getters -// -------------------------------------------- -- (enum mapistore_error) getPidTagDefaultPostMessageClass: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [@"IPM.Task" asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreTasksMessage.h b/Attic/OpenChange/MAPIStoreTasksMessage.h deleted file mode 100644 index 360c516ad..000000000 --- a/Attic/OpenChange/MAPIStoreTasksMessage.h +++ /dev/null @@ -1,32 +0,0 @@ -/* MAPIStoreTasksMessage.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef MAPISTORETASKSMESSAGE_H -#define MAPISTORETASKSMESSAGE_H - -#import "MAPIStoreCalTaskMessage.h" - -@interface MAPIStoreTasksMessage : MAPIStoreCalTaskMessage - -@end - -#endif /* MAPISTORETASKSMESSAGE_H */ diff --git a/Attic/OpenChange/MAPIStoreTasksMessage.m b/Attic/OpenChange/MAPIStoreTasksMessage.m deleted file mode 100644 index 3cd3f1bfd..000000000 --- a/Attic/OpenChange/MAPIStoreTasksMessage.m +++ /dev/null @@ -1,580 +0,0 @@ -/* MAPIStoreTasksMessage.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 Inverse inc - * - * Author: Wolfgang Sourdeau - * Ludovic Marcotte - * - * 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. - */ - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#import "MAPIStoreContext.h" -#import "MAPIStoreTasksFolder.h" -#import "MAPIStoreTypes.h" -#import "MAPIStoreUserContext.h" -#import "NSDate+MAPIStore.h" -#import "NSObject+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreTasksMessage.h" - -#undef DEBUG -#include -#include -#include -#include -#include - -@implementation SOGoTaskObject (MAPIStoreExtension) - -- (Class) mapistoreMessageClass -{ - return [MAPIStoreTasksMessage class]; -} - -@end - -@implementation MAPIStoreTasksMessage - -- (enum mapistore_error) getPidTagIconIndex: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - /* 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; -} - -- (enum mapistore_error) getPidTagMessageClass: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = talloc_strdup(memCtx, "IPM.Task"); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagNormalizedSubject: (void **) data // SUMMARY - inMemCtx: (TALLOC_CTX *) memCtx -{ - iCalToDo *task; - - task = [sogoObject component: NO secure: YES]; - *data = [[task summary] asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -/* FIXME: Should be combined somehow with the code in MAPIStoreAppointmentWrapper.m */ -- (enum mapistore_error) getPidTagBody: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_SUCCESS; - NSString *stringValue; - iCalToDo *task; - - /* FIXME: there is a confusion in NGCards around "comment" and "description" */ - task = [sogoObject component: NO secure: YES]; - stringValue = [task comment]; - if ([stringValue length] > 0) - *data = [stringValue asUnicodeInMemCtx: memCtx]; - else - *data = [@"" asUnicodeInMemCtx: memCtx]; - - return rc; -} - -/* FIXME: Should be combined somehow with the code in MAPIStoreAppointmentWrapper.m */ -- (enum mapistore_error) getPidLidPrivate: (void **) data // private (bool), should depend on CLASS and permissions - inMemCtx: (TALLOC_CTX *) memCtx -{ - iCalToDo *task; - - task = [sogoObject component: NO secure: YES]; - - if ([task isPublic]) - return [self getNo: data inMemCtx: memCtx]; - - return [self getYes: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagSensitivity: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - uint32_t v; - - v = (uint32_t) [self sensitivity]; - - *data = MAPILongValue (memCtx, v); - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidTagImportance: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - uint32_t v; - iCalToDo *task; - - task = [sogoObject component: NO secure: YES]; - 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; -} - -//------------------------------------ -// Specific task related properties -//------------------------------------ -- (enum mapistore_error) getPidLidTaskComplete: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - iCalToDo *task; - - task = [sogoObject component: NO secure: YES]; - *data = MAPIBoolValue (memCtx, - [[task status] isEqualToString: @"COMPLETED"]); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidPercentComplete: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - double doubleValue; - iCalToDo *task; - - task = [sogoObject component: NO secure: YES]; - - doubleValue = ((double) [[task percentComplete] intValue] / 100); - *data = MAPIDoubleValue (memCtx, doubleValue); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidTaskDateCompleted: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_SUCCESS; - NSCalendarDate *dateValue; - iCalToDo *task; - - task = [sogoObject component: NO secure: YES]; - - dateValue = [task completed]; - if (dateValue) - *data = [dateValue asFileTimeInMemCtx: memCtx]; - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidLidTaskState: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, 0x1); // not assigned - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidTaskMode: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getLongZero: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidTaskFRecurring: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getNo: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidTaskAccepted: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getNo: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidTaskActualEffort: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getLongZero: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidTaskEstimatedEffort: (void **) data // TODO - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getLongZero: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidTagHasAttachments: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getNo: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidTaskDueDate: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_SUCCESS; - NSCalendarDate *dateValue; - iCalToDo *task; - - task = [sogoObject component: NO secure: YES]; - dateValue = [task due]; - if (dateValue) - *data = [dateValue asFileTimeInMemCtx: memCtx]; - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - -- (enum mapistore_error) getPidLidTaskStartDate: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - enum mapistore_error rc = MAPISTORE_SUCCESS; - NSCalendarDate *dateValue; - iCalToDo *task; - - task = [sogoObject component: NO secure: YES]; - dateValue = [task startDate]; - if (dateValue) - *data = [dateValue asFileTimeInMemCtx: memCtx]; - else - rc = MAPISTORE_ERR_NOT_FOUND; - - return rc; -} - - -- (enum mapistore_error) getPidTagMessageDeliveryTime: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagLastModificationTime: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getClientSubmitTime: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagLastModificationTime: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getLocalCommitTime: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getPidTagLastModificationTime: data inMemCtx: memCtx]; -} - -- (enum mapistore_error) getPidLidTaskStatus: (void **) data // status - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *status; - uint32_t longValue; - iCalToDo *task; - - task = [sogoObject component: NO secure: YES]; - 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; -} - -- (enum mapistore_error) getPidLidTaskOwner: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *owner; - - /* FIXME: This is wrong when setting task's request */ - owner = [sogoObject ownerInContext: nil]; - - *data = [owner asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getPidLidTaskOwnership: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - return [self getLongZero: data inMemCtx: memCtx]; -} - -// ---------------------------------- -// Sharing -// ---------------------------------- -- (NSUInteger) sensitivity -{ - iCalToDo *task; - NSUInteger v; - - task = [sogoObject component: NO secure: YES]; - /* FIXME: Use OpenChange constants names */ - switch ([task symbolicAccessClass]) - { - case iCalAccessPrivate: - v = 0x2; - break; - case iCalAccessConfidential: - v = 0x3; - break; - default: - v = 0x0; - break; - } - return v; -} - -- (NSString *) creator -{ - iCalToDo *task; - - task = [sogoObject component: NO secure: YES]; - return [[task uniqueChildWithTag: @"x-sogo-component-created-by"] - flattenedValuesForKey: @""]; -} - -- (NSString *) owner -{ - /* This is not true but to allow a user edit its own tasks is required. - FIXME: When PidLidTaskOwner getter is properly implemented for Task Requests */ - return [self creator]; -} - -- (void) save:(TALLOC_CTX *) memCtx -{ - iCalCalendar *vCalendar; - iCalToDo *vToDo; - id value; - iCalDateTime *date; - iCalTimeZone *tz; - NSString *status, *priority, *tzName; - NSCalendarDate *now; - NSInteger tzOffset; - NSTimeZone *userTZ; - double doubleValue; - - vToDo = [sogoObject component: YES secure: NO]; - vCalendar = [vToDo parent]; - [vCalendar setProdID: @"-//Inverse inc.//OpenChange+SOGo//EN"]; - - userTZ = [[self userContext] timeZone]; - tzName = [userTZ name]; - tz = [iCalTimeZone timeZoneForName: tzName]; - [vCalendar addTimeZone: tz]; - - // summary - value = [properties - objectForKey: MAPIPropertyKey (PR_NORMALIZED_SUBJECT_UNICODE)]; - if (value) - [vToDo setSummary: value]; - - // comment - value = [properties - objectForKey: MAPIPropertyKey (PR_BODY_UNICODE)]; - if (!value) - { - value = [properties objectForKey: MAPIPropertyKey (PR_HTML)]; - if (value) - { - value = [[NSString alloc] initWithData: value - encoding: NSUTF8StringEncoding]; - [value autorelease]; - value = [value htmlToText]; - } - } - if (value) - { - if ([value length] == 0 || [value isEqualToString: @"\\n"]) - value = nil; - [vToDo setComment: value]; - } - - // location - value = [properties objectForKey: MAPIPropertyKey (PidLidLocation)]; - if (value) - [vToDo setLocation: value]; - - // created - value = [properties objectForKey: MAPIPropertyKey (PR_CREATION_TIME)]; - if (value) - [vToDo setCreated: value]; - - // last-modified + dtstamp - value = [properties objectForKey: MAPIPropertyKey (PR_LAST_MODIFICATION_TIME)]; - if (value) - { - [vToDo setLastModified: value]; - [vToDo setTimeStampAsDate: value]; - } - - // start - value = [properties objectForKey: MAPIPropertyKey (PidLidTaskStartDate)]; - if (value) - { - date = (iCalDateTime *) [vToDo uniqueChildWithTag: @"dtstart"]; - [date setTimeZone: tz]; - /* The property is set to user's local time zone. - See: [MS-OXOTASK] 2.2.2.2.4 - TODO: Ignore when the PT_SYSTIME is 0x5AE980E0*/ - tzOffset = [userTZ secondsFromGMTForDate: value]; - value = [value dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: -tzOffset]; - [date setDateTime: value]; - } - - // due - value = [properties objectForKey: MAPIPropertyKey (PidLidTaskDueDate)]; - if (value) - { - date = (iCalDateTime *) [vToDo uniqueChildWithTag: @"due"]; - [date setTimeZone: tz]; - /* The property is set to user's local time zone. - See: [MS-OXOTASK] 2.2.2.2.5 - TODO: Ignore when the PT_SYSTIME is 0x5AE980E0*/ - tzOffset = [userTZ secondsFromGMTForDate: value]; - value = [value dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: -tzOffset]; - [date setDateTime: value]; - } - - // completed - value = [properties objectForKey: MAPIPropertyKey (PidLidTaskDateCompleted)]; - if (value) - { - date = (iCalDateTime *) [vToDo uniqueChildWithTag: @"completed"]; - /* The property is set to midnight in local time zone converted to UTC: - See: [MS-OXOTASK] 2.2.2.2.9 */ - tzOffset = [userTZ secondsFromGMTForDate: value]; - value = [value dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: -tzOffset]; - [date setDate: value]; - } - - // status - value = [properties objectForKey: MAPIPropertyKey (PidLidTaskStatus)]; - if (value) - { - switch ([value intValue]) - { - case 1: status = @"IN-PROCESS"; break; - case 2: status = @"COMPLETED"; break; - default: status = @"NEEDS-ACTION"; - } - [vToDo setStatus: status]; - } - - // priority - value = [properties objectForKey: MAPIPropertyKey (PR_IMPORTANCE)]; - if (value) - { - switch ([value intValue]) - { - case 0: // IMPORTANCE_LOW - priority = @"9"; - break; - case 2: // IMPORTANCE_HIGH - priority = @"1"; - break; - default: // IMPORTANCE_NORMAL - priority = @"5"; - } - [vToDo setPriority: priority]; - } - - // percent complete - // NOTE: this does not seem to work on Outlook 2003. PidLidPercentComplete's value - // is always set to 0, no matter what value is set in Outlook - value = [properties objectForKey: MAPIPropertyKey (PidLidPercentComplete)]; - if (value) - { - doubleValue = [value doubleValue]; - [vToDo setPercentComplete: - [NSString stringWithFormat: @"%d", (int) (doubleValue * 100)]]; - } - - /* privacy */ - /* FIXME: this should be combined with the code found in iCalEvent+MAPIStore.m */ - value = [properties objectForKey: MAPIPropertyKey(PidLidPrivate)]; - - if (value) - { - if ([value boolValue]) - [vToDo setAccessClass: @"PRIVATE"]; - else - [vToDo setAccessClass: @"PUBLIC"]; - } - - /* Creation */ - now = [NSCalendarDate date]; - if ([sogoObject isNew]) - { - [vToDo setCreated: now]; - /* Creator is used for sharing purposes */ - value = [properties objectForKey: MAPIPropertyKey (PidTagLastModifierName)]; - if (value) - [[vToDo uniqueChildWithTag: @"x-sogo-component-created-by"] setSingleValue: value - forKey: @""]; - } - [vToDo setTimeStampAsDate: now]; - - [sogoObject saveCalendar: vCalendar]; - - [self updateVersions]; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreTasksMessageTable.h b/Attic/OpenChange/MAPIStoreTasksMessageTable.h deleted file mode 100644 index 4be570027..000000000 --- a/Attic/OpenChange/MAPIStoreTasksMessageTable.h +++ /dev/null @@ -1,32 +0,0 @@ -/* MAPIStoreTasksMessageTable.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -#ifndef MAPISTORETASKSMESSAGETABLE_H -#define MAPISTORETASKSMESSAGETABLE_H - -#import "MAPIStoreGCSMessageTable.h" - -@interface MAPIStoreTasksMessageTable : MAPIStoreGCSMessageTable - -@end - -#endif /* MAPISTORETASKSMESSAGETABLE_H */ diff --git a/Attic/OpenChange/MAPIStoreTasksMessageTable.m b/Attic/OpenChange/MAPIStoreTasksMessageTable.m deleted file mode 100644 index b0f39341c..000000000 --- a/Attic/OpenChange/MAPIStoreTasksMessageTable.m +++ /dev/null @@ -1,168 +0,0 @@ -/* MAPIStoreTasksMessageTable.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -#import - -#import - -#import - -#import - -#import "MAPIStoreTasksMessage.h" -#import "MAPIStoreTypes.h" -#import "NSData+MAPIStore.h" -#import "NSDate+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#import "MAPIStoreTasksMessageTable.h" - -#include - -static Class MAPIStoreTasksMessageK = Nil; - -@implementation MAPIStoreTasksMessageTable - -+ (void) initialize -{ - MAPIStoreTasksMessageK = [MAPIStoreTasksMessage class]; -} - -+ (Class) childObjectClass -{ - return MAPIStoreTasksMessageK; -} - -- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property -{ - static NSMutableDictionary *knownProperties = nil; - - if (!knownProperties) - { - knownProperties = [NSMutableDictionary new]; - [knownProperties setObject: @"c_enddate" - forKey: MAPIPropertyKey (PidLidTaskDueDate)]; - } - - return [knownProperties objectForKey: MAPIPropertyKey (property)]; -} - -/* restrictions */ - -- (MAPIRestrictionState) evaluatePropertyRestriction: (struct mapi_SPropertyRestriction *) res - intoQualifier: (EOQualifier **) qualifier -{ - MAPIRestrictionState rc; - id value; - - value = NSObjectFromMAPISPropValue (&res->lpProp); - switch ((uint32_t) res->ulPropTag) - { - case PR_MESSAGE_CLASS_UNICODE: - if ([value isKindOfClass: [NSString class]] - && [value isEqualToString: @"IPM.Task"]) - rc = MAPIRestrictionStateAlwaysTrue; - else - rc = MAPIRestrictionStateAlwaysFalse; - break; - case PR_SENSITIVITY: - rc = MAPIRestrictionStateAlwaysTrue; - break; - case PR_RULE_PROVIDER_UNICODE: // TODO: what's this? - rc = MAPIRestrictionStateAlwaysTrue; - break; - case PidLidTaskOwnership: - rc = MAPIRestrictionStateAlwaysTrue; - break; - case PidLidTaskStatus: - rc = MAPIRestrictionStateAlwaysTrue; - break; - - case PidLidTaskComplete: - *qualifier = [[EOKeyValueQualifier alloc] - initWithKey: @"c_status" - operatorSelector: EOQualifierOperatorEqual - value: [NSNumber numberWithInt: 1]]; - [*qualifier autorelease]; - rc = MAPIRestrictionStateNeedsEval; - break; - - case PidLidTaskDateCompleted: - rc = MAPIRestrictionStateAlwaysTrue; - break; - - default: - rc = [super evaluatePropertyRestriction: res intoQualifier: qualifier]; - } - - return rc; -} - -- (MAPIRestrictionState) evaluateExistRestriction: (struct mapi_SExistRestriction *) res - intoQualifier: (EOQualifier **) qualifier -{ - MAPIRestrictionState rc; - - switch ((uint32_t) res->ulPropTag) - { - case PidLidTaskDateCompleted: - /* since we don't store the completion date in the quick table, we only - checks whether the task has been completed */ - *qualifier = [[EOKeyValueQualifier alloc] - initWithKey: @"c_status" - operatorSelector: EOQualifierOperatorEqual - value: [NSNumber numberWithInt: 1]]; - [*qualifier autorelease]; - rc = MAPIRestrictionStateNeedsEval; - break; - - default: - rc = [super evaluateExistRestriction: res intoQualifier: qualifier]; - } - - return rc; -} - -/* sorting */ - -- (NSString *) sortIdentifierForProperty: (enum MAPITAGS) property -{ - static NSMutableDictionary *knownProperties = nil; - - if (!knownProperties) - { - knownProperties = [NSMutableDictionary new]; - [knownProperties setObject: @"c_title" - forKey: MAPIPropertyKey (PR_NORMALIZED_SUBJECT_UNICODE)]; - [knownProperties setObject: @"c_enddate" - forKey: MAPIPropertyKey (PidLidTaskDueDate)]; - [knownProperties setObject: @"c_creationdate" - forKey: MAPIPropertyKey (PidLidTaskOrdinal)]; - /* Use by oxcfxics to sort the latest first */ - [knownProperties setObject: @"c_lastmodified" - forKey: MAPIPropertyKey (PidTagMessageDeliveryTime)]; - } - - return [knownProperties objectForKey: MAPIPropertyKey (property)]; -} - -@end diff --git a/Attic/OpenChange/MAPIStoreTypes.h b/Attic/OpenChange/MAPIStoreTypes.h deleted file mode 100644 index b12cab6a1..000000000 --- a/Attic/OpenChange/MAPIStoreTypes.h +++ /dev/null @@ -1,65 +0,0 @@ -/* MAPIStoreTypes.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 MAPISTORETYPES_H -#define MAPISTORETYPES_H - -#import - -#include -#include -#include -#include - -@class NSData; -@class NSDictionary; -@class NSTimeZone; - -extern NSTimeZone *utcTZ; - -uint8_t *MAPIBoolValue (void *memCtx, BOOL value); -uint32_t *MAPILongValue (void *memCtx, uint32_t value); -uint64_t *MAPILongLongValue (void *memCtx, uint64_t value); -double *MAPIDoubleValue (void *memCtx, double value); - -id NSObjectFromSPropValue (const struct SPropValue *); -id NSObjectFromMAPISPropValue (const struct mapi_SPropValue *); -id NSObjectFromValuePointer (enum MAPITAGS, const void *); - -NSComparisonResult MAPICNCompare (uint64_t cn1, uint64_t cn2, void *); -NSComparisonResult MAPIChangeKeyGUIDCompare (id ck1, id ck2, void *); - -static inline NSNumber * -MAPIPropertyKey (enum MAPITAGS propTag) -{ -#if (GS_SIZEOF_LONG == 4) - return [NSString stringWithFormat: @"%ul", propTag]; -#elif (GS_SIZEOF_INT == 4) - return [NSString stringWithFormat: @"%u", propTag]; -#else -#error No suitable type for 4 bytes integers -#endif -} - -void MAPIStoreDumpMessageProperties (NSDictionary *properties); - -#endif /* MAPISTORETYPES_H */ diff --git a/Attic/OpenChange/MAPIStoreTypes.m b/Attic/OpenChange/MAPIStoreTypes.m deleted file mode 100644 index eb3b499b3..000000000 --- a/Attic/OpenChange/MAPIStoreTypes.m +++ /dev/null @@ -1,369 +0,0 @@ -/* MAPIStoreTypes.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -#import -#import -#import -#import -#import -#import - -#import "NSArray+MAPIStore.h" -#import "NSData+MAPIStore.h" -#import "NSDate+MAPIStore.h" - -#import "MAPIStoreTypes.h" - -#undef DEBUG -#include -#include - -NSTimeZone *utcTZ; - -uint8_t * -MAPIBoolValue (void *memCtx, BOOL value) -{ - uint8_t *boolValue; - - boolValue = talloc_zero (memCtx, uint8_t); - *boolValue = value; - - return boolValue; -} - -uint32_t * -MAPILongValue (void *memCtx, uint32_t value) -{ - uint32_t *longValue; - - longValue = talloc_zero (memCtx, uint32_t); - *longValue = value; - - return longValue; -} - -uint64_t * -MAPILongLongValue (void *memCtx, uint64_t value) -{ - uint64_t *llongValue; - - llongValue = talloc_zero (memCtx, uint64_t); - *llongValue = value; - - return llongValue; -} - -double * -MAPIDoubleValue (void *memCtx, double value) -{ - double *doubleValue; - - doubleValue = talloc_zero (memCtx, double); - *doubleValue = value; - - return doubleValue; -} - -id -NSObjectFromMAPISPropValue (const struct mapi_SPropValue *value) -{ - short int valueType; - id result; - - valueType = (value->ulPropTag & 0xffff); - switch (valueType) - { - case PT_NULL: - result = [NSNull null]; - break; - case PT_SHORT: - result = [NSNumber numberWithUnsignedShort: value->value.i]; - break; - case PT_LONG: - case PT_ERROR: - result = [NSNumber numberWithUnsignedLong: value->value.l]; - break; - case PT_I8: - result = [NSNumber numberWithUnsignedLongLong: value->value.d]; - break; - case PT_BOOLEAN: - result = [NSNumber numberWithBool: (value->value.b ? YES : NO)]; - break; - case PT_DOUBLE: - result = [NSNumber numberWithDouble: value->value.dbl]; - break; - case PT_UNICODE: - result = [NSString stringWithUTF8String: value->value.lpszW]; - break; - case PT_STRING8: - result = [NSString stringWithUTF8String: value->value.lpszA]; - break; - case PT_SYSTIME: - result = [NSCalendarDate dateFromFileTime: &(value->value.ft)]; - [result setTimeZone: utcTZ]; - break; - case PT_BINARY: - case PT_SVREID: - result = [NSData dataWithShortBinary: &value->value.bin]; - break; - case PT_CLSID: - result = [NSData dataWithGUID: &value->value.lpguid]; - break; - - case PT_MV_LONG: - result = [NSArray arrayFromMAPIMVLong: &value->value.MVl]; - break; - case PT_MV_STRING8: - result = [NSArray arrayFromMAPIMVString: &value->value.MVszA]; - break; - case PT_MV_UNICODE: - result = [NSArray arrayFromMAPIMVUnicode: &value->value.MVszW]; - break; - case PT_MV_CLSID: - result = [NSArray arrayFromMAPIMVGuid: &value->value.MVguid]; - break; - case PT_MV_BINARY: - result = [NSArray arrayFromMAPIMVBinary: &value->value.MVbin]; - break; - - default: -// #define PT_UNSPECIFIED 0x0 -// #define PT_I2 0x2 -// #define PT_CURRENCY 0x6 -// #define PT_APPTIME 0x7 -// #define PT_ERROR 0xa -// #define PT_OBJECT 0xd -// #define PT_I8 0x14 -// #define PT_SRESTRICT 0xFD -// #define PT_ACTIONS 0xFE - result = nil; - NSLog (@"%s: object type not handled: %d (0x%.4x)", - __PRETTY_FUNCTION__, valueType, valueType); - } - - return result; -} - -id -NSObjectFromSPropValue (const struct SPropValue *value) -{ - short int valueType; - id result; - - valueType = (value->ulPropTag & 0xffff); - switch (valueType) - { - case PT_NULL: - result = [NSNull null]; - break; - case PT_SHORT: - result = [NSNumber numberWithShort: value->value.i]; - break; - case PT_LONG: - case PT_ERROR: - result = [NSNumber numberWithLong: value->value.l]; - break; - case PT_I8: - result = [NSNumber numberWithUnsignedLongLong: value->value.d]; - break; - case PT_BOOLEAN: - result = [NSNumber numberWithBool: (value->value.b ? YES : NO)]; - break; - case PT_DOUBLE: - result = [NSNumber numberWithDouble: value->value.dbl]; - break; - case PT_UNICODE: - result = (value->value.lpszW - ? [NSString stringWithUTF8String: value->value.lpszW] - : (id) @""); - break; - case PT_STRING8: - result = (value->value.lpszA - ? [NSString stringWithUTF8String: (const char *) value->value.lpszA] - : (id) @""); - break; - case PT_SYSTIME: - result = [NSCalendarDate dateFromFileTime: &(value->value.ft)]; - break; - case PT_BINARY: - case PT_SVREID: - // lpProps->value.bin = *((const struct Binary_r *)data); - - result - = [NSData dataWithBinary: - (const struct Binary_r *) &(value->value.bin)]; - break; - case PT_CLSID: - result = [NSData dataWithFlatUID: value->value.lpguid]; - break; - case PT_MV_SHORT: - result = [NSArray arrayFromMVShort: &value->value.MVi]; - break; - case PT_MV_LONG: - result = [NSArray arrayFromMVLong: &value->value.MVl]; - break; - case PT_MV_I8: - result = [NSArray arrayFromMVUI8: &value->value.MVui8]; - break; - case PT_MV_STRING8: - result = [NSArray arrayFromMVString: &value->value.MVszA]; - break; - case PT_MV_UNICODE: - result = [NSArray arrayFromMVUnicode: &value->value.MVszW]; - break; - case PT_MV_CLSID: - result = [NSArray arrayFromMVGuid: &value->value.MVguid]; - break; - case PT_MV_BINARY: - result = [NSArray arrayFromMVBinary: &value->value.MVbin]; - break; - case PT_MV_SYSTIME: - result = [NSArray arrayFromMVFileTime: &value->value.MVft]; - break; - - default: -// #define PT_UNSPECIFIED 0x0 -// #define PT_I2 0x2 -// #define PT_CURRENCY 0x6 -// #define PT_APPTIME 0x7 -// #define PT_ERROR 0xa -// #define PT_OBJECT 0xd -// #define PT_I8 0x14 -// #define PT_SRESTRICT 0xFD -// #define PT_ACTIONS 0xFE - result = nil; - NSLog (@"%s: object type not handled: %d (0x%.4x)", - __PRETTY_FUNCTION__, valueType, valueType); - } - - return result; -} - -id -NSObjectFromValuePointer (enum MAPITAGS propTag, const void *data) -{ - struct SPropValue sPropValue; - id result; - - if (set_SPropValue_proptag(&sPropValue, propTag, data)) - result = NSObjectFromSPropValue (&sPropValue); - else - result = nil; - - return result; -} - -static uint64_t -_reverseCN (uint64_t cn) -{ - return ((cn & UINT64_C (0x00000000000000ff)) << 56 - | (cn & UINT64_C (0x000000000000ff00)) << 40 - | (cn & UINT64_C (0x0000000000ff0000)) << 24 - | (cn & UINT64_C (0x00000000ff000000)) << 8 - | (cn & UINT64_C (0x000000ff00000000)) >> 8 - | (cn & UINT64_C (0x0000ff0000000000)) >> 24 - | (cn & UINT64_C (0x00ff000000000000)) >> 40 - | (cn & UINT64_C (0xff00000000000000)) >> 56); -} - -NSComparisonResult -MAPICNCompare (uint64_t cn1, uint64_t cn2, void *unused) -{ - NSComparisonResult result; - - if (cn1 == cn2) - result = NSOrderedSame; - else if (_reverseCN (cn1) < _reverseCN (cn2)) - result = NSOrderedAscending; - else - result = NSOrderedDescending; - - return result; -} - -NSComparisonResult -MAPIChangeKeyGUIDCompare (id ck1, id ck2, void *unused) -{ - NSUInteger count; - const unsigned char *ptr1, *ptr2; - NSComparisonResult result = NSOrderedSame; - - if ([ck1 length] < 16) - { - NSLog (@"ck1 has a length < 16"); - abort (); - } - if ([ck2 length] < 16) - { - NSLog (@"ck2 has a length < 16"); - abort (); - } - - ptr1 = [ck1 bytes]; - ptr2 = [ck2 bytes]; - for (count = 0; result == NSOrderedSame && count < 16; count++) - { - if (*ptr1 < *ptr2) - result = NSOrderedAscending; - else if (*ptr1 > *ptr2) - result = NSOrderedDescending; - else - { - ptr1++; - ptr2++; - } - } - - return result; -} - -void -MAPIStoreDumpMessageProperties (NSDictionary *properties) -{ - NSNumber *key; - NSArray *allKeys; - NSUInteger count, max; - NSUInteger keyAsInt; - id value; - - allKeys = [properties allKeys]; - max = [allKeys count]; - - NSLog (@"message properties (%d):", max); - - value = [properties objectForKey: @"recipients"]; - if (value) - NSLog (@" recipients: %@", value); - - for (count = 0; count < max; count++) - { - key = [allKeys objectAtIndex: count]; - if ([key isKindOfClass: [NSNumber class]]) - { - keyAsInt = [key intValue]; - value = [properties objectForKey: key]; - NSLog (@" 0x%.4x: %@ (%@)", - keyAsInt, value, - NSStringFromClass ([value class])); - } - } -} diff --git a/Attic/OpenChange/MAPIStoreUserContext.h b/Attic/OpenChange/MAPIStoreUserContext.h deleted file mode 100644 index b8defd0cd..000000000 --- a/Attic/OpenChange/MAPIStoreUserContext.h +++ /dev/null @@ -1,96 +0,0 @@ -/* MAPIStoreUserContext.h - this file is part of $PROJECT_NAME_HERE$ - * - * Copyright (C) 2012 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. - */ - -#ifndef MAPISTOREUSERCONTEXT_H -#define MAPISTOREUSERCONTEXT_H - -#import - -@class NSMutableDictionary; -@class NSString; -@class NSTimeZone; -@class NSURL; - -@class WOContext; - -@class SOGoAppointmentFolders; -@class SOGoContactFolders; -@class SOGoMailAccount; -@class SOGoUser; -@class SOGoUserFolder; - -@class MAPIStoreAuthenticator; -@class MAPIStoreMapping; - -@interface MAPIStoreUserContext : NSObject -{ - NSString *username; - SOGoUser *sogoUser; - NSTimeZone *timeZone; - - SOGoUserFolder *userFolder; - NSMutableArray *containersBag; - NSMutableDictionary *rootFolders; - - MAPIStoreMapping *mapping; - - BOOL userDbTableExists; - NSURL *folderTableURL; - - WOContext *woContext; - MAPIStoreAuthenticator *authenticator; - - BOOL inboxHasNoInferiors; -} - -+ (id) userContextWithUsername: (NSString *) username - andTDBIndexing: (struct indexing_context *) indexing; - -- (id) initWithUsername: (NSString *) newUsername - andTDBIndexing: (struct indexing_context *) indexing; - -- (NSString *) username; -- (SOGoUser *) sogoUser; - -- (NSTimeZone *) timeZone; - -- (SOGoUserFolder *) userFolder; - -- (NSDictionary *) rootFolders; - -- (BOOL) inboxHasNoInferiors; - -- (NSURL *) folderTableURL; -- (MAPIStoreMapping *) mapping; - -- (void) ensureFolderTableExists; - -/* SOGo hacky magic */ -- (void) activateWithUser: (SOGoUser *) activeUser; -- (void) activate; -- (void) deactivate; -- (MAPIStoreAuthenticator *) authenticator; -- (WOContext *) woContext; - -@end - -#endif /* MAPISTOREUSERCONTEXT_H */ diff --git a/Attic/OpenChange/MAPIStoreUserContext.m b/Attic/OpenChange/MAPIStoreUserContext.m deleted file mode 100644 index f6d84aa97..000000000 --- a/Attic/OpenChange/MAPIStoreUserContext.m +++ /dev/null @@ -1,414 +0,0 @@ -/* MAPIStoreUserContext.m - this file is part of SOGo - * - * Copyright (C) 2012-2016 Inverse inc - * - * 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. - */ - -#import -#import -#import -#import -#import -#import -#import -#import - -#import -#import - -#import - -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#import -#import "MAPIApplication.h" -#import "MAPIStoreAuthenticator.h" -#import "MAPIStoreMapping.h" - -#import "MAPIStoreUserContext.h" - -static NSMapTable *contextsTable = nil; - -@implementation MAPIStoreUserContext - -+ (void) initialize -{ - contextsTable = [NSMapTable mapTableWithStrongToWeakObjects]; - [contextsTable retain]; -} - -+ (id) userContextWithUsername: (NSString *) username - andTDBIndexing: (struct indexing_context *) indexing; -{ - id userContext; - - userContext = [contextsTable objectForKey: username]; - if (!userContext) - { - userContext = [[self alloc] initWithUsername: username - andTDBIndexing: indexing]; - [userContext autorelease]; - [contextsTable setObject: userContext forKey: username]; - } - else - [userContext activate]; - - return userContext; -} - -- (id) init -{ - if ((self = [super init])) - { - username = nil; - sogoUser = nil; - - userFolder = nil; - containersBag = [NSMutableArray new]; - rootFolders = nil; - - mapping = nil; - - userDbTableExists = NO; - folderTableURL = nil; - - authenticator = nil; - woContext = [WOContext contextWithRequest: nil]; - [woContext retain]; - } - - return self; -} - -- (NSString *) _readPasswordFile: (NSString *) path -{ - NSString *password; - NSData *content; - - password = nil; - content = [NSData dataWithContentsOfFile: path]; - - if (content) - { - password = [[NSString alloc] initWithData: content - encoding: NSUTF8StringEncoding]; - [password autorelease]; - password = [password stringByTrimmingCharactersInSet: - [NSCharacterSet characterSetWithCharactersInString: @"\r\n"]]; - } - - return password; -} - -- (NSString *) _readUserPassword: (NSString *) newUsername -{ - NSString *password, *path; - - path = [NSString stringWithFormat: SAMBA_PRIVATE_DIR - @"/mapistore/%@/password", newUsername]; - - password = [self _readPasswordFile: path]; - if (password == nil) - { - // Try to get master password - path = [NSString stringWithFormat: SAMBA_PRIVATE_DIR @"/mapistore/master.password"]; - password = [self _readPasswordFile: path]; - } - - return password; -} - -- (id) initWithUsername: (NSString *) newUsername - andTDBIndexing: (struct indexing_context *) indexing -{ - NSString *userPassword; - - if ((self = [self init])) - { - /* "username" will be retained by table */ - username = newUsername; - if (indexing) - ASSIGN (mapping, [MAPIStoreMapping mappingForUsername: username - withIndexing: indexing]); - - authenticator = [MAPIStoreAuthenticator new]; - [authenticator setUsername: username]; - /* TODO: very hackish (IMAP access) */ - userPassword = [self _readUserPassword: newUsername]; - if ([userPassword length] == 0) - userPassword = username; - [authenticator setPassword: userPassword]; - // Activate the profile on initialization - [self activate]; - } - - return self; -} - -- (void) dealloc -{ - [userFolder release]; - [containersBag release]; - [rootFolders release]; - - [woContext release]; - [authenticator release]; - [mapping release]; - - [folderTableURL release]; - - [sogoUser release]; - - [contextsTable removeObjectForKey: username]; - - [super dealloc]; -} - -- (NSString *) username -{ - return username; -} - -- (SOGoUser *) sogoUser -{ - if (!sogoUser) - ASSIGN (sogoUser, [SOGoUser userWithLogin: username]); - - return sogoUser; -} - -- (NSTimeZone *) timeZone -{ - if (!timeZone) - { - SOGoUser *user; - - user = [self sogoUser]; - timeZone = [[user userDefaults] timeZone]; - [timeZone retain]; - } - - return timeZone; -} - -- (SOGoUserFolder *) userFolder -{ - if (!userFolder) - { - userFolder = [SOGoUserFolder objectWithName: username - inContainer: nil]; - [userFolder retain]; - } - - return userFolder; -} - -- (NSDictionary *) rootFolders -{ - SOGoMailAccounts *accountsFolder; - id currentFolder; - NGImap4Connection *connection; - NSDictionary *hierarchy; - NSArray *flags; - - if (!rootFolders) - { - rootFolders = [NSMutableDictionary new]; - [self activate]; - [self userFolder]; // force lazy initialization - [woContext setClientObject: userFolder]; - - /* Calendar */ - currentFolder = [userFolder lookupName: @"Calendar" - inContext: woContext - acquire: NO]; - [rootFolders setObject: currentFolder - forKey: @"calendar"]; - [rootFolders setObject: currentFolder - forKey: @"tasks"]; - - /* Contacts */ - currentFolder = [userFolder lookupName: @"Contacts" - inContext: woContext - acquire: NO]; - [rootFolders setObject: currentFolder - forKey: @"contacts"]; - - /* Mail */ - accountsFolder = [userFolder lookupName: @"Mail" - inContext: woContext - acquire: NO]; - [containersBag addObject: accountsFolder]; - [woContext setClientObject: accountsFolder]; - - currentFolder = [accountsFolder lookupName: @"0" - inContext: woContext - acquire: NO]; - [rootFolders setObject: currentFolder - forKey: @"mail"]; - connection = [currentFolder imap4Connection]; - [connection enableExtensions: [NSArray arrayWithObject: @"QRESYNC"]]; - - /* ensure the folder cache is filled */ - [currentFolder toManyRelationshipKeysWithNamespaces: YES]; - hierarchy = [connection cachedHierarchyResultsForURL: [currentFolder imap4URL]]; - flags = [[hierarchy objectForKey: @"list"] objectForKey: @"/INBOX"]; - inboxHasNoInferiors = [flags containsObject: @"noinferiors"]; - } - - return rootFolders; -} - -- (BOOL) inboxHasNoInferiors -{ - [self rootFolders]; - - return inboxHasNoInferiors; -} - -- (MAPIStoreMapping *) mapping -{ - return mapping; -} - - -/* OpenChange db table */ - -- (NSURL *) folderTableURL -{ - NSString *urlString, *ocFSTableName; - NSMutableArray *parts; - SOGoUser *user; - - if (!folderTableURL) - { - user = [self sogoUser]; - urlString = [[user domainDefaults] folderInfoURL]; - parts = [[urlString componentsSeparatedByString: @"/"] - mutableCopy]; - [parts autorelease]; - if ([parts count] == 5) - { - /* If "OCSFolderInfoURL" is properly configured, we must have 5 - parts in this url. We strip the '-' character in case we have - this in the domain part - like foo@bar-zot.com */ - ocFSTableName = [NSString stringWithFormat: @"sogo_cache_folder_%@", - [[[user login] asCSSIdentifier] - stringByReplacingOccurrencesOfString: @"-" - withString: @"_"]]; - [parts replaceObjectAtIndex: 4 withObject: ocFSTableName]; - folderTableURL - = [NSURL URLWithString: [parts componentsJoinedByString: @"/"]]; - [folderTableURL retain]; - } - else - [NSException raise: @"MAPIStoreIOException" - format: @"'OCSFolderInfoURL' is not set"]; - } - - return folderTableURL; -} - -- (void) ensureFolderTableExists -{ - GCSChannelManager *cm; - EOAdaptorChannel *channel; - NSString *tableName, *query; - GCSSpecialQueries *queries; - - if ([GCSFolderManager singleStoreMode]) - return; - - [self folderTableURL]; - - cm = [GCSChannelManager defaultChannelManager]; - channel = [cm acquireOpenChannelForURL: folderTableURL]; - - /* FIXME: make use of [EOChannelAdaptor describeTableNames] instead */ - tableName = [[folderTableURL path] lastPathComponent]; - if ([channel evaluateExpressionX: - [NSString stringWithFormat: @"SELECT count(*) FROM %@", - tableName]]) - { - queries = [channel specialQueries]; - query = [queries createSOGoCacheGCSFolderTableWithName: tableName]; - if ([channel evaluateExpressionX: query]) - [NSException raise: @"MAPIStoreIOException" - format: @"could not create special table '%@'", tableName]; - } - else - [channel cancelFetch]; - - - [cm releaseChannel: channel]; -} - -/* SOGo context objects */ -- (WOContext *) woContext -{ - return woContext; -} - -- (MAPIStoreAuthenticator *) authenticator -{ - return authenticator; -} - -- (void) activate -{ - [self activateWithUser: [self sogoUser]]; -} - -- (void) activateWithUser: (SOGoUser *) activeUser; -{ - NSMutableDictionary *info; - - [MAPIApp setUserContext: self]; - [woContext setActiveUser: activeUser]; - info = [[NSThread currentThread] threadDictionary]; - [info setObject: woContext forKey: @"WOContext"]; -} - -- (void) deactivate -{ - NSMutableDictionary *info; - - if (self == [MAPIApp userContext]) - [MAPIApp setUserContext: nil]; - else - [self errorWithFormat: @"Error: Tried to deactivate an user context " - @"not enabled (%@ vs %@)", - [self username], [[MAPIApp userContext] username]]; - - info = [[NSThread currentThread] threadDictionary]; - if (woContext == [info objectForKey: @"WOContext"]) - [info removeObjectForKey: @"WOContext"]; - else - [self errorWithFormat: @"Error: Tried to deactivate a WOContext " - @"not enabled (%@ vs %@)", - woContext, [info objectForKey: @"WOContext"]]; -} - -@end diff --git a/Attic/OpenChange/NSArray+MAPIStore.h b/Attic/OpenChange/NSArray+MAPIStore.h deleted file mode 100644 index a61bc4bc3..000000000 --- a/Attic/OpenChange/NSArray+MAPIStore.h +++ /dev/null @@ -1,51 +0,0 @@ -/* NSArray+MAPIStore.h - this file is part of SOGo - * - * Copyright (C) 2010 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 NSARRAY_MAPISTORE_H -#define NSARRAY_MAPISTORE_H - -#import - -@interface NSArray (MAPIStoreFolders) - -/* mapi structs */ -+ (id) arrayFromMAPIMVLong: (const struct mapi_MV_LONG_STRUCT *) mvLong; -+ (id) arrayFromMAPIMVUnicode: (const struct mapi_SLPSTRArrayW *) mvUnicode; -+ (id) arrayFromMAPIMVString: (const struct mapi_SLPSTRArray *) mvString; -+ (id) arrayFromMAPIMVBinary: (const struct mapi_SBinaryArray *) mvBinary; -+ (id) arrayFromMAPIMVGuid: (const struct mapi_SGuidArray *) mvGuid; - -+ (id) arrayFromMVShort: (const struct ShortArray_r *) mvShort; -+ (id) arrayFromMVLong: (const struct LongArray_r *) mvLong; -- (struct LongArray_r *) asMVLongInMemCtx: (void *) memCtx; -+ (id) arrayFromMVUI8: (const struct UI8Array_r *) mvI8; -+ (id) arrayFromMVString: (const struct StringArray_r *) mvString; -+ (id) arrayFromMVUnicode: (const struct StringArrayW_r *) mvUnicode; -- (struct StringArrayW_r *) asMVUnicodeInMemCtx: (void *) memCtx; -+ (id) arrayFromMVBinary: (const struct BinaryArray_r *) mvBinary; -- (struct BinaryArray_r *) asMVBinaryInMemCtx: (void *) memCtx; -+ (id) arrayFromMVGuid: (const struct FlatUIDArray_r *) mvGuid; -+ (id) arrayFromMVFileTime: (const struct DateTimeArray_r *) mvGuid; - -@end - -#endif /* NSARRAY+MAPISTORE_H */ diff --git a/Attic/OpenChange/NSArray+MAPIStore.m b/Attic/OpenChange/NSArray+MAPIStore.m deleted file mode 100644 index be54e9259..000000000 --- a/Attic/OpenChange/NSArray+MAPIStore.m +++ /dev/null @@ -1,308 +0,0 @@ -/* NSArray+MAPIStore.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -#import - -#import "NSDate+MAPIStore.h" -#import "NSData+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#import "NSArray+MAPIStore.h" - -#undef DEBUG -#include -#include -#include -#include -#include - -@implementation NSArray (MAPIStoreFolders) - -+ (id) arrayFromMAPIMVLong: (struct mapi_MV_LONG_STRUCT *) mvLong -{ - NSUInteger count; - NSNumber *subObject; - NSMutableArray *mvResult; - - mvResult = [NSMutableArray arrayWithCapacity: mvLong->cValues]; - for (count = 0; count < mvLong->cValues; count++) - { - subObject = [NSNumber numberWithLong: mvLong->lpl[count]]; - [mvResult addObject: subObject]; - } - - return mvResult; -} - -+ (id) arrayFromMAPIMVUnicode: (struct mapi_SLPSTRArrayW *) mvUnicode -{ - NSUInteger count; - NSString *subObject; - NSMutableArray *mvResult; - - mvResult = [NSMutableArray arrayWithCapacity: mvUnicode->cValues]; - for (count = 0; count < mvUnicode->cValues; count++) - { - subObject - = [NSString stringWithUTF8String: mvUnicode->strings[count].lppszW]; - [mvResult addObject: subObject]; - } - - return mvResult; -} - -+ (id) arrayFromMAPIMVString: (struct mapi_SLPSTRArray *) mvString -{ - NSUInteger count; - id subObject; - NSMutableArray *mvResult; - - mvResult = [NSMutableArray arrayWithCapacity: mvString->cValues]; - for (count = 0; count < mvString->cValues; count++) - { - subObject = [NSString stringWithUTF8String: mvString->strings[count].lppszA]; - [mvResult addObject: subObject]; - } - - return mvResult; -} - -+ (id) arrayFromMAPIMVBinary: (struct mapi_SBinaryArray *) mvBinary -{ - NSUInteger count; - id subObject; - NSMutableArray *mvResult; - - mvResult = [NSMutableArray arrayWithCapacity: mvBinary->cValues]; - for (count = 0; count < mvBinary->cValues; count++) - { - subObject = [NSData dataWithShortBinary: mvBinary->bin + count]; - [mvResult addObject: subObject]; - } - - return mvResult; -} - -+ (id) arrayFromMAPIMVGuid: (struct mapi_SGuidArray *) mvGuid -{ - NSUInteger count; - id subObject; - NSMutableArray *mvResult; - - mvResult = [NSMutableArray arrayWithCapacity: mvGuid->cValues]; - for (count = 0; count < mvGuid->cValues; count++) - { - subObject = [NSData dataWithGUID: mvGuid->lpguid + count]; - [mvResult addObject: subObject]; - } - - return mvResult; -} - -+ (id) arrayFromMVShort: (const struct ShortArray_r *) mvShort -{ - NSUInteger count; - NSNumber *subObject; - NSMutableArray *mvResult; - - mvResult = [NSMutableArray arrayWithCapacity: mvShort->cValues]; - for (count = 0; count < mvShort->cValues; count++) - { - subObject = [NSNumber numberWithShort: mvShort->lpi[count]]; - [mvResult addObject: subObject]; - } - - return mvResult; -} - -+ (id) arrayFromMVLong: (const struct LongArray_r *) mvLong -{ - NSUInteger count; - NSNumber *subObject; - NSMutableArray *mvResult; - - mvResult = [NSMutableArray arrayWithCapacity: mvLong->cValues]; - for (count = 0; count < mvLong->cValues; count++) - { - subObject = [NSNumber numberWithLong: mvLong->lpl[count]]; - [mvResult addObject: subObject]; - } - - return mvResult; -} - -- (struct LongArray_r *) asMVLongInMemCtx: (void *) memCtx -{ - struct LongArray_r *list; - NSNumber *number; - NSInteger count, max; - - max = [self count]; - - list = talloc_zero (memCtx, struct LongArray_r); - list->cValues = max; - list->lpl = talloc_array (list, uint32_t, max); - for (count = 0; count < max; count++) - { - number = [self objectAtIndex: count]; - list->lpl[count] = [number longValue]; - } - - return list; -} - -+ (id) arrayFromMVUI8: (const struct UI8Array_r *) mvUI8 -{ - NSUInteger count; - NSNumber *subObject; - NSMutableArray *mvResult; - - mvResult = [NSMutableArray arrayWithCapacity: mvUI8->cValues]; - for (count = 0; count < mvUI8->cValues; count++) - { - subObject = [NSNumber numberWithLongLong: mvUI8->lpui8[count]]; - [mvResult addObject: subObject]; - } - - return mvResult; -} - -+ (id) arrayFromMVUnicode: (const struct StringArrayW_r *) mvUnicode -{ - NSUInteger count; - NSString *subObject; - NSMutableArray *mvResult; - - mvResult = [NSMutableArray arrayWithCapacity: mvUnicode->cValues]; - for (count = 0; count < mvUnicode->cValues; count++) - { - subObject = [NSString stringWithUTF8String: mvUnicode->lppszW[count]]; - [mvResult addObject: subObject]; - } - - return mvResult; -} - -- (struct StringArrayW_r *) asMVUnicodeInMemCtx: (void *) memCtx -{ - struct StringArrayW_r *list; - NSInteger count, max; - - max = [self count]; - - list = talloc_zero (memCtx, struct StringArrayW_r); - list->cValues = max; - list->lppszW = talloc_array (list, const char *, max); - - for (count = 0; count < max; count++) - list->lppszW[count] = [[self objectAtIndex: count] asUnicodeInMemCtx: list->lppszW]; - - return list; -} - -+ (id) arrayFromMVString: (const struct StringArray_r *) mvString -{ - NSUInteger count; - id subObject; - NSMutableArray *mvResult; - - mvResult = [NSMutableArray arrayWithCapacity: mvString->cValues]; - for (count = 0; count < mvString->cValues; count++) - { - subObject = [NSString stringWithUTF8String: (const char *) mvString->lppszA[count]]; - [mvResult addObject: subObject]; - } - - return mvResult; -} - -+ (id) arrayFromMVBinary: (const struct BinaryArray_r *) mvBinary -{ - NSUInteger count; - id subObject; - NSMutableArray *mvResult; - - mvResult = [NSMutableArray arrayWithCapacity: mvBinary->cValues]; - for (count = 0; count < mvBinary->cValues; count++) - { - subObject = [NSData dataWithBinary: mvBinary->lpbin + count]; - [mvResult addObject: subObject]; - } - - return mvResult; -} - -- (struct BinaryArray_r *) asMVBinaryInMemCtx: (void *) memCtx -{ - struct BinaryArray_r *list; - NSData *data; - NSInteger count, max; - - max = [self count]; - - list = talloc_zero (memCtx,struct BinaryArray_r); - list->cValues = max; - list->lpbin = talloc_array (list, struct Binary_r, max); - - for (count = 0; count < max; count++) - { - data = [self objectAtIndex: count]; - list->lpbin[count].cb = [data length]; - list->lpbin[count].lpb = talloc_memdup (list->lpbin, [data bytes], list->lpbin[count].cb); - } - - return list; -} - -+ (id) arrayFromMVGuid: (const struct FlatUIDArray_r *) mvGuid -{ - NSUInteger count; - id subObject; - NSMutableArray *mvResult; - - mvResult = [NSMutableArray arrayWithCapacity: mvGuid->cValues]; - for (count = 0; count < mvGuid->cValues; count++) - { - subObject = [NSData dataWithFlatUID: mvGuid->lpguid[count]]; - [mvResult addObject: subObject]; - } - - return mvResult; -} - -+ (id) arrayFromMVFileTime: (const struct DateTimeArray_r *) mvFileTime -{ - NSUInteger count; - id subObject; - NSMutableArray *mvResult; - - mvResult = [NSMutableArray arrayWithCapacity: mvFileTime->cValues]; - for (count = 0; count < mvFileTime->cValues; count++) - { - subObject = [NSDate dateFromFileTime: mvFileTime->lpft + count]; - [mvResult addObject: subObject]; - } - - return mvResult; -} - -@end diff --git a/Attic/OpenChange/NSData+MAPIStore.h b/Attic/OpenChange/NSData+MAPIStore.h deleted file mode 100644 index 13daa8aef..000000000 --- a/Attic/OpenChange/NSData+MAPIStore.h +++ /dev/null @@ -1,62 +0,0 @@ -/* NSData+MAPIStore.h - this file is part of SOGo - * - * Copyright (C) 2010 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 NSDATA_MAPISTORE_H -#define NSDATA_MAPISTORE_H - -#import - -@interface NSData (MAPIStoreDataTypes) - -+ (id) dataWithBinary: (const struct Binary_r *) binData; -- (struct Binary_r *) asBinaryInMemCtx: (void *) memCtx; - -+ (id) dataWithShortBinary: (const struct SBinary_short *) binData; -- (struct SBinary_short *) asShortBinaryInMemCtx: (void *) memCtx; - -+ (id) dataWithFlatUID: (const struct FlatUID_r *) flatUID; -- (struct FlatUID_r *) asFlatUIDInMemCtx: (void *) memCtx; - -+ (id) dataWithGUID: (const struct GUID *) guid; -- (struct GUID *) asGUIDInMemCtx: (void *) memCtx; - -+ (id) dataWithXID: (const struct XID *) xid; -- (struct XID *) asXIDInMemCtx: (void *) memCtx; -- (struct SizedXid *) asSizedXidArrayInMemCtx: (void *) memCtx - with: (uint32_t *) length; - -+ (id) dataWithChangeKeyGUID: (NSString *) guidString - andCnt: (NSData *) globCnt; - -- (void) hexDumpWithLineSize: (NSUInteger) lineSize; - -@end - -@interface NSMutableData (MAPIStoreDataTypes) - -- (void) appendUInt8: (uint8_t) value; -- (void) appendUInt16: (uint16_t) value; -- (void) appendUInt32: (uint32_t) value; - -@end - -#endif /* NSDATA_MAPISTORE_H */ diff --git a/Attic/OpenChange/NSData+MAPIStore.m b/Attic/OpenChange/NSData+MAPIStore.m deleted file mode 100644 index 5a2afeb1d..000000000 --- a/Attic/OpenChange/NSData+MAPIStore.m +++ /dev/null @@ -1,291 +0,0 @@ -/* NSData+MAPIStore.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -#import - -#import "MAPIStoreTypes.h" -#import "NSObject+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#import "NSData+MAPIStore.h" - -#undef DEBUG -#include -#include -#include -#include -#include - -@implementation NSData (MAPIStoreDataTypes) - -+ (id) dataWithBinary: (const struct Binary_r *) binData -{ - return [NSData dataWithBytes: binData->lpb length: binData->cb]; -} - -- (struct Binary_r *) asBinaryInMemCtx: (void *) memCtx -{ - struct Binary_r *binary; - - binary = talloc_zero (memCtx, struct Binary_r); - binary->cb = [self length]; - binary->lpb = (uint8_t *) [self bytes]; - [self tallocWrapper: binary]; - - return binary; -} - -+ (id) dataWithShortBinary: (const struct SBinary_short *) binData -{ - return [NSData dataWithBytes: binData->lpb length: binData->cb]; -} - -- (struct SBinary_short *) asShortBinaryInMemCtx: (void *) memCtx -{ - struct SBinary_short *binary; - - binary = talloc_zero (memCtx, struct SBinary_short); - binary->cb = [self length]; - binary->lpb = (uint8_t *) [self bytes]; - [self tallocWrapper: binary]; - - return binary; -} - -+ (id) dataWithFlatUID: (const struct FlatUID_r *) flatUID -{ - return [NSData dataWithBytes: flatUID->ab length: 16]; -} - -- (struct FlatUID_r *) asFlatUIDInMemCtx: (void *) memCtx -{ - struct FlatUID_r *flatUID; - - flatUID = talloc_zero (memCtx, struct FlatUID_r); - [self getBytes: flatUID->ab]; - - return flatUID; -} - -static void _fillFlatUIDWithGUID (struct FlatUID_r *flatUID, const struct GUID *guid) -{ - flatUID->ab[0] = (guid->time_low & 0xFF); - flatUID->ab[1] = ((guid->time_low >> 8) & 0xFF); - flatUID->ab[2] = ((guid->time_low >> 16) & 0xFF); - flatUID->ab[3] = ((guid->time_low >> 24) & 0xFF); - flatUID->ab[4] = (guid->time_mid & 0xFF); - flatUID->ab[5] = ((guid->time_mid >> 8) & 0xFF); - flatUID->ab[6] = (guid->time_hi_and_version & 0xFF); - flatUID->ab[7] = ((guid->time_hi_and_version >> 8) & 0xFF); - memcpy (flatUID->ab + 8, guid->clock_seq, sizeof (uint8_t) * 2); - memcpy (flatUID->ab + 10, guid->node, sizeof (uint8_t) * 6); -} - -+ (id) dataWithGUID: (const struct GUID *) guid -{ - struct FlatUID_r flatUID; - - _fillFlatUIDWithGUID (&flatUID, guid); - - return [self dataWithFlatUID: &flatUID]; -} - -- (void) _extractGUID: (struct GUID *) guid -{ - uint8_t *bytes; - - bytes = (uint8_t *) [self bytes]; - - guid->time_low = (bytes[3] << 24 | bytes[2] << 16 - | bytes[1] << 8 | bytes[0]); - guid->time_mid = (bytes[5] << 8 | bytes[4]); - guid->time_hi_and_version = (bytes[7] << 8 | bytes[6]); - memcpy (guid->clock_seq, bytes + 8, sizeof (uint8_t) * 2); - memcpy (guid->node, bytes + 10, sizeof (uint8_t) * 6); -} - -- (struct GUID *) asGUIDInMemCtx: (void *) memCtx -{ - struct GUID *guid; - - guid = talloc_zero (memCtx, struct GUID); - [self _extractGUID: guid]; - - return guid; -} - -+ (id) dataWithXID: (const struct XID *) xid -{ - NSMutableData *xidData; - struct FlatUID_r flatUID; - - _fillFlatUIDWithGUID (&flatUID, &xid->NameSpaceGuid); - - xidData = [NSMutableData dataWithCapacity: 16 + xid->LocalId.length]; - [xidData appendBytes: flatUID.ab length: 16]; - [xidData appendBytes: xid->LocalId.data length: xid->LocalId.length]; - - return xidData; -} - -- (struct XID *) asXIDInMemCtx: (void *) memCtx -{ - struct XID *xid; - uint8_t *bytes; - NSUInteger max; - - max = [self length]; - if (max > 16) - { - xid = talloc_zero (memCtx, struct XID); - - [self _extractGUID: &xid->NameSpaceGuid]; - - xid->LocalId.length = max - 16; - - bytes = (uint8_t *) [self bytes]; - xid->LocalId.data = talloc_memdup (xid, (bytes+16), xid->LocalId.length); - } - else - { - xid = NULL; - abort (); - } - - return xid; -} - -- (struct SizedXid *) asSizedXidArrayInMemCtx: (void *) memCtx - with: (uint32_t *) length -{ - struct Binary_r bin; - struct SizedXid *sizedXIDArray; - - bin.cb = [self length]; - bin.lpb = (uint8_t *)[self bytes]; - - sizedXIDArray = get_SizedXidArray(memCtx, &bin, length); - if (!sizedXIDArray) - { - NSLog (@"Impossible to parse SizedXID array"); - return NULL; - } - - return sizedXIDArray; -} - -- (NSComparisonResult) compare: (NSData *) otherGlobCnt -{ - uint64_t globCnt = 0, oGlobCnt = 0; - - if ([self length] > 0) - globCnt = *(uint64_t *) [self bytes]; - - if ([otherGlobCnt length] > 0) - oGlobCnt = *(uint64_t *) [otherGlobCnt bytes]; - - return MAPICNCompare (globCnt, oGlobCnt, NULL); -} - -+ (id) dataWithChangeKeyGUID: (NSString *) guidString - andCnt: (NSData *) globCnt; -{ - NSMutableData *changeKey; - struct GUID guid; - - changeKey = [NSMutableData dataWithCapacity: 16 + [globCnt length]]; - - [guidString extractGUID: &guid]; - [changeKey appendData: [NSData dataWithGUID: &guid]]; - [changeKey appendData: globCnt]; - - return changeKey; -} - -- (void) hexDumpWithLineSize: (NSUInteger) lineSize -{ - const char *bytes; - NSUInteger lineCount, count, max, charCount, charMax; - NSMutableString *line; - - bytes = [self bytes]; - max = [self length]; - - lineCount = 0; - for (count = 0; count < max; count++) - { - line = [NSMutableString stringWithFormat: @"%d: ", lineCount]; - if (lineSize) - { - if ((max - count) > lineSize) - charMax = lineSize; - else - charMax = max - count; - } - else - charMax = max; - for (charCount = 0; charCount < charMax; charCount++) - [line appendFormat: @" %.2x", *(bytes + count + charCount)]; - [self logWithFormat: @" %@", line]; - count += charMax; - lineCount++; - } -} - -@end - -@implementation NSMutableData (MAPIStoreDataTypes) - -- (void) appendUInt8: (uint8_t) value -{ - [self appendBytes: (char *) &value length: 1]; -} - -- (void) appendUInt16: (uint16_t) value -{ - NSUInteger count; - char bytes[2]; - - for (count = 0; count < 2; count++) - { - bytes[count] = value & 0xff; - value >>= 8; - } - - [self appendBytes: bytes length: 2]; -} - -- (void) appendUInt32: (uint32_t) value -{ - NSUInteger count; - char bytes[4]; - - for (count = 0; count < 4; count++) - { - bytes[count] = value & 0xff; - value >>= 8; - } - - [self appendBytes: bytes length: 4]; -} - -@end diff --git a/Attic/OpenChange/NSDate+MAPIStore.h b/Attic/OpenChange/NSDate+MAPIStore.h deleted file mode 100644 index d61df7b11..000000000 --- a/Attic/OpenChange/NSDate+MAPIStore.h +++ /dev/null @@ -1,46 +0,0 @@ -/* NSDate+MAPIStore.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 NSCALENDARDATE_MAPISTORE_H -#define NSCALENDARDATE_MAPISTORE_H - -#import - -@class NSCalendarDate; - -@interface NSDate (MAPIStoreDataTypes) - -+ (NSCalendarDate *) dateFromMinutesSince1601: (uint32_t) minutes; -- (uint32_t) asMinutesSince1601; - -+ (id) dateFromFileTime: (const struct FILETIME *) timeValue; -- (struct FILETIME *) asFileTimeInMemCtx: (void *) memCtx; - -- (BOOL) isNever; /* occurs on 4500-12-31 */ - -+ (NSCalendarDate *) dateFromSystemTime: (struct SYSTEMTIME) date - andRuleYear: (uint16_t) rYear; -@end - -NSComparisonResult NSDateCompare (id date1, id date2, void *); - -#endif /* NSCALENDARDATE+MAPISTORE_H */ diff --git a/Attic/OpenChange/NSDate+MAPIStore.m b/Attic/OpenChange/NSDate+MAPIStore.m deleted file mode 100644 index b8f09dcc6..000000000 --- a/Attic/OpenChange/NSDate+MAPIStore.m +++ /dev/null @@ -1,209 +0,0 @@ -/* NSDate+MAPIStore.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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. - */ - -#import -#import -#import - -#import "MAPIStoreTypes.h" -#import "NSDate+MAPIStore.h" - -#undef DEBUG -#include -#include -#include -#include - -static NSCalendarDate *refDate = nil; - -@interface NSDate (MAPIStorePossibleMethods) - -- (NSTimeZone *) timeZone; - -@end - -@implementation NSDate (MAPIStoreDataTypes) - -static void -_setupRefDate () -{ - refDate = [[NSCalendarDate alloc] - initWithYear: 1601 month: 1 day: 1 - hour: 0 minute: 0 second: 0 - timeZone: utcTZ]; -} - -+ (NSCalendarDate *) dateFromMinutesSince1601: (uint32_t) minutes -{ - NSCalendarDate *result; - - if (!refDate) - _setupRefDate (); - - result = [refDate dateByAddingYears: 0 months: 0 days: 0 hours: 0 - minutes: minutes seconds: 0]; - - return result; -} - -- (uint32_t) asMinutesSince1601 -{ - uint32_t minutes; - NSInteger offset; - - if (!refDate) - _setupRefDate (); - - if ([self respondsToSelector: @selector (timeZone)]) - offset = [[self timeZone] secondsFromGMT]; - else - offset = 0; - minutes = (uint32_t) (([self timeIntervalSinceDate: refDate] + offset) / 60); - - return minutes; -} - -+ (id) dateFromFileTime: (const struct FILETIME *) timeValue -{ - NSCalendarDate *result; - uint64_t interval; - - if (!refDate) - _setupRefDate (); - - interval = ((uint64_t) timeValue->dwHighDateTime << 32 - | timeValue->dwLowDateTime); - result = [[NSCalendarDate alloc] - initWithTimeInterval: (NSTimeInterval) interval / 10000000 - sinceDate: refDate]; - [result autorelease]; - - return result; -} - -- (struct FILETIME *) asFileTimeInMemCtx: (void *) memCtx -{ - struct FILETIME *timeValue; - uint64_t interval; - - if (!refDate) - _setupRefDate (); - - interval = (((uint64_t) [self timeIntervalSinceDate: refDate]) * 10000000); - timeValue = talloc_zero (memCtx, struct FILETIME); - timeValue->dwLowDateTime = (uint32_t) (interval & 0xffffffff); - timeValue->dwHighDateTime = (uint32_t) ((interval >> 32) & 0xffffffff); - - return timeValue; -} - -- (BOOL) isNever /* occurs on 4500-12-31 */ -{ - NSCalendarDate *calDate; - - if ([self isKindOfClass: [NSCalendarDate class]]) - calDate = (NSCalendarDate *) self; - else - calDate = [NSCalendarDate dateWithTimeIntervalSince1970: - [self timeIntervalSince1970]]; - - return [calDate yearOfCommonEra] == 4500; -} - -+ (NSCalendarDate *) dateFromSystemTime: (struct SYSTEMTIME) date - andRuleYear: (uint16_t) rYear -{ - NSCalendarDate *result; - NSInteger daysToDate; - NSUInteger firstDayOfWeek, year; - - /* ([MS-OXOCAL] 2.2.1.41.1) When we're provided an absolute date (i.e., it - happens once), the SYSTEMTIME structure is enough to fill the date. - When we're parsing a SYSTEMTIME field from a time zone rule, however, a - relative date can be provided for the peroidicity of its periods. In this - scenario, the wYear field is empty and we have to use the wYear field in - the parent rule */ - if (date.wYear != 0) - year = date.wYear; - else - year = rYear; - - /* The wDay field indicates the occurrence of the wDayOfWeek within the month. - The 5th occurrence means the last one, even if it is the 4th. */ - if (date.wDay < 5) - { - result = [[NSCalendarDate alloc] initWithYear: year month: date.wMonth day: 1 - hour: date.wHour minute: date.wMinute second: date.wSecond - timeZone: utcTZ]; - [result autorelease]; - - firstDayOfWeek = [result dayOfWeek]; - - daysToDate = 7 * (date.wDay - 1) + date.wDayOfWeek - firstDayOfWeek; - if (date.wDayOfWeek < firstDayOfWeek) - daysToDate += 7; - - result = [result dateByAddingYears: 0 months: 0 days: daysToDate - hours: 0 minutes: 0 - seconds: 0]; - } - else - { - result = [[NSCalendarDate alloc] initWithYear: year month: date.wMonth + 1 day: 1 - hour: date.wHour minute: date.wMinute second: date.wSecond - timeZone: utcTZ]; - [result autorelease]; - - firstDayOfWeek = [result dayOfWeek]; - - daysToDate = date.wDayOfWeek - firstDayOfWeek; - if (date.wDayOfWeek >= firstDayOfWeek) - daysToDate -= 7; - - result = [result dateByAddingYears: 0 months: 0 days: daysToDate - hours: 0 minutes: 0 - seconds: 0]; - } - - return result; -} - -@end - -NSComparisonResult -NSDateCompare (id date1, id date2, void *ctx) -{ - NSTimeInterval secs1, secs2; - NSComparisonResult result; - - secs1 = [date1 timeIntervalSince1970]; - secs2 = [date2 timeIntervalSince1970]; - if (secs1 == secs2) - result = NSOrderedSame; - else if (secs1 < secs2) - result = NSOrderedAscending; - else - result = NSOrderedDescending; - - return result; -} - diff --git a/Attic/OpenChange/NSObject+MAPIStore.h b/Attic/OpenChange/NSObject+MAPIStore.h deleted file mode 100644 index 52c276c00..000000000 --- a/Attic/OpenChange/NSObject+MAPIStore.h +++ /dev/null @@ -1,76 +0,0 @@ -/* NSObject+MAPIStore.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#ifndef NSOBJECT_MAPISTORE_H -#define NSOBJECT_MAPISTORE_H - -#import - -#include -#include - -struct MAPIStoreTallocWrapper -{ - id instance; -}; - -@interface NSObject (MAPIStoreTallocHelpers) - -- (struct MAPIStoreTallocWrapper *) tallocWrapper: (TALLOC_CTX *) tallocCtx; - -@end - -@interface NSObject (MAPIStoreDataTypes) - -- (enum mapistore_error) getValue: (void **) data - forTag: (enum MAPITAGS) propTag - inMemCtx: (TALLOC_CTX *) memCtx; - -/* getter helpers */ -- (enum mapistore_error) getEmptyString: (void **) data inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getLongZero: (void **) data inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getYes: (void **) data inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getNo: (void **) data inMemCtx: (TALLOC_CTX *) memCtx; -- (enum mapistore_error) getSMTPAddrType: (void **) data inMemCtx: (TALLOC_CTX *) memCtx; - -@end - -@interface NSObject (MAPIStoreExtension) - -- (Class) mapistoreMessageClass; - -@end - -@interface NSObject (MAPIStoreProperties) - -+ (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP - inMemCtx: (TALLOC_CTX *) memCtx; -+ (void) fillAvailableProperties: (struct SPropTagArray *) properties - withExclusions: (BOOL *) exclusions; - -- (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP - inMemCtx: (TALLOC_CTX *) memCtx; -- (BOOL) canGetProperty: (enum MAPITAGS) propTag; - -@end - -#endif /* NSOBJECT_MAPISTORE_H */ diff --git a/Attic/OpenChange/NSObject+MAPIStore.m b/Attic/OpenChange/NSObject+MAPIStore.m deleted file mode 100644 index 9962806c4..000000000 --- a/Attic/OpenChange/NSObject+MAPIStore.m +++ /dev/null @@ -1,270 +0,0 @@ -/* NSObject+MAPIStore.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import -#import -#import -#import - -#import "MAPIStorePropertySelectors.h" -#import "MAPIStoreTypes.h" -#import "NSArray+MAPIStore.h" -#import "NSData+MAPIStore.h" -#import "NSDate+MAPIStore.h" -#import "NSValue+MAPIStore.h" -#import "NSString+MAPIStore.h" - -#import "NSObject+MAPIStore.h" - -#undef DEBUG -#include -#include - -@implementation NSObject (MAPIStoreTallocHelpers) - -static int -MAPIStoreTallocWrapperDestroy (void *data) -{ - struct MAPIStoreTallocWrapper *wrapper; - NSAutoreleasePool *pool; - -// GSRegisterCurrentThread (); - pool = [NSAutoreleasePool new]; - wrapper = data; - //NSLog (@"destroying wrapped object (wrapper: %p; object: %p (%@))...\n", wrapper, wrapper->instance, NSStringFromClass([wrapper->instance class])); - [wrapper->instance release]; - [pool release]; -// GSUnregisterCurrentThread (); - - return 0; -} - -- (struct MAPIStoreTallocWrapper *) tallocWrapper: (TALLOC_CTX *) tallocCtx -{ - struct MAPIStoreTallocWrapper *wrapper; - - wrapper = talloc_zero (tallocCtx, struct MAPIStoreTallocWrapper); - talloc_set_destructor ((void *) wrapper, MAPIStoreTallocWrapperDestroy); - wrapper->instance = self; - [self retain]; - //NSLog (@"returning wrapper: %p; object: %p (%@)", wrapper, self, NSStringFromClass([self class])); - return wrapper; -} - -@end - -@implementation NSObject (MAPIStoreDataTypes) - -- (enum mapistore_error) getValue: (void **) data - forTag: (enum MAPITAGS) propTag - inMemCtx: (TALLOC_CTX *) memCtx -{ - uint16_t valueType; - enum mapistore_error rc = MAPISTORE_SUCCESS; - - // [self logWithFormat: @"property %.8x found", propTag]; - valueType = (propTag & 0xffff); - switch (valueType) - { - case PT_NULL: - *data = NULL; - break; - case PT_SHORT: - *data = [(NSNumber *) self asShortInMemCtx: memCtx]; - break; - case PT_LONG: - *data = [(NSNumber *) self asLongInMemCtx: memCtx]; - break; - case PT_I8: - *data = [(NSNumber *) self asI8InMemCtx: memCtx]; - break; - case PT_BOOLEAN: - *data = [(NSNumber *) self asBooleanInMemCtx: memCtx]; - break; - case PT_DOUBLE: - *data = [(NSNumber *) self asDoubleInMemCtx: memCtx]; - break; - case PT_UNICODE: - case PT_STRING8: - *data = [(NSString *) self asUnicodeInMemCtx: memCtx]; - break; - case PT_SYSTIME: - *data = [(NSCalendarDate * ) self asFileTimeInMemCtx: memCtx]; - break; - case PT_BINARY: - case PT_SVREID: - *data = [(NSData *) self asBinaryInMemCtx: memCtx]; - break; - case PT_CLSID: - *data = [(NSData *) self asGUIDInMemCtx: memCtx]; - break; - case PT_MV_LONG: - *data = [(NSArray *) self asMVLongInMemCtx: memCtx]; - break; - case PT_MV_UNICODE: - *data = [(NSArray *) self asMVUnicodeInMemCtx: memCtx]; - break; - case PT_MV_BINARY: - *data = [(NSArray *) self asMVBinaryInMemCtx: memCtx]; - break; - - default: - [self errorWithFormat: @"object type not handled: %d (0x%.4x)", - valueType, valueType]; - abort(); - *data = NULL; - rc = MAPISTORE_ERR_NOT_FOUND; - } - - return rc; -} - -/* helper getters */ -- (enum mapistore_error) getEmptyString: (void **) data inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [@"" asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getLongZero: (void **) data inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPILongValue (memCtx, 0); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getYes: (void **) data inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPIBoolValue (memCtx, YES); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getNo: (void **) data inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = MAPIBoolValue (memCtx, NO); - - return MAPISTORE_SUCCESS; -} - -- (enum mapistore_error) getSMTPAddrType: (void **) data inMemCtx: (TALLOC_CTX *) memCtx -{ - *data = [@"SMTP" asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - -@end - -@implementation NSObject (MAPIStoreProperties) - -+ (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP - inMemCtx: (TALLOC_CTX *) memCtx -{ - struct SPropTagArray *properties; - const MAPIStorePropertyGetter *classGetters; - NSUInteger count; - enum MAPITAGS propTag; - uint16_t propId; - - properties = talloc_zero (memCtx, struct SPropTagArray); - properties->aulPropTag = talloc_array (properties, enum MAPITAGS, - MAPIStoreSupportedPropertiesCount); - classGetters = MAPIStorePropertyGettersForClass (self); - for (count = 0; count < MAPIStoreSupportedPropertiesCount; count++) - { - propTag = MAPIStoreSupportedProperties[count]; - propId = (propTag >> 16) & 0xffff; - if (classGetters[propId]) - { - properties->aulPropTag[properties->cValues] = propTag; - properties->cValues++; - } - } - - *propertiesP = properties; - - return MAPISTORE_SUCCESS; -} - -+ (void) fillAvailableProperties: (struct SPropTagArray *) properties - withExclusions: (BOOL *) exclusions -{ - TALLOC_CTX *localMemCtx; - struct SPropTagArray *subProperties; - uint16_t propId; - NSUInteger count; - - localMemCtx = talloc_zero (NULL, TALLOC_CTX); - [self getAvailableProperties: &subProperties inMemCtx: localMemCtx]; - for (count = 0; count < subProperties->cValues; count++) - { - propId = (subProperties->aulPropTag[count] >> 16) & 0xffff; - if (!exclusions[propId]) - { - properties->aulPropTag[properties->cValues] - = subProperties->aulPropTag[count]; - properties->cValues++; - exclusions[propId] = YES; - } - } - talloc_free (localMemCtx); -} - -- (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSUInteger count; - struct SPropTagArray *availableProps; - enum MAPITAGS propTag; - - availableProps = talloc_zero (memCtx, struct SPropTagArray); - availableProps->aulPropTag = talloc_array (availableProps, enum MAPITAGS, - MAPIStoreSupportedPropertiesCount); - for (count = 0; count < MAPIStoreSupportedPropertiesCount; count++) - { - propTag = MAPIStoreSupportedProperties[count]; - if ([self canGetProperty: propTag]) - { - availableProps->aulPropTag[availableProps->cValues] = propTag; - availableProps->cValues++; - } - } - - *propertiesP = availableProps; - - return MAPISTORE_SUCCESS; -} - -- (BOOL) canGetProperty: (enum MAPITAGS) propTag -{ - uint16_t propId; - const IMP *classGetters; - - classGetters = (IMP *) MAPIStorePropertyGettersForClass (isa); - propId = (propTag >> 16) & 0xffff; - - return (classGetters[propId] != NULL); -} - -@end diff --git a/Attic/OpenChange/NSObject+PropertyList.h b/Attic/OpenChange/NSObject+PropertyList.h deleted file mode 100644 index 34ea28ea8..000000000 --- a/Attic/OpenChange/NSObject+PropertyList.h +++ /dev/null @@ -1,64 +0,0 @@ -/* dbmsgdump.m - this file is part of SOGo - * - * Copyright (C) 2014 Kamen Mazdrashki - * - * Based on implementation done by 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. - */ - -/* - * A format-agnostic dump extensions for: - * NSArray - * NSObject - * NSDictionary - */ - -#ifndef NSOBJECT_PROPERTYLIST_H -#define NSOBJECT_PROPERTYLIST_H - -#import -#import -#import - - -@interface NSObject (plext) - -- (void) displayWithIndentation: (NSInteger) anInt; - -@end - - -@interface NSDictionary (plext) - -- (void) displayKey: (NSString *) key - withIndentation: (NSInteger) anInt; - -- (void) displayWithIndentation: (NSInteger) anInt; - -@end - - -@interface NSArray (plext) - -- (void) displayCount: (NSUInteger) count - withIndentation: (NSInteger) anInt; - -- (void) displayWithIndentation: (NSInteger) anInt; - -@end - -#endif /* NSOBJECT_PROPERTYLIST_H */ diff --git a/Attic/OpenChange/NSObject+PropertyList.m b/Attic/OpenChange/NSObject+PropertyList.m deleted file mode 100644 index 164ac5054..000000000 --- a/Attic/OpenChange/NSObject+PropertyList.m +++ /dev/null @@ -1,137 +0,0 @@ -/* dbmsgdump.m - this file is part of SOGo - * - * Copyright (C) 2011-2014 Inverse inc - * - * 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. - */ - -/* A format-agnostic property list dumper. - Usage: dbmsgdump [filename] */ - -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#import -#import "NSObject+PropertyList.h" - -const char *indentationStep = " "; - - -@implementation NSObject (plext) - -- (void) _outputIndentation: (NSInteger) anInt -{ - NSInteger i; - - for (i = 0; i < anInt; i++) - printf ("%s", indentationStep); -} - -- (void) displayWithIndentation: (NSInteger) anInt -{ - printf ("(%s) %s", - [NSStringFromClass (isa) UTF8String], - [[self description] UTF8String]); -} - -@end - -@implementation NSDictionary (plext) - -- (void) displayKey: (NSString *) key - withIndentation: (NSInteger) anInt -{ - [self _outputIndentation: anInt]; - - printf ("%s ", [[key description] UTF8String]); - if ([key isKindOfClass: [NSValue class]]) - printf ("(%s: 0x%.8x) ", [(NSValue *) key objCType], [key intValue]); - - printf ("= "); -} - -- (void) displayWithIndentation: (NSInteger) anInt -{ - NSUInteger i, max; - NSArray *keys; - NSInteger subIndent; - NSString *key; - - keys = [self allKeys]; - max = [keys count]; - - printf ("{ (%ld) items\n", (long) max); - - subIndent = anInt + 1; - - for (i = 0; i < max; i++) - { - key = [keys objectAtIndex: i]; - [self displayKey: key withIndentation: subIndent]; - [[self objectForKey: key] displayWithIndentation: subIndent]; - if (i < (max - 1)) - printf (","); - printf ("\n"); - } - - [self _outputIndentation: anInt]; - printf ("}"); -} - -@end - -@implementation NSArray (plext) - -- (void) displayCount: (NSUInteger) count - withIndentation: (NSInteger) anInt -{ - [self _outputIndentation: anInt]; - printf ("%lu = ", (unsigned long) count); -} - -- (void) displayWithIndentation: (NSInteger) anInt -{ - NSUInteger i, max; - NSInteger subIndent; - - max = [self count]; - - printf ("[ (%ld) items\n", (long) max); - - subIndent = anInt + 1; - - for (i = 0; i < max; i++) - { - [self displayCount: i withIndentation: subIndent]; - [[self objectAtIndex: i] displayWithIndentation: subIndent]; - if (i < (max - 1)) - printf (","); - printf ("\n"); - } - - [self _outputIndentation: anInt]; - printf ("]"); -} - -@end - diff --git a/Attic/OpenChange/NSString+MAPIStore.h b/Attic/OpenChange/NSString+MAPIStore.h deleted file mode 100644 index e5006c2ae..000000000 --- a/Attic/OpenChange/NSString+MAPIStore.h +++ /dev/null @@ -1,41 +0,0 @@ -/* NSString+MAPIStore.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 NSSTRING_MAPISTORE_H -#define NSSTRING_MAPISTORE_H - -#import - -@interface NSString (MAPIStoreDataTypes) - -+ (id) stringWithGUID: (const struct GUID *) guid; -- (void) extractGUID: (struct GUID *) guid; - -- (char *) asUnicodeInMemCtx: (void *) memCtx; - -- (NSData *) convertHexStringToBytes; - -- (NSString *) stringByReplacingPercentEscapesUsingEncoding: (NSStringEncoding) encoding; - -@end - -#endif /* NSSTRING+MAPISTORE_H */ diff --git a/Attic/OpenChange/NSString+MAPIStore.m b/Attic/OpenChange/NSString+MAPIStore.m deleted file mode 100644 index 83ca8d6e6..000000000 --- a/Attic/OpenChange/NSString+MAPIStore.m +++ /dev/null @@ -1,201 +0,0 @@ -/* NSString+MAPIStore.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 - -#import "NSString+MAPIStore.h" - -#undef DEBUG -#include -#include -#include - -@implementation NSString (MAPIStoreDataTypes) - -+ (id) stringWithGUID: (const struct GUID *) guid -{ - char *guidString; - NSString *newString; - - guidString = GUID_string (NULL, guid); - newString = [self stringWithUTF8String: guidString]; - talloc_free (guidString); - - return newString; -} - -- (void) extractGUID: (struct GUID *) guid -{ - GUID_from_string ([self UTF8String], guid); -} - -- (char *) asUnicodeInMemCtx: (void *) memCtx -{ - char *unicode; - NSData *encoded; - - if ([self length] > 0) - { - encoded = [self dataUsingEncoding: NSUTF8StringEncoding]; - unicode = talloc_strndup (memCtx, [encoded bytes], [encoded length]); - } - else - unicode = talloc_memdup (memCtx, "", 1); - - return unicode; -} - -- (char) _decodeHexByte: (char) byteChar -{ - char newByte; - - if (byteChar >= 48 && byteChar <= 57) - newByte = (uint8_t) byteChar - 48; - else if (byteChar >= 65 && byteChar <= 70) - newByte = (uint8_t) byteChar - 55; - else if (byteChar >= 97 && byteChar <= 102) - newByte = (uint8_t) byteChar - 87; - else - newByte = -1; - - return newByte; -} - -- (BOOL) _decodeHexByte: (uint8_t *) byte - atPos: (NSUInteger) pos -{ - BOOL error = NO; - char newByte; - unichar byteChar; - - byteChar = [self characterAtIndex: pos]; - if (byteChar < 256) - { - newByte = [self _decodeHexByte: (char) byteChar]; - if (newByte == -1) - error = YES; - else - *byte = newByte; - } - else - error = YES; - - return error; -} - -- (BOOL) _decodeHexPair: (uint8_t *) byte - atPos: (NSUInteger) pos -{ - BOOL error; - uint8_t lowValue, highValue; - - error = [self _decodeHexByte: &highValue atPos: pos]; - if (!error) - { - error = [self _decodeHexByte: &lowValue atPos: pos + 1]; - if (!error) - *byte = highValue << 4 | lowValue; - } - - return error; -} - -- (NSData *) convertHexStringToBytes -{ - NSUInteger count, strLen, bytesLen; - uint8_t *bytes, *currentByte; - NSData *decoded = nil; - BOOL error = NO; - - strLen = [self length]; - if ((strLen % 2) == 0) - { - bytesLen = strLen / 2; - bytes = NSZoneCalloc (NULL, bytesLen, sizeof (uint8_t)); - currentByte = bytes; - for (count = 0; !error && count < strLen; count += 2) - { - error = [self _decodeHexPair: currentByte atPos: count]; - currentByte++; - } - if (error) - NSZoneFree (NULL, bytes); - else - decoded = [NSData dataWithBytesNoCopy: bytes - length: bytesLen - freeWhenDone: YES]; - } - - return decoded; -} - -- (NSString *) stringByReplacingPercentEscapesUsingEncoding: (NSStringEncoding) encoding -{ - NSString *newString; - NSData *data; - NSUInteger count, length, newCount; - const char *bytes; - char *newBytes; - char newByte0, newByte1; - - data = [self dataUsingEncoding: NSASCIIStringEncoding]; - if (data) - { - length = [data length]; - bytes = [data bytes]; - newBytes = NSZoneMalloc (NULL, sizeof (char) * length); - newCount = 0; - for (count = 0; count < length; count++) - { - if (bytes[count] == '%') - { - newByte0 = [self _decodeHexByte: bytes[count+1]]; - newByte1 = [self _decodeHexByte: bytes[count+2]]; - if ((newByte0 != -1) && (newByte1 != -1)) - { - newBytes[newCount] = (((newByte0 << 4) & 0xf0) - | (newByte1 & 0x0f)); - count += 2; - } - else - newBytes[newCount] = bytes[count]; - } - else - newBytes[newCount] = bytes[count]; - newCount++; - } - - data = [NSData dataWithBytesNoCopy: newBytes length: newCount freeWhenDone: YES]; - newString = [[NSString alloc] - initWithData: data encoding: encoding]; - [newString autorelease]; - } - else - newString = nil; - - return newString; -} - -@end diff --git a/Attic/OpenChange/NSValue+MAPIStore.h b/Attic/OpenChange/NSValue+MAPIStore.h deleted file mode 100644 index da0b2aa41..000000000 --- a/Attic/OpenChange/NSValue+MAPIStore.h +++ /dev/null @@ -1,38 +0,0 @@ -/* NSValue+MAPIStore.h - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 NSVALUE_MAPISTORE_H -#define NSVALUE_MAPISTORE_H - -#import - -@interface NSNumber (MAPIStoreDataTypes) - -- (uint8_t *) asBooleanInMemCtx: (void *) memCtx; -- (uint16_t *) asShortInMemCtx: (void *) memCtx; -- (uint32_t *) asLongInMemCtx: (void *) memCtx; -- (uint64_t *) asI8InMemCtx: (void *) memCtx; -- (double *) asDoubleInMemCtx: (void *) memCtx; - -@end - -#endif /* NSVALUE_MAPISTORE_H */ diff --git a/Attic/OpenChange/NSValue+MAPIStore.m b/Attic/OpenChange/NSValue+MAPIStore.m deleted file mode 100644 index a3301ce00..000000000 --- a/Attic/OpenChange/NSValue+MAPIStore.m +++ /dev/null @@ -1,79 +0,0 @@ -/* NSValue+MAPIStore.m - this file is part of SOGo - * - * Copyright (C) 2010-2012 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 - -#import "NSValue+MAPIStore.h" - -@implementation NSNumber (MAPIStoreDataTypes) - -- (uint8_t *) asBooleanInMemCtx: (void *) memCtx -{ - uint8_t *value; - - value = talloc (memCtx, uint8_t); - *value = ([self boolValue] ? 1 : 0); - - return value; -} - -- (uint16_t *) asShortInMemCtx: (void *) memCtx -{ - uint16_t *value; - - value = talloc (memCtx, uint16_t); - *value = [self shortValue]; - - return value; -} - -- (uint32_t *) asLongInMemCtx: (void *) memCtx -{ - uint32_t *value; - - value = talloc (memCtx, uint32_t); - *value = [self longValue]; - - return value; -} - -- (uint64_t *) asI8InMemCtx: (void *) memCtx -{ - uint64_t *value; - - value = talloc (memCtx, uint64_t); - *value = [self unsignedLongLongValue]; - - return value; -} - -- (double *) asDoubleInMemCtx: (void *) memCtx -{ - double *value; - - value = talloc (memCtx, double); - *value = [self doubleValue]; - - return value; -} - -@end diff --git a/Attic/OpenChange/RTFHandler.h b/Attic/OpenChange/RTFHandler.h deleted file mode 100644 index ec776a8d3..000000000 --- a/Attic/OpenChange/RTFHandler.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - Copyright (C) 2005-2012 Inverse inc. - - 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 - Free Software Foundation; either version 2, or (at your option) any - later version. - - 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. - - You should have received a copy of the GNU Lesser General Public - License along with OGo; see the file COPYING. If not, write to the - Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. -*/ - -#include -#include -#include -#include -#include - -// -// -// -@class RTFFontTable; - -@interface RTFHandler : NSObject -{ - NSMapTable *_charsets; - NSMutableData *_html; - NSData *_data; - - const char *_bytes; - int _current_pos; - int _len; -} - -- (id) initWithData: (NSData *) theData; -- (NSMutableData *) parse; - -- (RTFFontTable *) parseFontTable; -- (void) mangleInternalStateWithBytesPtr: (const char*) newBytes - andCurrentPos: (int) newCurrentPos; - -@end - -// -// -// -@interface RTFStack: NSObject -{ - NSMutableArray *a; -} -- (void) push: (id) theObject; -- (id) pop; -@end - -// -// -// -@interface RTFFormattingOptions : NSObject -{ -@public - BOOL bold; - BOOL italic; - BOOL underline; - BOOL strikethrough; - int font_index; - int color_index; - int start_pos; - const unsigned short *charset; -} -@end - -// -// -// -@interface RTFFontInfo : NSObject -{ -@public - NSString *family; - unsigned char charset; - NSString *name; - unsigned int pitch; - unsigned int index; -} - -- (NSString *) description; -@end - -// -// \fX - font, index in font table -// -@interface RTFFontTable : NSObject -{ - @public - NSMapTable *fontInfos; -} - -- (void) addFontInfo: (RTFFontInfo *) theFontInfo - atIndex: (unsigned int ) theIndex; -- (RTFFontInfo *) fontInfoAtIndex: (unsigned int ) theIndex; -- (NSString *) description; - -@end - -// -// -// -@interface RTFColorDef : NSObject -{ -@public - unsigned char red; - unsigned char green; - unsigned char blue; -} - -@end - -// -// {\colortbl\red0\green0\blue0;\red128\green0\blue0;\red255\green0\blue0;} -// -// \cfX - color/foreground - index -// \cbX - color/background - index -// -// -@interface RTFColorTable : NSObject -{ - @public - NSMutableArray *colorDefs; -} - -- (void) addColorDef: (RTFColorDef *) theColorDef; - -@end diff --git a/Attic/OpenChange/RTFHandler.m b/Attic/OpenChange/RTFHandler.m deleted file mode 100644 index c89f4c677..000000000 --- a/Attic/OpenChange/RTFHandler.m +++ /dev/null @@ -1,1481 +0,0 @@ -/* - Copyright (C) 2005-2013 Inverse inc. - - 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 - Free Software Foundation; either version 2, or (at your option) any - later version. - - 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. - - You should have received a copy of the GNU Lesser General Public - License along with OGo; see the file COPYING. If not, write to the - Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. -*/ - -#include "RTFHandler.h" -#include -#include - -// -// Useful macros -// -#define ADVANCE self->_bytes++; self->_current_pos++; -#define ADVANCE_N(N) self->_bytes += (N); self->_current_pos += (N); -#define REWIND self->_bytes--; self->_current_pos--; - -#define DEFAULT_CHARSET 1 -#define FONTNAME_LEN_MAX 100 - -// -// Charset definitions. See http://msdn.microsoft.com/en-us/goglobal/bb964654 for all details. -// -const unsigned short ansicpg1250[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, - 0x20ac, 0x0000, 0x201a, 0x0000, 0x201e, 0x2026, 0x2020, 0x2021, 0x0000, 0x2030, 0x0160, 0x2039, 0x015a, 0x0164, 0x017d, 0x0179, - 0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0161, 0x203a, 0x015b, 0x0165, 0x017e, 0x017a, - 0x00a0, 0x02c7, 0x02d8, 0x0141, 0x00a4, 0x0104, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x015e, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x017b, - 0x00b0, 0x00b1, 0x02db, 0x0142, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x0105, 0x015f, 0x00bb, 0x013d, 0x02dd, 0x013e, 0x017c, - 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e, - 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df, - 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f, - 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9 }; - -const unsigned short ansicpg1251[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, - 0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021, 0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f, - 0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f, - 0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7, 0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407, - 0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7, 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457, - 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, - 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, - 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, - 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f }; - -const unsigned short ansicpg1252[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, - 0x20ac, 0x0000, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017d, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x0000, 0x017e, 0x0178, - 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, - 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, - 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, - 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, - 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, - 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff }; - -const unsigned short ansicpg1253[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, - 0x20ac, 0x0000, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0000, 0x203a, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00a0, 0x0385, 0x0386, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x0000, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x2015, - 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x0384, 0x00b5, 0x00b6, 0x00b7, 0x0388, 0x0389, 0x038a, 0x00bb, 0x038c, 0x00bd, 0x038e, 0x038f, - 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, - 0x03a0, 0x03a1, 0x0000, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af, - 0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, - 0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0x0000 }; - -const unsigned short ansicpg1254[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, - 0x20ac, 0x0000, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x0000, 0x0000, 0x0178, - 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, - 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, - 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, - 0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df, - 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, - 0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff }; - -const unsigned short ansicpg1255[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, - 0x20ac, 0x0000, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0x0000, 0x203a, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20aa, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00d7, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, - 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00f7, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, - 0x05b0, 0x05b1, 0x05b2, 0x05b3, 0x05b4, 0x05b5, 0x05b6, 0x05b7, 0x05b8, 0x05b9, 0x0000, 0x05bb, 0x05bc, 0x05bd, 0x05be, 0x05bf, - 0x05c0, 0x05c1, 0x05c2, 0x05c3, 0x05f0, 0x05f1, 0x05f2, 0x05f3, 0x05f4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df, - 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0x0000, 0x0000, 0x200e, 0x200f, 0x0000 }; - -const unsigned short ansicpg1256[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, - 0x20ac, 0x067e, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, - 0x06af, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x06a9, 0x2122, 0x0691, 0x203a, 0x0153, 0x200c, 0x200d, 0x06ba, - 0x00a0, 0x060c, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x06be, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, - 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x061b, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x061f, - 0x06c1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, - 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00d7, 0x0637, 0x0638, 0x0639, 0x063a, 0x0640, 0x0641, 0x0642, 0x0643, - 0x00e0, 0x0644, 0x00e2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x0649, 0x064a, 0x00ee, 0x00ef, - 0x064b, 0x064c, 0x064d, 0x064e, 0x00f4, 0x064f, 0x0650, 0x00f7, 0x0651, 0x00f9, 0x0652, 0x00fb, 0x00fc, 0x200e, 0x200f, 0x06d2 }; - -const unsigned short ansicpg1257[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, - 0x20ac, 0x0000, 0x201a, 0x0000, 0x201e, 0x2026, 0x2020, 0x2021, 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00a8, 0x02c7, 0x00b8, - 0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0000, 0x203a, 0x0000, 0x00af, 0x02db, 0x0000, - 0x00a0, 0x0000, 0x00a2, 0x00a3, 0x00a4, 0x0000, 0x00a6, 0x00a7, 0x00d8, 0x00a9, 0x0156, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00c6, - 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00f8, 0x00b9, 0x0157, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00e6, - 0x0104, 0x012e, 0x0100, 0x0106, 0x00c4, 0x00c5, 0x0118, 0x0112, 0x010c, 0x00c9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012a, 0x013b, - 0x0160, 0x0143, 0x0145, 0x00d3, 0x014c, 0x00d5, 0x00d6, 0x00d7, 0x0172, 0x0141, 0x015a, 0x016a, 0x00dc, 0x017b, 0x017d, 0x00df, - 0x0105, 0x012f, 0x0101, 0x0107, 0x00e4, 0x00e5, 0x0119, 0x0113, 0x010d, 0x00e9, 0x017a, 0x0117, 0x0123, 0x0137, 0x012b, 0x013c, - 0x0161, 0x0144, 0x0146, 0x00f3, 0x014d, 0x00f5, 0x00f6, 0x00f7, 0x0173, 0x0142, 0x015b, 0x016b, 0x00fc, 0x017c, 0x017e, 0x02d9 }; - -const unsigned short ansicpg1258[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, - 0x20ac, 0x0000, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0x0000, 0x203a, 0x0153, 0x0000, 0x0000, 0x0178, - 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, - 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, - 0x00c0, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x0300, 0x00cd, 0x00ce, 0x00cf, - 0x0110, 0x00d1, 0x0309, 0x00d3, 0x00d4, 0x01a0, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x01af, 0x0303, 0x00df, - 0x00e0, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x0301, 0x00ed, 0x00ee, 0x00ef, - 0x0111, 0x00f1, 0x0323, 0x00f3, 0x00f4, 0x01a1, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x01b0, 0x20ab, 0x00ff }; - -const unsigned short ansicpg874[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, - 0x20ac, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, - 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, - 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, - 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37, 0x0e38, 0x0e39, 0x0e3a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0e3f, - 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f, - 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0x0000, 0x0000, 0x0000, 0x0000 }; - -// -// -// -@implementation RTFStack - -- (id) init -{ - if ((self = [super init])) - { - a = [[NSMutableArray alloc] init]; - } - return self; -} - -- (void) dealloc -{ - [a release]; - [super dealloc]; -} - -- (void) push: (id) theObject -{ - [a addObject: theObject]; -} - -- (id) pop -{ - id o = nil; - - if ([a count]) - { - o = [[[a lastObject] retain] autorelease]; - [a removeLastObject]; - } - - return o; -} - -- (id) top -{ - id o = nil; - - if ([a count]) - { - o = [[[a lastObject] retain] autorelease]; - } - - return o; -} - -@end - -// -// -// -@implementation RTFFormattingOptions -@end - -// -// -// -@implementation RTFFontInfo - -- (id) init -{ - if ((self = [super init])) - { - - } - - charset = DEFAULT_CHARSET; - return self; -} - -- (void) dealloc -{ - [family release]; - [name release]; - [super dealloc]; -} - -- (NSString *) description -{ - NSString *description; - description = [NSString stringWithFormat: - @"%u name=%@ family=%@ charset=%u pitch=%u", - index, name, family, charset, pitch - ]; - return description; -} - -@end - -// -// -// -@implementation RTFFontTable - -- (id) init -{ - if ((self = [super init])) - { - fontInfos = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 128); - } - return self; -} - -- (void) dealloc -{ - NSFreeMapTable(fontInfos); - [super dealloc]; -} - -- (void) addFontInfo: (RTFFontInfo *) theFontInfo - atIndex: (unsigned int) theIndex -{ - NSNumber *key; - - key = [NSNumber numberWithInt: theIndex]; - NSMapInsert(fontInfos, key, (void*) theFontInfo); -} - -- (RTFFontInfo *) fontInfoAtIndex: (unsigned int) theIndex -{ - NSNumber *key; - - key = [NSNumber numberWithInt: theIndex]; - return NSMapGet(fontInfos, key); -} - -- (NSString *) description -{ - NSMutableString *description; - NSEnumerator *enumerator; - RTFFontInfo *fontInfo; - - description = [NSMutableString stringWithFormat: @"Number of fonts: %u\n", [fontInfos count]]; - - enumerator = [fontInfos objectEnumerator]; - while ((fontInfo = [enumerator nextObject])) - { - [description appendString: [fontInfo description]]; - [description appendString: @"\n"]; - } - - return description; -} - -@end - -// -// -// -@implementation RTFColorDef - -@end - -// -// -// -@implementation RTFColorTable - -- (id) init -{ - if ((self = [super init])) - { - colorDefs = [[NSMutableArray alloc] init]; - } - return self; -} - -- (void) dealloc -{ - [colorDefs release]; - [super dealloc]; -} - -- (void) addColorDef: (RTFColorDef *) theColorDef -{ - [colorDefs addObject: theColorDef]; -} - -- (RTFColorDef *) colorDefAtIndex: (unsigned int) theIndex -{ - return [colorDefs objectAtIndex: theIndex]; -} - -@end - -// -// -// -@implementation RTFHandler - -static NSMapTable *_charsets = nil; -static NSMapTable *_cws = nil; -typedef enum { - CW_UNKNOWN = 0, - CW_ANSICPG, - CW_B, - CW_CF, - CW_COLORTBL, - CW_F, - CW_FONTTBL, - CW_I, - CW_PAR, - CW_PICT, - CW_SOFTLINE, - CW_STRIKE, - CW_STYLESHEET, - CW_TAB, - CW_U, - CW_UL, - CW_ULNONE -} commandWordId; - -static NSMapTable *_fontCws = nil; -typedef enum { - FONTCW_UNKNOWN = 0, - FONTCW_F, - FONTCW_FBIDI, - FONTCW_FCHARSET, - FONTCW_FDECOR, - FONTCW_FMODERN, - FONTCW_FNIL, - FONTCW_FPRQ, - FONTCW_FROMAN, - FONTCW_FSCRIPT, - FONTCW_FSWISS, - FONTCW_FTECH -} fontCommandWordId; - -static void _init_charsets_table() -{ - _charsets = NSCreateMapTable(NSObjectMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, 23); - // 238 — Eastern European - cpg1250 - NSMapInsert(_charsets, @"ansicpg1250", ansicpg1250); - NSMapInsert(_charsets, [NSNumber numberWithUnsignedChar: 238], ansicpg1250); - // 204 — Russian - cpg1251 - NSMapInsert(_charsets, @"ansicpg1251", ansicpg1251); - NSMapInsert(_charsets, [NSNumber numberWithUnsignedChar: 204], ansicpg1251); - // 0 - Latin 1 - cpg1252 - also know as ANSI - NSMapInsert(_charsets, [NSNumber numberWithUnsignedChar: 0], ansicpg1252); - NSMapInsert(_charsets, @"ansicpg1252", ansicpg1252); - // 161 - Greek cpg1253 - NSMapInsert(_charsets, @"ansicpg1253", ansicpg1253); - NSMapInsert(_charsets, [NSNumber numberWithUnsignedChar: 161], ansicpg1253); - // 162 — Turkish - cpg1254 - NSMapInsert(_charsets, @"ansicpg1254", ansicpg1254); - NSMapInsert(_charsets, [NSNumber numberWithUnsignedChar: 162], ansicpg1254); - // 177 — Hebrew Traditional - cpg1255 - // also 181 - Hebrew user - NSMapInsert(_charsets, @"ansicpg1255", ansicpg1255); - NSMapInsert(_charsets, [NSNumber numberWithUnsignedChar: 177], ansicpg1255); - NSMapInsert(_charsets, [NSNumber numberWithUnsignedChar: 181], ansicpg1255); - // 178 — Arabic - cpg1256 - // also 179 - Arabic traditional - // also 180 - Arabic User - NSMapInsert(_charsets, @"ansicpg1256", ansicpg1256); - NSMapInsert(_charsets, [NSNumber numberWithUnsignedChar: 178], ansicpg1256); - NSMapInsert(_charsets, [NSNumber numberWithUnsignedChar: 179], ansicpg1256); - NSMapInsert(_charsets, [NSNumber numberWithUnsignedChar: 180], ansicpg1256); - // 186 — Baltic - pg 1257 - NSMapInsert(_charsets, @"ansicpg1257", ansicpg1257); - NSMapInsert(_charsets, [NSNumber numberWithUnsignedChar: 186], ansicpg1257); - // 163 — Vietnamese - pg1259 - NSMapInsert(_charsets, @"ansicpg1258", ansicpg1258); - NSMapInsert(_charsets, [NSNumber numberWithUnsignedChar: 163], ansicpg1258); - // 222 — Thai - cpg874 - NSMapInsert(_charsets, @"ansicpg874", ansicpg874); - NSMapInsert(_charsets, [NSNumber numberWithUnsignedChar: 222], ansicpg874); - - // TODO: check differences between traditional/user/no-qualified for Arabic and Hebrew - // TODO: missing codepage for the following codes: - // 2 — Symbol - // 3 — Invalid - // 77 — Mac - // 128 — Shift Jis - // 129 — Hangul - // 130 — Johab - // 134 — GB2312 - // 136 — Big5 - // 254 — PC 437 - // 255 — OEM -} - -static void _init_cws_table() -{ - _cws = NSCreateMapTable(NSObjectMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, 16); - NSMapInsert(_cws, @"ansicpg", (void *) CW_ANSICPG); - NSMapInsert(_cws, @"b", (void *) CW_B); - NSMapInsert(_cws, @"cf", (void *) CW_CF); - NSMapInsert(_cws, @"colortbl", (void *) CW_COLORTBL); - NSMapInsert(_cws, @"f", (void *) CW_F); - NSMapInsert(_cws, @"fonttbl", (void *) CW_FONTTBL); - NSMapInsert(_cws, @"i", (void *) CW_I); - NSMapInsert(_cws, @"par", (void *) CW_PAR); - NSMapInsert(_cws, @"pict", (void *) CW_PICT); - NSMapInsert(_cws, @"softline", (void *) CW_SOFTLINE); - NSMapInsert(_cws, @"strike", (void *) CW_STRIKE); - NSMapInsert(_cws, @"stylesheet", (void *) CW_STYLESHEET); - NSMapInsert(_cws, @"tab", (void *) CW_TAB); - NSMapInsert(_cws, @"u", (void *) CW_U); - NSMapInsert(_cws, @"ul", (void *) CW_UL); - NSMapInsert(_cws, @"ulnone", (void *) CW_ULNONE); -} - -static void _init_fontCws_table() -{ - _fontCws = NSCreateMapTable(NSObjectMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, 23); - NSMapInsert(_fontCws, @"f", (void *) FONTCW_F); - NSMapInsert(_fontCws, @"fbidi", (void *) FONTCW_FBIDI); - NSMapInsert(_fontCws, @"fcharset", (void *) FONTCW_FCHARSET); - NSMapInsert(_fontCws, @"fdecor", (void *) FONTCW_FDECOR); - NSMapInsert(_fontCws, @"fmodern", (void *) FONTCW_FMODERN); - NSMapInsert(_fontCws, @"fnil", (void *) FONTCW_FNIL); - NSMapInsert(_fontCws, @"fprq", (void *) FONTCW_FPRQ); - NSMapInsert(_fontCws, @"froman", (void *) FONTCW_FROMAN); - NSMapInsert(_fontCws, @"fscript", (void *) FONTCW_FSCRIPT); - NSMapInsert(_fontCws, @"fswiss", (void *) FONTCW_FSWISS); - NSMapInsert(_fontCws, @"ftech", (void *) FONTCW_FTECH); -} - -- (id) initWithData: (NSData *) theData -{ - if ((self = [super init])) - { - ASSIGN(_data, theData); - _bytes = (char *)[_data bytes]; - _len = [_data length]; - _current_pos = 0; - if (_charsets == nil) - _init_charsets_table(); - if (_cws == nil) - _init_cws_table(); - if (_fontCws == nil) - _init_fontCws_table(); - } - - return self; -} - -- (void) dealloc -{ - NSFreeMapTable(_charsets); - [_data release]; - [super dealloc]; -} - -/* - Returns pointer to the control word and in len pointer its length including numeric argument -*/ -- (const char *) parseControlWord: (unsigned int *) len -{ - const char *start, *end; - - start = ADVANCE; - - /* - A control word is defined by: - - \ - */ - while (isalpha(*_bytes)) - { - ADVANCE; - } - - /* - The can be one of the following: - - - A space. This serves only to delimit a control word and is - ignored in subsequent processing. - - - A numeric digit or an ASCII minus sign (-), which indicates - that a numeric parameter is associated with the control word. - Only this case requires to include it in the control word. - - - Any character other than a letter or a digit - */ - if (*_bytes == '-' || isdigit(*_bytes)) - { - ADVANCE; - while (isdigit(*_bytes)) // TODO: Allow up to 10 digits - { - ADVANCE; - } - } - /* In this case, the delimiting character terminates the control - word and is not part of the control word. */ - - end = _bytes; - *len = end-start-1; - - return start+1; -} - -- (const char *) parseControlWordAndSetLenIn: (unsigned int *) len - setHasIntArgumentIn: (BOOL *) hasArg - setIntArgumentIn: (int *) arg -{ - const char *start; - const char *end = NULL; - const char *startArg = NULL; - const char *endArg = NULL; - - ADVANCE; - start = _bytes; - - /* - A control word is defined by: - - \ - */ - while (isalpha(*_bytes)) - { - end = _bytes; - ADVANCE; - } - - if (end == NULL) - { - return NULL; - } - - /* - The can be one of the following: - - - A space. This serves only to delimit a control word and is - ignored in subsequent processing. - - - A numeric digit or an ASCII minus sign (-), which indicates - that a numeric parameter is associated with the control word. - Only this case requires to include it in the control word. - - - Any character other than a letter or a digit - */ - - if (*_bytes == '-' || isdigit(*_bytes)) - { - startArg = _bytes; - endArg = _bytes; - ADVANCE; - while (isdigit(*_bytes)) - { - endArg = _bytes; - ADVANCE; - } - } - - *hasArg = NO; - *arg = 0; - if (startArg) - { - NSString *s; - unsigned int argLength = endArg - startArg + 1; - // the next guard is to protect against a single '-' - if (argLength > 1 || (*startArg != '-')) - { - s = [[NSString alloc] initWithBytesNoCopy: (void *) startArg - length: argLength - encoding: NSASCIIStringEncoding - freeWhenDone: NO]; - [s autorelease]; - *hasArg = YES; - *arg = [s intValue]; // Warning: it does not detect conversion errors - } - } - - - /* In other cases, the delimiting character terminates the control - word and is not part of the control word. */ - *len = end - start + 1; - return start; -} - -// -// {\colortbl\red0\green0\blue0;\red128\green0\blue0;\red255\green0\blue0;} -// -- (RTFColorTable *) parseColorTable -{ - RTFColorTable *colorTable; - RTFColorDef *colorDef; - - colorTable = [[[RTFColorTable alloc] init] autorelease]; - colorDef = [[[RTFColorDef alloc] init] autorelease]; - - while (*_bytes != '}') - { - if (*_bytes == ';') - { - [colorTable addColorDef: colorDef]; - colorDef = [[[RTFColorDef alloc] init] autorelease]; - ADVANCE; - } - else if (*_bytes == '\\') - { - const char *cw; - unsigned int len; - NSString *s; - - cw = [self parseControlWord: &len]; - - // Skip our control word - //if (strncmp(start+1, "colortbl", len) == 0) - // continue; - - s = [[NSString alloc] initWithBytesNoCopy: (void *)cw - length: len - encoding: NSASCIIStringEncoding - freeWhenDone: NO]; - [s autorelease]; - - if ([s hasPrefix: @"red"]) - { - colorDef->red = [[s substringFromIndex: 3] intValue]; - } - else if ([s hasPrefix: @"green"]) - { - colorDef->green = [[s substringFromIndex: 4] intValue]; - } - else - { - colorDef->blue = [[s substringFromIndex: 4] intValue]; - } - } - else - { - ADVANCE; - } - - } - - return colorTable; -} - -// -// Possible formats: -// -// {\fonttbl\f0\fswiss Helvetica;} -// {\fonttbl{\f0\froman\fcharset0\fprq2 Arial;}{\f1\fswiss\fprq2\fcharset0 Arial;}} -// -// FIXME: Complex ones not handled right now: -// -// {\fonttbl{\f2\fnil\fcharset256\fprq2{\*\panose 00020703090202050204}Courier New;}{... -// {\fonttbl{\f31\fnil\fcharset0\fprq0 Times New Roman Monotype{\*\falt Times New Roman};}{... -// -// We receive the full string. -// -- (RTFFontTable *) parseFontTable -{ - RTFFontTable *fontTable; - RTFFontInfo *fontInfo; - - unsigned int level; - - fontTable = [[[RTFFontTable alloc] init] autorelease]; - fontInfo = nil; - level = 0; - - do - { - if (*_bytes == '{') - { - if (fontTable && level == 1) - { - fontInfo = [[[RTFFontInfo alloc] init] autorelease]; - } - ADVANCE; - level++; - } - else if (*_bytes == '}') - { - if (fontTable && level == 2) //&& ![NSAllMapTableValues(fontTable->fontInfos) containsObject: fontInfo]) - { - [fontTable addFontInfo: fontInfo atIndex: fontInfo->index]; - } - ADVANCE; - level--; - } - else if (*_bytes == '\\') - { - const char *cw; - unsigned int len; - BOOL hasArg; - int arg; - NSString *cwKey; - fontCommandWordId cwId; - - cw = [self parseControlWordAndSetLenIn: &len - setHasIntArgumentIn: &hasArg - setIntArgumentIn: &arg]; - if (level != 2) - continue; - else if (cw == NULL) - continue; - - cwKey= [[NSString alloc] initWithBytesNoCopy: (void *)cw - length: len - encoding: NSASCIIStringEncoding - freeWhenDone: NO]; - [cwKey autorelease]; - - cwId = (fontCommandWordId) NSMapGet(_fontCws, cwKey); - switch (cwId) - { - case FONTCW_F: - if (hasArg) - fontInfo->index = arg; - break; - case FONTCW_FBIDI: - fontInfo->family = @"bidi"; - break; - case FONTCW_FCHARSET: - if (hasArg) - fontInfo->charset = arg; - break; - case FONTCW_FDECOR: - fontInfo->family = @"decor"; - break; - case FONTCW_FMODERN: - fontInfo->family = @"modern"; - break; - case FONTCW_FNIL: - fontInfo->family = @"nil"; - break; - case FONTCW_FPRQ: - if (hasArg) - fontInfo->pitch = arg; - break; - case FONTCW_FROMAN: - fontInfo->family = @"roman"; - break; - case FONTCW_FSCRIPT: - fontInfo->family = @"script"; - break; - case FONTCW_FSWISS: - fontInfo->family = @"swiss"; - break; - case FONTCW_FTECH: - fontInfo->family = @"tech"; - break; - case FONTCW_UNKNOWN: - default: - // do nothing - break; - } - } - else // no char - { - if (level == 2 && isalnum(*_bytes)) - { - // we assume this is the fontname - unsigned int fontnameLen; - const char *delim = strpbrk(_bytes, ";{}\\"); - if (delim == NULL) - { - // no delimiter found, we skip to next characters - ADVANCE; - continue; - } - fontnameLen = delim - _bytes; - // only valid if the delimiter is a correct ';' - if (*delim == ';') - { - // there is no explicit limit length but we took 100 - // as protection - if (delim && fontnameLen <= FONTNAME_LEN_MAX) - { - fontInfo->name = [[NSString alloc] initWithBytesNoCopy: (char *) _bytes - length: fontnameLen - encoding: NSASCIIStringEncoding - freeWhenDone: NO]; - ADVANCE_N(fontnameLen); - } - } - else { - // advance just before the special character - ADVANCE_N(fontnameLen - 1); - } - } - ADVANCE; - } - - } while (level > 0); - - return fontTable; -} - -// -// -// -- (void) parseStyleSheet -{ - unsigned int count; - - count = 0; - - do - { - if (*_bytes == '{') - { - count++; - } - else if (*_bytes == '}') - { - count--; - } - ADVANCE; - - } while (count != 0); -} - -- (void) parseIgnoringEverything -{ - unsigned int count = 1; - // Ignore everything. But we cannot parse it blindly because it could have - // binary data with '}' and '{' bytes, so disasters can happen and they will - do - { - if (*_bytes == '\\') - { - unsigned int binary_size, len = 0, cw_len; - const char *cw = [self parseControlWord: &len]; - cw_len = strlen("bin"); - if (strncmp(cw, "bin", cw_len) == 0 && len > cw_len) - { - NSString *s; - s = [[NSString alloc] initWithBytesNoCopy: (void *) cw + cw_len - length: len - cw_len - encoding: NSASCIIStringEncoding - freeWhenDone: NO]; - [s autorelease]; - binary_size = [s intValue]; - ADVANCE_N(binary_size); - } - } - - if (*_bytes == '{') count++; - if (*_bytes == '}') count--; - ADVANCE; - } - while (count > 0); -} - -// -// -// -- (void) parsePicture -{ - [self parseIgnoringEverything]; -} - - -// todo: This keyword is only valid in the RTF header section right after the \ansi, \mac, \pc or \pca keyword. -inline static void parseAnsicpg (BOOL hasArg, int arg, const unsigned short **out_default_char) -{ - NSString *key; - const unsigned short *res; - - if (!hasArg) - return; - key = [NSString stringWithFormat: @"anscicpg%i", arg]; - res = NSMapGet(_charsets, key); - if (res) - *out_default_char = res; -} - -inline static void parseB(RTFHandler *self, BOOL hasArg, int arg, RTFFormattingOptions *formattingOptions) -{ - if (!formattingOptions) - return; - if (hasArg && arg == 0) - { - [self->_html appendBytes: "" length: 4]; - formattingOptions->bold = NO; - } - else - { - [self->_html appendBytes: "" length: 3]; - formattingOptions->bold = YES; - } -} - -inline static void parseCf(RTFHandler *self, BOOL hasArg, int arg, RTFFormattingOptions *formattingOptions, RTFColorTable *colorTable) -{ - RTFColorDef *colorDef; - char *v; - - if (!hasArg) - return; - if (!formattingOptions) - return; - - colorDef = [colorTable colorDefAtIndex: arg]; - if (!colorDef) - return; - - if (formattingOptions->color_index >= 0) - { - [self->_html appendBytes: "" length: 7]; - } - - formattingOptions->color_index = arg; - - v = calloc(23, sizeof(char)); - sprintf(v, "", colorDef->red, colorDef->green, colorDef->blue); - [self->_html appendBytes: v length: strlen(v)]; - free(v); -} - - -inline static void parseColorTableWrapper(RTFHandler *self, RTFColorTable **colorTable) -{ - *colorTable = [self parseColorTable]; -} - -inline static void parseF(RTFHandler *self, BOOL hasArg, int arg, RTFFormattingOptions *formattingOptions, RTFFontTable *fontTable) -{ - RTFFontInfo *fontInfo; - - if (!hasArg) - return; - if (!formattingOptions) - return; - - if (formattingOptions->font_index >= 0 && arg != formattingOptions->font_index) - { - [self->_html appendBytes: "" length: 7]; - } - - formattingOptions->font_index = arg; - - fontInfo = [fontTable fontInfoAtIndex: arg]; - char *v = NULL; - if (fontInfo && fontInfo->name) - { - if ([fontInfo->name length] < 128) - { - int tag_size = 15 + [fontInfo->name length]; - v = calloc(tag_size, sizeof(char)); - snprintf(v, tag_size, "", [fontInfo->name UTF8String]); - } - else - { - NSLog(@"RTFHandler: Font %u has %d chars length, parse error? " - "Ignored", arg, [fontInfo->name length]); - v = calloc(7, sizeof(char)); - sprintf(v, ""); - } - } - else - { - // RTF badformed? We don't know about that font (arg index not found). - // Anyhow, we still open the html tag because in the future - // we will close it (e.g. when new font is used). - v = calloc(7, sizeof(char)); - sprintf(v, ""); - } - - if (fontInfo && fontInfo->charset) - { - if (fontInfo->charset == DEFAULT_CHARSET) - /* charset 1 is default charset */ - formattingOptions->charset = NULL; - else { - NSNumber *key = [NSNumber numberWithUnsignedChar: fontInfo->charset]; - formattingOptions->charset = NSMapGet(_charsets, key); - } - } - - [self->_html appendBytes: v length: strlen(v)]; - free(v); -} - -inline static void parseFontTableWrapper(RTFHandler *self, const char * cw, RTFFontTable **fontTable) -{ - // We rewind our buffer so we start at the beginning of {\fonttbl... - self->_bytes = cw-2; - self->_current_pos -= 9; // Length: {\fonttbl - *fontTable = [self parseFontTable]; - - // We go back 1 byte in order to end our section properly ('}' character) - REWIND; -} - -inline static void parseI(RTFHandler *self, BOOL hasArg, int arg, RTFFormattingOptions *formattingOptions) -{ - if (!formattingOptions) - return; - if (hasArg && arg == 0) - { - [self->_html appendBytes: "" length: 4]; - formattingOptions->italic = NO; - } - else - { - [self->_html appendBytes: "" length: 3]; - formattingOptions->italic = YES; - } -} - -inline static void parsePar(RTFHandler *self) -{ - [self->_html appendBytes: "
" length: 4]; -} - -inline static void parsePictureWrapper(RTFHandler *self, const char * cw) -{ - self->_bytes = cw-2; - self->_current_pos -= 6; // Length: {\pict - [self parsePicture]; - REWIND; -} - -// same implementation that /par -inline static void parseSoftline(RTFHandler *self) -{ - [self->_html appendBytes: "
" length: 4]; -} - -inline static void parseStrike(RTFHandler *self, BOOL hasArg, int arg, RTFFormattingOptions *formattingOptions) -{ - if (!formattingOptions) - return; - if (hasArg && arg == 0) - { - [self->_html appendBytes: "" length: 9]; - formattingOptions->strikethrough = NO; - } - else - { - [self->_html appendBytes: "" length: 8]; - formattingOptions->strikethrough = YES; - } -} - -inline static void parseStyleSheetWrapper(RTFHandler *self, const char * cw) -{ - self->_bytes = cw-2; - self->_current_pos -= 12; // Length: {\stylesheet - [self parseStyleSheet]; - REWIND; -} - -inline static void parseTab(RTFHandler *self) -{ - [self->_html appendBytes: "  " length: 12]; -} - -inline static void parseU(RTFHandler *self, BOOL hasArg, int arg) -{ - unichar uch; - NSString *s; - NSData *d; - - if (!hasArg) - return; - if (arg < 0) - // a negative value means a value greater than 32767 - arg = 32767 - arg; - - uch = (unichar) arg; - s = [NSString stringWithCharacters: &uch length: 1]; - d = [s dataUsingEncoding: NSUTF8StringEncoding]; - [self->_html appendData: d]; -} - -inline static void parseUl(RTFHandler *self, BOOL hasArg, int arg, RTFFormattingOptions *formattingOptions) -{ - if (!formattingOptions) - return; - if (hasArg && arg ==0) - { - [self->_html appendBytes: "" length: 4]; - formattingOptions->underline = NO; - } - else - { - [self->_html appendBytes: "" length: 3]; - formattingOptions->underline = YES; - } -} - - -- (NSMutableData *) parse -{ - RTFFormattingOptions *formattingOptions; - RTFColorTable *colorTable; - RTFFontTable *fontTable; - RTFStack *stack; - - const unsigned short *defaultCharset; - - // convenience variables for parsing - unsigned char c; - NSData *d; - NSString *s; - - stack = [[RTFStack alloc] init]; - fontTable = nil; - colorTable = nil; - defaultCharset = ansicpg1252; - formattingOptions = nil; - - _html = [[[NSMutableData alloc] init] autorelease]; - [_html appendBytes: "" length: 34]; - - - // Check if we got RTF data - // this does not allow \s\n before '}' neither newline before control command - if (_len > 4 && strncmp((const char*)_bytes, "{\\rtf", 4) != 0) - return nil; - - while (_current_pos < _len) - { - c = *_bytes; - - // RTF control code - if (c == '\\') - { - unsigned int len; - const char *cw; - BOOL hasArg; - int arg; - NSString *cwKey; - commandWordId cwId; - char nextByte = *(_bytes+1); - - if (nextByte == '\'') - { - // A hexadecimal value, based on the specified character set (may be used to identify 8-bit values). - const char *b1, *b2; - short index; - short tmp; - - const unsigned short * active_charset; - if (formattingOptions && formattingOptions->charset) - active_charset = formattingOptions->charset; - else - active_charset = defaultCharset; - - - ADVANCE; - ADVANCE; - - b1 = ADVANCE; - b2 = ADVANCE; - - tmp = (isdigit(*b1) ? *b1 - 48 : toupper(*b1) - 55); - if (tmp < 0 || tmp > 16) - { - // Incorrect first hexadecimal character. Skipping. - continue; - } - index = tmp*16; - - tmp = (isdigit(*b2) ? *b2 - 48 : toupper(*b2) - 55); - if (tmp < 0 || tmp > 16) - { - // Incorrect second hexadecimal character. Skipping. - continue; - } - index += tmp; - - s = [NSString stringWithCharacters: &(active_charset[index]) length: 1]; - d = [s dataUsingEncoding: NSUTF8StringEncoding]; - [_html appendData: d]; - continue; - } - else if (nextByte == '*') - { - [self parseIgnoringEverything]; - continue; - } - else if (!isalpha(nextByte)) - { - // escape + character - ADVANCE_N(2); - // check for special escapes for the no-implemented features - // for control of word breaking - if (nextByte == '~') - // no breaking space - nextByte = ' '; - else if (nextByte == '-') - // optional hyphen; we skip it - continue; - else if (nextByte == '_') - // no breaking hyphen, treat it as a normal hyphen - nextByte = '-'; - - [_html appendBytes: &nextByte length: 1]; - continue; - } - - - cw = [self parseControlWordAndSetLenIn: &len - setHasIntArgumentIn: &hasArg - setIntArgumentIn: &arg]; - if (cw == NULL) - continue; - - cwKey= [[NSString alloc] initWithBytesNoCopy: (void *)cw - length: len - encoding: NSASCIIStringEncoding - freeWhenDone: NO]; - [cwKey autorelease]; - - cwId = (commandWordId) NSMapGet(_cws, cwKey); - switch (cwId) - { - case CW_ANSICPG: - parseAnsicpg(hasArg, arg, &defaultCharset); - break; - case CW_B: - parseB(self, hasArg, arg, formattingOptions); - break; - case CW_CF: - parseCf(self, hasArg, arg, formattingOptions, colorTable); - break; - case CW_COLORTBL: - parseColorTableWrapper(self, &colorTable); - break; - case CW_F: - parseF(self, hasArg, arg, formattingOptions, fontTable); - break; - case CW_FONTTBL: - parseFontTableWrapper(self, cw, &fontTable); - break; - case CW_I: - parseI(self, hasArg, arg, formattingOptions); - break; - case CW_PAR: - parsePar(self); - break; - case CW_PICT: - parsePictureWrapper(self, cw); - break; - case CW_SOFTLINE: - parseSoftline(self); - break; - case CW_STRIKE: - parseStrike(self, hasArg, arg, formattingOptions); - break; - case CW_STYLESHEET: - parseStyleSheetWrapper(self, cw); - break; - case CW_TAB: - parseTab(self); - break; - case CW_U: - parseU(self, hasArg, arg); - break; - case CW_UL: - parseUl(self, hasArg, arg, formattingOptions); - break; - case CW_ULNONE: - parseUl(self, YES, 0, formattingOptions); - break; - case CW_UNKNOWN: - default: - // do nothing - break; - } - - // If a space delimits the control word, the space does not appear in the document. - // Any characters following the delimiter, including spaces, will appear in the document. (except newline!) - if (*_bytes == ' ') - { - ADVANCE; - } - } - else if (c == '{') - { - formattingOptions = [[[RTFFormattingOptions alloc] init] autorelease]; - - formattingOptions->bold = NO; - formattingOptions->italic = NO; - formattingOptions->strikethrough = NO; - formattingOptions->underline = NO; - formattingOptions->font_index = -1; - formattingOptions->color_index = -1; - formattingOptions->start_pos = [_html length]; - formattingOptions->charset = defaultCharset; - [stack push: formattingOptions]; - ADVANCE; - } - else if (c == '}') - { - formattingOptions = [stack pop]; - - if (formattingOptions) - { - // Handle {\b bold} vs. \b bold \b0 - if (formattingOptions->bold) - { - [_html appendBytes: "
" length: 4]; - } - - if (formattingOptions->italic) - { - [_html appendBytes: "" length: 4]; - } - - if (formattingOptions->strikethrough) - { - [_html appendBytes: "" length: 9]; - } - - if (formattingOptions->underline) - { - [_html appendBytes: "" length: 4]; - } - - if (formattingOptions->font_index >= 0) - { - [_html appendBytes: "" length: 7]; - } - - if (formattingOptions->color_index >= 0) - { - [_html appendBytes: "" length: 7]; - } - } - - formattingOptions = [stack top]; - ADVANCE; - } - else - { - c = *_bytes; - // We avoid appending NULL bytes or endlines - if (c && (c != '\n') && (c != '\r')) - { - const unsigned short * active_charset; - if (formattingOptions && formattingOptions->charset) - active_charset = formattingOptions->charset; - else - active_charset = defaultCharset; - - s = [NSString stringWithCharacters: &(active_charset[c]) length: 1]; - d = [s dataUsingEncoding: NSUTF8StringEncoding]; - [_html appendData: d]; - } - ADVANCE; - } - } - - [_html appendBytes: "" length: 14]; - - [stack release]; - return _html; -} - -/* This method is for ease of testing and should not be used in normal operations */ -- (void) mangleInternalStateWithBytesPtr: (const char*) newBytes - andCurrentPos: (int) newCurrentPos -{ - _bytes = newBytes; - _current_pos = newCurrentPos; -} - -@end diff --git a/Attic/OpenChange/SOGoCacheGCSObject+MAPIStore.h b/Attic/OpenChange/SOGoCacheGCSObject+MAPIStore.h deleted file mode 100644 index da8452e3d..000000000 --- a/Attic/OpenChange/SOGoCacheGCSObject+MAPIStore.h +++ /dev/null @@ -1,32 +0,0 @@ -/* SOGoCacheGCSObject+MAPIStore.h - this file is part of SOGo - * - * Copyright (C) 2014 Inverse inc. - * - * 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 SOGOCACHEGCSOBJECTMAPISTORE -#define SOGOCACHEGCSOBJECTMAPISTORE - -#include - -@interface SOGoCacheGCSObject (MAPIStore) - -- (Class) mapistoreMessageClass; - -@end - -#endif // SOGOCACHEGCSOBJECTMAPISTORE diff --git a/Attic/OpenChange/SOGoCacheGCSObject+MAPIStore.m b/Attic/OpenChange/SOGoCacheGCSObject+MAPIStore.m deleted file mode 100644 index 679bee089..000000000 --- a/Attic/OpenChange/SOGoCacheGCSObject+MAPIStore.m +++ /dev/null @@ -1,68 +0,0 @@ -/* SOGoCacheGCSObject+MAPIStore.m - this file is part of SOGo - * - * Copyright (C) 2014 Inverse inc. - * - * 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. - */ - -#import -#import -#import - -#include "MAPIStoreTypes.h" - -#include "SOGoCacheGCSObject+MAPIStore.h" - -@implementation SOGoCacheGCSObject (MAPIStore) - -- (Class) mapistoreMessageClass -{ - NSString *className, *mapiMsgClass; - - switch (objectType) - { - case MAPIMessageCacheObject: - mapiMsgClass = [properties - objectForKey: MAPIPropertyKey (PidTagMessageClass)]; - if (mapiMsgClass) - { - if ([mapiMsgClass isEqualToString: @"IPM.StickyNote"]) - className = @"MAPIStoreNotesMessage"; - else - className = @"MAPIStoreDBMessage"; - //[self logWithFormat: @"PidTagMessageClass = '%@', returning '%@'", - // mapiMsgClass, className]; - } - else - { - //[self warnWithFormat: @"PidTagMessageClass is not set, falling back" - // @" to 'MAPIStoreDBMessage'"]; - className = @"MAPIStoreDBMessage"; - } - break; - case MAPIFAICacheObject: - className = @"MAPIStoreFAIMessage"; - break; - default: - [NSException raise: @"MAPIStoreIOException" - format: @"message class should not be queried for objects" - @" of type '%d'", objectType]; - } - - return NSClassFromString (className); -} - -@end diff --git a/Attic/OpenChange/SOGoMAPIDBMessage.h b/Attic/OpenChange/SOGoMAPIDBMessage.h deleted file mode 100644 index 4211988f6..000000000 --- a/Attic/OpenChange/SOGoMAPIDBMessage.h +++ /dev/null @@ -1,32 +0,0 @@ -/* SOGoMAPIDBMessage.h - this file is part of SOGo - * - * Copyright (C) 2012-2014 Inverse inc. - * - * 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 SOGOMAPIDBMESSAGE_H -#define SOGOMAPIDBMESSAGE_H - -#import - -@class NSDate; -@class NSString; - -@interface SOGoMAPIDBMessage : SOGoCacheGCSObject -@end - -#endif /* SOGOMAPIDBMESSAGE_H */ diff --git a/Attic/OpenChange/SOGoMAPIDBMessage.m b/Attic/OpenChange/SOGoMAPIDBMessage.m deleted file mode 100644 index 343b90334..000000000 --- a/Attic/OpenChange/SOGoMAPIDBMessage.m +++ /dev/null @@ -1,61 +0,0 @@ -/* SOGoMAPIDBMessage.m - this file is part of SOGo - * - * Copyright (C) 2012 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. - */ - -#import -#import -#import -#import -#import -#import -#import - -#import - -#import - -#import "SOGoMAPIDBMessage.h" - -@implementation SOGoMAPIDBMessage - -- (Class) mapistoreMessageClass -{ - // NSArray *dirMembers; - NSString *className; - - [NSException raise: @"whereisthisusedexception" - format: @"this exception should be triggered only for tracing"]; - // /* FIXME: this method is a bit dirty */ - // dirMembers = [[container directory] componentsSeparatedByString: @"/"]; - // if ([dirMembers containsObject: @"fai"]) /* should not occur as FAI message - // are instantiated directly in - // MAPIStoreFolder */ - // className = @"MAPIStoreFAIMessage"; - // else if ([dirMembers containsObject: @"notes"]) - // className = @"MAPIStoreNotesMessage"; - // else - // className = @"MAPIStoreDBMessage"; - - className = @"nimportequoi"; - return NSClassFromString (className); -} - -@end diff --git a/Attic/OpenChange/classes.txt b/Attic/OpenChange/classes.txt deleted file mode 100644 index 37f8287b0..000000000 --- a/Attic/OpenChange/classes.txt +++ /dev/null @@ -1,26 +0,0 @@ -class hierarchy (*: end points) - -MAPIStoreContext - MAPIStoreGCSBaseContext - * MAPIStoreCalendarContext - * MAPIStoreContactsContext - * MAPIStoreTasksContext - * MAPIStoreMailContext - * MAPIStoreOutboxContext - * MAPIStoreSpoolerContext - MAPIStoreFileSystemBaseContext - * MAPIStoreCommonViewsContext - * MAPIStoreDeferredActionsContext - * MAPIStoreDraftsContext - * MAPIStoreJournalContext - * MAPIStoreNotesContext - * MAPIStoreRemindersContext - * MAPIStoreSearchContext - * MAPIStoreSentItemsContext - * MAPIStoreShortcutsContext - - (undecided:) - DeletedItems (trash IMAP folder?) - Freebusy (needs info) - Schedule (needs info + purpose?) - Views (needs info + purpose) diff --git a/Attic/OpenChange/code-MAPIStorePropertySelectors.h b/Attic/OpenChange/code-MAPIStorePropertySelectors.h deleted file mode 100644 index cf2148e0d..000000000 --- a/Attic/OpenChange/code-MAPIStorePropertySelectors.h +++ /dev/null @@ -1,27 +0,0 @@ -/* code-MAPIStorePropertySelectors.h - this file is part of SOGo - * - * Copyright (C) 2011-2012 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 enum mapistore_error (*MAPIStorePropertyGetter) (id inst, SEL _cmd, - void **data, TALLOC_CTX *memCtx); - -const MAPIStorePropertyGetter *MAPIStorePropertyGettersForClass (Class klass); -SEL MAPIStoreSelectorForPropertyGetter (uint16_t propertyId); diff --git a/Attic/OpenChange/code-MAPIStorePropertySelectors.m b/Attic/OpenChange/code-MAPIStorePropertySelectors.m deleted file mode 100644 index 86ac76f20..000000000 --- a/Attic/OpenChange/code-MAPIStorePropertySelectors.m +++ /dev/null @@ -1,73 +0,0 @@ -/* code-MAPIStorePropertySelectors.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -#import -#import - -#undef DEBUG -#include - -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)); - NSMapInsert (classesTable, klass, getters); - 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/Attic/OpenChange/dbmsgreader.m b/Attic/OpenChange/dbmsgreader.m deleted file mode 100644 index 5ad74b82b..000000000 --- a/Attic/OpenChange/dbmsgreader.m +++ /dev/null @@ -1,160 +0,0 @@ -/* dbmsgreader.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 Inverse inc - * 2015 Enrique J. Hernandez - * - * - * 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. - */ - -/* A format-agnostic property list readerer. - Usage: dbmsgreader [username] [filename] */ - -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#import - -#import "MAPIStoreUserContext.h" -#import - -#import -#import "NSObject+PropertyList.h" - - -Class MAPIStoreUserContextK, SOGoCacheGCSObjectK, NSStringK; - -static void -DumpBSONData(NSData *data) -{ - id key, value; - NSEnumerator *dictEnum; - NSDictionary *dvalue; - NSMutableString *outStr; - NSUInteger max; - - dvalue = [data BSONValue]; - max = [dvalue count]; - dictEnum = [dvalue keyEnumerator]; - NSStringK = [NSString class]; - outStr = [NSMutableString stringWithFormat: @"{ %d items\n", max]; - while ((key = [dictEnum nextObject])) - { - uint32_t proptag = 0; - if ([key isKindOfClass: NSStringK] && [(NSString *)key intValue] > 0) - proptag = [(NSString *)key intValue]; - - if (proptag > 0) - { - const char *propTagName = get_proptag_name (proptag); - NSString *propName; - - if (propTagName) - propName = [NSString stringWithCString: propTagName - encoding: NSUTF8StringEncoding]; - else - propName = [NSString stringWithFormat: @"0x%.4x", [key unsignedLongValue]]; - - [outStr appendFormat: @" %@ = ", propName]; - } - else - [outStr appendFormat: @" %@ = ", key]; - - value = [dvalue objectForKey: key]; - [outStr appendFormat: @"(%@) %@,\n", NSStringFromClass ([value class]), value]; - } - [outStr appendFormat: @"}\n"]; - printf ("%s\n", [outStr UTF8String]); -} - -static void -DbDumpObject (NSString *username, NSString *path) -{ - id ctx; - NSData *content; - id dbobject; - NSDictionary *record; - - ctx = [MAPIStoreUserContextK userContextWithUsername: username - andTDBIndexing: NULL]; - dbobject = [SOGoCacheGCSObjectK new]; - [dbobject setTableUrl: [ctx folderTableURL]]; - record = [dbobject lookupRecord: path newerThanVersion: -1]; - if (record) - { - printf("record found: %p\n", record); - content = [[record objectForKey: @"c_content"] dataByDecodingBase64]; - DumpBSONData (content); - } - else - NSLog (@"record not found"); - - [dbobject release]; -} - -int main (int argc, char *argv[], char *envp[]) -{ - NSAutoreleasePool *pool; - SOGoProductLoader *loader; - NSUserDefaults *ud; - SoProductRegistry *registry; - NSArray *arguments; - - /* Here we work around a bug in GNUstep which decodes XML user - defaults using the system encoding rather than honouring - the encoding specified in the file. */ - putenv ("GNUSTEP_STRING_ENCODING=NSUTF8StringEncoding"); - - pool = [NSAutoreleasePool new]; - - [SOGoSystemDefaults sharedSystemDefaults]; - - /* We force the plugin to base its configuration on the SOGo tree. */ - ud = [NSUserDefaults standardUserDefaults]; - [ud registerDefaults: [ud persistentDomainForName: @"sogod"]]; - - [NSProcessInfo initializeWithArguments: argv - count: argc - environment: envp]; - - registry = [SoProductRegistry sharedProductRegistry]; - [registry scanForProductsInDirectory: SOGO_BUNDLES_DIR]; - - loader = [SOGoProductLoader productLoader]; - [loader loadProducts: [NSArray arrayWithObject: BACKEND_BUNDLE_NAME]]; - - MAPIStoreUserContextK = NSClassFromString (@"MAPIStoreUserContext"); - SOGoCacheGCSObjectK = NSClassFromString (@"SOGoCacheGCSObject"); - - arguments = [[NSProcessInfo processInfo] arguments]; - if ([arguments count] > 2) { - DbDumpObject ([arguments objectAtIndex: 1], - [arguments objectAtIndex: 2]); - } else if ([arguments count] > 1) { - DumpBSONData([[arguments objectAtIndex:1] dataByDecodingBase64]); - } - - [pool release]; - - return 0; -} diff --git a/Attic/OpenChange/gen-charset-table.py b/Attic/OpenChange/gen-charset-table.py deleted file mode 100755 index 1bcc1aa17..000000000 --- a/Attic/OpenChange/gen-charset-table.py +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/python - -import getopt -import os -import re -import string -import sys - -h_template = """unsigned short %(charsetName)s[%(len)d] = { %(values)s };""" -CHAR_UNDEF = "0x0000" -MAP_LEN = 256 -itemsPerLine = 16 - -def usage(): - usageMsg = """ -Usage: %s -f inputFile -""" % (os.path.basename(sys.argv[0])) - sys.stderr.write(usageMsg) - -def parseCharsetFile(file = None): - if file is None: - return None - - charmap = [CHAR_UNDEF] * MAP_LEN - - # Sample line: - # FD = U+200E : LEFT-TO-RIGHT MARK - for line in file.xreadlines(): - m = re.search("(\w{2}) = U\+(\w{4}) :", line) - if not m: - sys.stderr.write("Skipping weird line: %s" % line) - continue - - ind = int(m.group(1), base=16) - unicodeValue = str(m.group(2)).lower() - - charmap[ind] = "0x%s" % (unicodeValue) - - return charmap - - -def formatCharacterMap(charmap = None): - if not charmap: - return None - - value = "" - for i in xrange(0,MAP_LEN-1): - char = charmap[i] - if i % itemsPerLine == 0: - value += "\n " - value += "%s, " % (char) - i += 1 - value += charmap[MAP_LEN-1] - - return value - -if __name__ == '__main__': - inputFile = None - - try: - opts, args = getopt.getopt(sys.argv[1:], "f:") - except getopt.GetoptError, err: - sys.stderr.write(str(err)) - usage() - sys.exit(2) - - for o, a in opts: - if o == "-f": - inputFile = a - else: - assert False, "unhandled option" - - if not inputFile: - usage() - sys.exit(1) - - - f = open(inputFile, "r", 1) - - charsetMap = parseCharsetFile(f) - charsetValues = formatCharacterMap(charsetMap) - print h_template % {"len": len(charsetMap), - "charsetName": os.path.basename(inputFile), - "values": charsetValues} diff --git a/Attic/OpenChange/gen-property-selectors.py b/Attic/OpenChange/gen-property-selectors.py deleted file mode 100755 index d0431784b..000000000 --- a/Attic/OpenChange/gen-property-selectors.py +++ /dev/null @@ -1,266 +0,0 @@ -#!/usr/bin/python - -include_dirs = [ "/usr/include" ] - -output = "-" - -import os -import sys - -m_template = """/* %(filename)s (auto-generated) */ - -#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) */ - -#ifndef %(h_exclusion)s -#define %(h_exclusion)s 1 - -#import - -#include -#include -#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 */ -""" - -# hack: some properties have multiple and incompatible types. Sometimes those -# props are not related at all... -bannedProps = set(["PidTagBodyHtml", "PidTagFavAutosubfolders", - "PidTagAttachDataObj", "PidTagAclTable", "PidTagAclData", - "PidTagRulesTable", "PidTagRulesData", - "PidTagDisableWinsock", - "PidTagHierarchyServer", "PidTagOfflineAddrbookEntryid", - "PidTagShorttermEntryidFromObject", - "PidTagNormalMessageSizeExtended", - "PidTagAssocMessageSizeExtended", - "PidTagMessageSizeExtended", - "PidTagOabContainerGuid", - "PidTagOfflineAddressBookMessageClass", "PidTagScriptData", - "PidTagOfflineAddressBookTruncatedProperties", - "PidTagOfflineAddressBookContainerGuid", - "PidTagOfflineAddressBookDistinguishedName", - "PidTagOfflineAddressBookShaHash", - "PidTagSenderTelephoneNumber", - "PidTagGatewayNeedsToRefresh", - "PidTagWlinkType", "PidTagWlinkFlags", - "PidTagWlinkGroupClsid", "PidTagWlinkGroupName", - "PidTagWlinkGroupHeaderID", - "PidTagScheduleInfoDelegatorWantsCopy", - "PidTagWlinkOrdinal", - "PidTagWlinkSection", "PidTagWlinkCalendarColor", - "PidTagWlinkAddressBookEID", "PidTagWlinkFolderType", - "PidTagScheduleInfoDelegateNames", - "PidTagScheduleInfoDelegateEntryIds", - "PidTagBusiness2TelephoneNumbers", - "PidTagHome2TelephoneNumbers", - "PidTagAttachDataObject", - "PidTagShorttermEntryIdFromObject", - ]) - -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 ParseExchangeHDefinition(names, line): - stripped = line.strip() - eqIdx = stripped.find("=") - if eqIdx == -1: - raise Exception, "line does not contain a '='" - - propName = stripped[0:eqIdx] - if not propName.endswith("_Error") and not propName.endswith("_string8") \ - and propName not in bannedProps: - intIdx = stripped.find("(int", eqIdx) - valueIdx = stripped.find("0x", intIdx + 1) - endIdx = stripped.find(")", valueIdx) - value = int(stripped[valueIdx:endIdx], 16) - if value < 0x80000000: - 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() - if not propName.startswith("PidLidUnknown") and propName not in bannedProps: - 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: - 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") - - prop_types = {} - # sanitization: only take unicode version of text properties - for name, prop_tag in names.iteritems(): - prop_id = prop_tag >> 16 - prop_type = prop_tag & 0xffff - if not prop_id in prop_types: - prop_types[prop_id] = [] - prop_types[prop_id].append(prop_type) - if (prop_type & 0xfff) == 0x001e: - prop_tag = (prop_tag & 0xfffff000) | 0x001f - names[name] = prop_tag - - #sanitization: report multiple types for the same keynames - for prop_id, xtypes in prop_types.iteritems(): - cnt = len(xtypes) - if cnt > 1: - print "%d types available for prop id 0x%.4x: %s" % (cnt, prop_id, ", ".join(["%.4x" % x for x in xtypes])) - - supported_properties = [] - current_getter_idx = 0 - highest_prop_idx = 0 - for name, prop_tag in names.iteritems(): - supported_properties.append(" 0x%.8x" % prop_tag); - prop_idx = (prop_tag & 0xffff0000) >> 16 - getters_idx[prop_idx] = " 0x%.4x" % current_getter_idx - if prop_idx > highest_prop_idx: - highest_prop_idx = prop_idx - getters.append(" @selector (get%s:inMemCtx:)" % name) - # preferred_types.append(" 0x%.4x" % (prop_tag & 0xffff)) - prototypes.append("- (enum mapistore_error) get%s: (void **) data inMemCtx: (TALLOC_CTX *) memCtx;" % 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/Attic/OpenChange/iCalEvent+MAPIStore.h b/Attic/OpenChange/iCalEvent+MAPIStore.h deleted file mode 100644 index 8d73923e1..000000000 --- a/Attic/OpenChange/iCalEvent+MAPIStore.h +++ /dev/null @@ -1,44 +0,0 @@ -/* iCalEvent+MAPIStore.h - this file is part of SOGo - * - * Copyright (C) 2012 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. - */ - -#ifndef ICALEVENT_MAPISTORE_H -#define ICALEVENT_MAPISTORE_H - -#include - -#import - -@class MAPIStoreUserContext; -@class NSDictionary; -@class NSString; -@class SOGoUser; - -@interface iCalEvent (MAPIStoreProperties) - -- (void) updateFromMAPIProperties: (NSDictionary *) properties - inUserContext: (MAPIStoreUserContext *) userContext - withActiveUser: (SOGoUser *) activeUser - isNew: (BOOL) isNew - inMemCtx: (TALLOC_CTX *) memCtx; -@end - -#endif /* ICALEVENT_MAPISTORE_H */ diff --git a/Attic/OpenChange/iCalEvent+MAPIStore.m b/Attic/OpenChange/iCalEvent+MAPIStore.m deleted file mode 100644 index 1bf0d261a..000000000 --- a/Attic/OpenChange/iCalEvent+MAPIStore.m +++ /dev/null @@ -1,587 +0,0 @@ -/* iCalEvent+MAPIStore.m - this file is part of SOGo - * - * Copyright (C) 2012 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. - */ - -#include - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#import "MAPIStoreAppointmentWrapper.h" -#import "MAPIStoreCalendarAttachment.h" -#import "MAPIStoreCalendarFolder.h" -#import "MAPIStoreContext.h" -#import "MAPIStoreMapping.h" -#import "MAPIStoreRecurrenceUtils.h" -#import "MAPIStoreTypes.h" -#import "MAPIStoreUserContext.h" -#import "NSDate+MAPIStore.h" -#import "NSData+MAPIStore.h" -#import "NSObject+MAPIStore.h" -#import "NSString+MAPIStore.h" -#import "NSValue+MAPIStore.h" - -#import "MAPIStoreCalendarMessage.h" - -#undef DEBUG -#include -#include -#include -#include -#include -#include -#include - -#import "iCalEvent+MAPIStore.h" -#import "iCalTimeZone+MAPIStore.h" - -@implementation iCalEvent (MAPIStoreProperties) - -- (void) _setupEventRecurrence: (NSData *) mapiRecurrenceData - inTimeZone: (iCalTimeZone *) tz - inMemCtx: (TALLOC_CTX *) memCtx -{ - struct Binary_r *blob; - struct AppointmentRecurrencePattern *pattern; - - blob = [mapiRecurrenceData asBinaryInMemCtx: memCtx]; - pattern = get_AppointmentRecurrencePattern (memCtx, blob); - - if (pattern == NULL) { - [self logWithFormat: @"Error parsing recurrence pattern. No changes in event recurrence will be done"]; - return; - } - - [(iCalCalendar *) parent setupRecurrenceWithMasterEntity: self - fromRecurrencePattern: &pattern->RecurrencePattern - withExceptions: pattern->ExceptionInfo - andExceptionCount: pattern->ExceptionCount - inTimeZone: tz - ]; - //talloc_free (blob); -} - -- (void) _setupEventAlarmFromProperties: (NSDictionary *) properties -{ - NSArray *alarms; - iCalAlarm *currentAlarm, *alarm = nil; - iCalTrigger *trigger; - NSNumber *delta; - NSString *action; - NSUInteger count, max; - - /* find and remove first display alarm */ - alarms = [self alarms]; - max = [alarms count]; - for (count = 0; !alarm && count < max; count++) - { - currentAlarm = [alarms objectAtIndex: count]; - action = [[currentAlarm action] lowercaseString]; - if (!action || [action isEqualToString: @"display"]) - alarm = currentAlarm; - } - - if (alarm) - [self removeChild: alarm]; - - if ([[properties objectForKey: MAPIPropertyKey (PidLidReminderSet)] - boolValue]) - { - delta - = [properties objectForKey: MAPIPropertyKey (PidLidReminderDelta)]; - if (delta) - { - alarm = [iCalAlarm new]; - [alarm setAction: @"DISPLAY"]; - trigger = [iCalTrigger elementWithTag: @"trigger"]; - [trigger setValueType: @"DURATION"]; - [trigger - setSingleValue: [NSString stringWithFormat: @"-PT%@M", delta] - forKey: @""]; - [alarm setTrigger: trigger]; - [self addToAlarms: alarm]; - [alarm release]; - } - } -} - -- (int) _updateFromAttendeeMAPIProperties: (NSArray *) recipients - withRole: (NSString *) role - outParam: (BOOL *) organizerIsSet -{ - NSDictionary *dict; - NSString *attEmail; - iCalPerson *person; - iCalPersonPartStat newPartStat; - NSNumber *flags, *trackStatus; - int i, effective; - - effective = 0; - for (i = 0; i < [recipients count]; i++) - { - dict = [recipients objectAtIndex: i]; - person = [iCalPerson new]; - [person setCn: [dict objectForKey: @"fullName"]]; - attEmail = [dict objectForKey: @"email"]; - [person setEmail: attEmail]; - - flags = [dict objectForKey: MAPIPropertyKey (PR_RECIPIENT_FLAGS)]; - if (!flags) - { - [self logWithFormat: - @"no recipient flags specified: skipping recipient"]; - continue; - } - - if (([flags unsignedIntValue] & 0x0002)) /* recipOrganizer */ - { - [self setOrganizer: person]; - *organizerIsSet = YES; - [self logWithFormat: @"organizer set via recipient flags"]; - } - else - { - BOOL isOrganizer = NO; - - // /* Work-around: it happens that Outlook still passes the - // organizer as a recipient, maybe because of a feature - // documented in a pre-mesozoic PDF still buried in a - // cavern... In that case we remove it, and we keep the - // number of effective recipients in "effective". If the - // total is 0, we remove the "ORGANIZER" too. */ - // if ([attEmail isEqualToString: orgEmail]) - // { - // [self logWithFormat: - // @"avoiding setting organizer as recipient"]; - // continue; - // } - - trackStatus = [dict objectForKey: MAPIPropertyKey (PidTagRecipientTrackStatus)]; - if (trackStatus) - { - /* FIXME: we should provide a data converter between OL - partstats and SOGo */ - switch ([trackStatus unsignedIntValue]) - { - case 0x01: /* respOrganized */ - isOrganizer = YES; - break; - case 0x02: /* respTentative */ - newPartStat = iCalPersonPartStatTentative; - break; - case 0x03: /* respAccepted */ - newPartStat = iCalPersonPartStatAccepted; - break; - case 0x04: /* respDeclined */ - newPartStat = iCalPersonPartStatDeclined; - break; - default: - newPartStat = iCalPersonPartStatNeedsAction; - } - - if (isOrganizer) - { - [self setOrganizer: person]; - *organizerIsSet = YES; - [self logWithFormat: @"organizer set via track status"]; - } - else - { - [person setParticipationStatus: newPartStat]; - [person setRsvp: @"TRUE"]; - [person setRole: role]; - [self addToAttendees: person]; - effective++; - } - } - else - [self errorWithFormat: @"skipped recipient due" - @" to missing track status"]; - } - - [person release]; - } - - return effective; -} - - -- (void) updateFromMAPIProperties: (NSDictionary *) properties - inUserContext: (MAPIStoreUserContext *) userContext - withActiveUser: (SOGoUser *) activeUser - isNew: (BOOL) isNew - inMemCtx: (TALLOC_CTX *) memCtx -{ - BOOL isAllDay; - iCalDateTime *start, *end; - iCalTimeZone *tz; - NSString *priority, *class = nil, *tzDescription = nil; - NSUInteger responseStatus = 0; - SOGoUser *ownerUser; - id value; - - // value = [properties objectForKey: MAPIPropertyKey (PidTagMessageClass)]; - // if (value) - // isException = [value isEqualToString: @"IPM.OLE.CLASS.{00061055-0000-0000-C000-000000000046}"]; - // else - // isException = NO; - - /* privacy */ - value = [properties objectForKey: MAPIPropertyKey(PidLidPrivate)]; - - if (value) - { - if ([value boolValue]) - [self setAccessClass: @"PRIVATE"]; - else - [self setAccessClass: @"PUBLIC"]; - } - - /* Time zone = PidLidAppointmentTimeZoneDefinitionRecur - or PidLidAppointmentTimeZoneDefinition[Start|End]Display */ - value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentTimeZoneDefinitionStartDisplay)]; - if (!value) - { - value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentTimeZoneDefinitionEndDisplay)]; - if (!value) - { - /* If PidLidtimeZoneStruct, TZID SHOULD come from PidLidTimeZoneDescription, - if PidLidAppointmentTimeZoneDefinition[Start|End]Display it MUST be derived from KeyName - (MS-OXCICAL] 2.1.3.1.1.19.1) */ - value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentTimeZoneDefinitionRecur)]; - tzDescription = [properties objectForKey: MAPIPropertyKey (PidLidTimeZoneDescription)]; - } - } - if (value) - { - tz = [[iCalTimeZone alloc] iCalTimeZoneFromDefinition: value - withDescription: tzDescription - inMemCtx: memCtx]; - } - else - /* The client is more likely to have the webmail's time zone than any other */ - tz = [iCalTimeZone timeZoneForName: [[userContext timeZone] name]]; - [(iCalCalendar *) parent addTimeZone: tz]; - - /* CREATED */ - value = [properties objectForKey: MAPIPropertyKey (PidTagCreationTime)]; - if (value) - [self setCreated: value]; - - // LAST-MODIFIED = PidTagLastModificationTime - value = [properties objectForKey: MAPIPropertyKey (PidTagLastModificationTime)]; - if (value) - [self setLastModified: value]; - - /* DTSTAMP = PidLidOwnerCriticalChange or PidLidAttendeeCriticalChange */ - value = [properties objectForKey: MAPIPropertyKey (PidLidOwnerCriticalChange)]; - if (value) - [self setTimeStampAsDate: value]; - - /* SUMMARY */ - value = [properties objectForKey: MAPIPropertyKey (PidTagNormalizedSubject)]; - if (value) - [self setSummary: value]; - - // Location - value = [properties objectForKey: MAPIPropertyKey (PidLidLocation)]; - if (value) - [self setLocation: value]; - - isAllDay = [self isAllDay]; - value = [properties - objectForKey: MAPIPropertyKey (PidLidAppointmentSubType)]; - if (value) - isAllDay = [value boolValue]; - - // recurrence-id - value - = [properties objectForKey: MAPIPropertyKey (PidLidExceptionReplaceTime)]; - if (value) - [self setRecurrenceId: value]; - - // start - value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentStartWhole)]; - if (!value) - value = [properties objectForKey: MAPIPropertyKey (PR_START_DATE)]; - if (value) - { - start = (iCalDateTime *) [self uniqueChildWithTag: @"dtstart"]; - [start setTimeZone: tz]; - if (isAllDay) - { - /* All-day events are set in floating time ([MS-OXCICAL] 2.1.3.1.1.20.8) */ - [start setDate: value]; - [start setTimeZone: nil]; - } - else - [start setDateTime: value]; - } - - /* end */ - value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentEndWhole)]; - if (!value) - value = [properties objectForKey: MAPIPropertyKey (PR_END_DATE)]; - if (value) - { - end = (iCalDateTime *) [self uniqueChildWithTag: @"dtend"]; - [end setTimeZone: tz]; - if (isAllDay) - { - /* All-day events are set in floating time ([MS-OXCICAL] 2.1.3.1.1.20.8) */ - [end setDate: value]; - [end setTimeZone: nil]; - } - else - [end setDateTime: value]; - } - - /* priority */ - value = [properties objectForKey: MAPIPropertyKey(PR_IMPORTANCE)]; - if (value) - { - switch ([value intValue]) - { - case 0: // IMPORTANCE_LOW - priority = @"9"; - break; - case 2: // IMPORTANCE_HIGH - priority = @"1"; - break; - default: // IMPORTANCE_NORMAL - priority = @"5"; - } - } - else - priority = @"0"; // None - [self setPriority: priority]; - - /* class */ - /* See [MS-OXCICAL] Section 2.1.3.11.20.4 */ - value = [properties objectForKey: MAPIPropertyKey(PR_SENSITIVITY)]; - if (value) - { - switch ([value intValue]) - { - case 1: - class = @"X-PERSONAL"; - break; - case 2: - class = @"PRIVATE"; - break; - case 3: - class = @"CONFIDENTIAL"; - break; - default: /* 0 as well */ - class = @"PUBLIC"; - } - } - - if (class) - [self setAccessClass: class]; - - /* Categories */ - /* See [MS-OXCICAL] Section 2.1.3.1.1.20.3 */ - value = [properties objectForKey: MAPIPropertyKey (PidNameKeywords)]; - if (value) - [self setCategories: value]; - - /* show time as free/busy/tentative/out of office. Possible values are: - 0x00000000 - olFree - 0x00000001 - olTentative - 0x00000002 - olBusy - 0x00000003 - olOutOfOffice */ - value = [properties objectForKey: MAPIPropertyKey(PidLidBusyStatus)]; - if (value) - { - switch ([value intValue]) - { - case 0: - [self setTransparency: @"TRANSPARENT"]; - break; - case 1: - case 2: - case 3: - default: - [self setTransparency: @"OPAQUE"]; - } - } - - /* Comment */ - value = [properties objectForKey: MAPIPropertyKey (PR_BODY_UNICODE)]; - if (!value) - { - value = [properties objectForKey: MAPIPropertyKey (PR_HTML)]; - if (value) - { - value = [[NSString alloc] initWithData: value - encoding: NSUTF8StringEncoding]; - [value autorelease]; - value = [value htmlToText]; - } - } - if (value) - { - if ([value length] == 0 || [value isEqualToString: @"\\n"]) - value = nil; - [self setComment: value]; - } - - /* recurrence */ - value = [properties - objectForKey: MAPIPropertyKey (PidLidAppointmentRecur)]; - if (value) - [self _setupEventRecurrence: value inTimeZone: tz inMemCtx: memCtx]; - - /* alarm */ - [self _setupEventAlarmFromProperties: properties]; - - // Organizer - value = [properties objectForKey: @"recipients"]; - if (value) - { - NSDictionary *dict; - NSString *orgEmail, *sentBy; - iCalPerson *person; - iCalPersonPartStat newPartStat; - int effective; - BOOL organizerIsSet = NO; - - [self setOrganizer: nil]; - [self removeAllAttendees]; - - /* In [MS-OXOCAL] Section 2.2.4.10.7 says the recipient type is 0x01 as Required - and 0x02 as Optional and other documents such [MS-OXCMSG] 2.2.3.1.2 indicates - that MAPI_TO is 0x01 and MAPI_CC is 0x02, that's why in SOGo is in 'to' and 'cc' - respectively. */ - effective = [self _updateFromAttendeeMAPIProperties: [value objectForKey: @"to"] - withRole: @"REQ-PARTICIPANT" - outParam: &organizerIsSet]; - effective += [self _updateFromAttendeeMAPIProperties: [value objectForKey: @"cc"] - withRole: @"OPT-PARTICIPANT" - outParam: &organizerIsSet]; - - if (effective == 0) /* See work-around inside _updateFromAttendeeMAPIProperties */ - [self setOrganizer: nil]; - else - { - // SEQUENCE = PidLidAppointmentSequence - value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentSequence)]; - if (value) - [self setSequence: value]; - - ownerUser = [userContext sogoUser]; - if (organizerIsSet) - { - /* We must reset the participation status to the value - obtained from PidLidResponseStatus as the value in - PidTagRecipientTrackStatus is not correct. Note (hack): - the method used here requires that the user directory - from LDAP and Samba matches perfectly. This can be solved - more appropriately by making use of the sender - properties... */ - person = [self userAsAttendee: ownerUser]; - if (person) - { - value - = [properties objectForKey: MAPIPropertyKey (PidLidResponseStatus)]; - if (value) - responseStatus = [value unsignedLongValue]; - - /* FIXME: we should provide a data converter between OL partstats and - SOGo */ - switch (responseStatus) - { - case 0x02: /* respTentative */ - newPartStat = iCalPersonPartStatTentative; - break; - case 0x03: /* respAccepted */ - newPartStat = iCalPersonPartStatAccepted; - break; - case 0x04: /* respDeclined */ - newPartStat = iCalPersonPartStatDeclined; - break; - default: - newPartStat = iCalPersonPartStatNeedsAction; - } - [person setParticipationStatus: newPartStat]; - - value = [properties objectForKey: MAPIPropertyKey (PidLidAttendeeCriticalChange)]; - if (value && ![value isNever]) - [self setTimeStampAsDate: value]; - } - } - else - { - [self errorWithFormat: @"organizer was not set although a" - @" recipient list was specified"]; - /* We must set the organizer preliminarily here because, unlike what - the doc states, Outlook does not always pass the real organizer - in the recipients list. */ - dict = [ownerUser primaryIdentity]; - person = [iCalPerson new]; - [person setCn: [dict objectForKey: @"fullName"]]; - orgEmail = [dict objectForKey: @"email"]; - [person setEmail: orgEmail]; - - if (![activeUser isEqual: ownerUser]) - { - dict = [activeUser primaryIdentity]; - sentBy = [NSString stringWithFormat: @"mailto:%@", - [dict objectForKey: @"email"]]; - [person setSentBy: sentBy]; - } - [self setOrganizer: person]; - [person release]; - } - } - } - // Creator (with sharing purposes) - if (isNew) - { - value = [properties objectForKey: MAPIPropertyKey (PidTagLastModifierName)]; - if (value) - [[self uniqueChildWithTag: @"x-sogo-component-created-by"] setSingleValue: value - forKey: @""]; - } -} - -@end diff --git a/Attic/OpenChange/iCalTimeZone+MAPIStore.h b/Attic/OpenChange/iCalTimeZone+MAPIStore.h deleted file mode 100644 index 25817392a..000000000 --- a/Attic/OpenChange/iCalTimeZone+MAPIStore.h +++ /dev/null @@ -1,42 +0,0 @@ -/* iCalTimeZone+MAPIStore.h - this file is part of SOGo - * - * Copyright (C) 2012 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 ICALTIMEZONE_MAPISTORE_H -#define ICALTIMEZONE_MAPISTORE_H - -#import - -@interface iCalTimeZone (MAPIStoreProperties) - -- (struct Binary_r *) asTimeZoneStructInMemCtx: (TALLOC_CTX *) memCtx; -- (struct Binary_r *) asZoneTimeDefinitionWithFlags: (enum TZRuleFlag) flags - inMemCtx: (TALLOC_CTX *) memCtx; -- (iCalTimeZone *) iCalTimeZoneFromDefinition: (NSData *) value - withDescription: (NSString *) description - inMemCtx: (TALLOC_CTX *) memCtx; -- (NSCalendarDate *) shiftedCalendarDateForDate: (NSCalendarDate *) date; - - -@end - - -#endif /* ICALTIMEZONE_MAPISTORE_H */ diff --git a/Attic/OpenChange/iCalTimeZone+MAPIStore.m b/Attic/OpenChange/iCalTimeZone+MAPIStore.m deleted file mode 100644 index 7cf380fdf..000000000 --- a/Attic/OpenChange/iCalTimeZone+MAPIStore.m +++ /dev/null @@ -1,377 +0,0 @@ -/* iCalTimeZone+MAPIStore.m - this file is part of SOGo - * - * Copyright (C) 2012 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. - */ - -#import -#import -#import -#import -#import -#import -#import -#import - -#import "NSString+MAPIStore.h" -#import "NSData+MAPIStore.h" -#import "NSDate+MAPIStore.h" - -#include -#include -#include -#undef DEBUG -#include - -#import "iCalTimeZone+MAPIStore.h" -#import "MAPIStoreTypes.h" - -@interface iCalTimeZonePeriod (MAPIStorePropertiesPrivate) - -- (void) _fillTZDate: (struct SYSTEMTIME *) tzData; - -@end - -@implementation iCalTimeZonePeriod (MAPIStorePropertiesPrivate) - -- (void) _fillTZDate: (struct SYSTEMTIME *) tzData -{ - iCalRecurrenceRule *rrule; - NSArray *byMonth; - iCalByDayMask *mask; - NSCalendarDate *dateValue; - int16_t wDay; - - rrule = [self recurrenceRule]; - byMonth = [rrule byMonth]; - if ([byMonth count] > 0) - { - tzData->wMonth = [[byMonth objectAtIndex: 0] intValue]; - mask = [rrule byDayMask]; - tzData->wDayOfWeek = [mask firstDay]; - wDay = [mask firstOccurrence]; - if (wDay < 0) - /* [MS-OXOCAL] the wDay field is set to indicate the - occurrence of the day of the week within the month (1 to - 5, where 5 indicates the final occurrence during the - month if that day of the week does not occur 5 times). */ - wDay += 6; - tzData->wDay = (uint16_t) wDay; - - dateValue = [self startDate]; - tzData->wHour = [dateValue hourOfDay]; - tzData->wMinute = [dateValue minuteOfHour]; - tzData->wSecond = [dateValue secondOfMinute]; - } -} - -@end - -@implementation iCalTimeZone (MAPIStoreProperties) - -- (iCalTimeZonePeriod *) _mostRecentPeriodWithName: (NSString *) periodName -{ - NSArray *periods; - iCalTimeZonePeriod *period; - NSUInteger max; - - periods = [self childrenWithTag: periodName]; - max = [periods count]; - if (max > 0) - { - periods = [periods sortedArrayUsingSelector: @selector (compare:)]; - period = (iCalTimeZonePeriod *) [periods objectAtIndex: (max - 1)]; - } - else - period = nil; - - return period; -} - -- (struct Binary_r *) asTimeZoneStructInMemCtx: (TALLOC_CTX *) memCtx -{ - iCalTimeZonePeriod *period; - struct TimeZoneStruct tz; - int32_t lBias, dlBias; - - memset (&tz, 0, sizeof (struct TimeZoneStruct)); - period = [self _mostRecentPeriodWithName: @"STANDARD"]; - lBias = -[period secondsOffsetFromGMT] / 60; - tz.lBias = lBias; - [period _fillTZDate: &tz.stStandardDate]; - period = [self _mostRecentPeriodWithName: @"DAYLIGHT"]; - if (!period) - tz.stStandardDate.wMonth = 0; - dlBias = -([period secondsOffsetFromGMT] / 60) - lBias; - tz.lDaylightBias = dlBias; - [period _fillTZDate: &tz.stDaylightDate]; - tz.wStandardYear = tz.stStandardDate.wYear; - tz.wDaylightYear = tz.stDaylightDate.wYear; - - return set_TimeZoneStruct (memCtx, &tz); -} - -- (struct Binary_r *) asZoneTimeDefinitionWithFlags: (enum TZRuleFlag) flags - inMemCtx: (TALLOC_CTX *) memCtx -{ - iCalTimeZonePeriod *period; - struct TimeZoneDefinition definition; - struct TZRule rule; - NSString *tzId; - int lBias, dlBias; - - memset (&definition, 0, sizeof (struct TimeZoneDefinition)); - - definition.major = 0x02; - definition.minor = 0x01; - definition.reserved = 0x0002; - - tzId = [self tzId]; - definition.keyName = [tzId asUnicodeInMemCtx: memCtx]; - definition.cbHeader = 6 + [tzId length] * 2; - - definition.cRules = 1; - definition.TZRules = &rule; - - memset (&rule, 0, sizeof (struct TZRule)); - rule.major = 0x02; - rule.minor = 0x01; - rule.reserved = 0x003e; - rule.flags = flags; - - period = [self _mostRecentPeriodWithName: @"STANDARD"]; - rule.wYear = [[period startDate] yearOfCommonEra]; - lBias = -[period secondsOffsetFromGMT] / 60; - rule.lBias = lBias; - [period _fillTZDate: &rule.stStandardDate]; - period = [self _mostRecentPeriodWithName: @"DAYLIGHT"]; - if (!period) - rule.stStandardDate.wMonth = 0; - dlBias = -([period secondsOffsetFromGMT] / 60) - lBias; - rule.lDaylightBias = dlBias; - [period _fillTZDate: &rule.stDaylightDate]; - - - return set_TimeZoneDefinition (memCtx, &definition); -} - -- (NSString *) _offsetStringFromOffset: (NSInteger) offset -{ - NSInteger offsetHours, offsetMins; - NSString *offsetSign; - - /* The offset format is, eg, "+0200" for 2 hours 0 minutes ahead */ - if (offset < 0) - offsetSign = @"-"; - else - offsetSign = @"+"; - offsetHours = abs (offset) / 60; - offsetMins = abs (offset) % 60; - - return [NSString stringWithFormat: @"%@%d%d%d%d", - offsetSign, offsetHours / 10, offsetHours % 10, - offsetMins / 10, offsetMins % 10]; - -} - -- (NSString *) _rRuleStringFromSystemTime: (struct SYSTEMTIME) date -{ - NSString *result, *byDay; - - /* The conversion tables between the SYSTEMTIME fields and the RRULE ones - can be found at [MS-OXCICAL] 2.1.3.2.1 */ - if (date.wDay == 5) - byDay = @"-1"; - else - byDay = [NSString stringWithFormat: @"%d", date.wDay]; - - switch (date.wDayOfWeek) - { - case iCalWeekDaySunday: - byDay = [byDay stringByAppendingString: @"SU"]; - break; - case iCalWeekDayMonday: - byDay = [byDay stringByAppendingString: @"MO"]; - break; - case iCalWeekDayTuesday: - byDay = [byDay stringByAppendingString: @"TU"]; - break; - case iCalWeekDayWednesday: - byDay = [byDay stringByAppendingString: @"WE"]; - break; - case iCalWeekDayThursday: - byDay = [byDay stringByAppendingString: @"TH"]; - break; - case iCalWeekDayFriday: - byDay = [byDay stringByAppendingString: @"FR"]; - break; - case iCalWeekDaySaturday: - byDay = [byDay stringByAppendingString: @"SA"]; - break; - } - - result = [NSString stringWithFormat: @"FREQ=YEARLY;BYDAY=%@;BYMONTH=%d", byDay, date.wMonth]; - - return result; -} - -- (iCalTimeZone *) iCalTimeZoneFromDefinition: (NSData *) value - withDescription: (NSString *) description - inMemCtx: (TALLOC_CTX *) memCtx -{ - BOOL daylightDefined = NO, ruleFound = NO; - iCalDateTime *daylightStart, *standardStart; - iCalRecurrenceRule *daylightRRule, *standardRRule; - iCalTimeZone *tz = nil; - iCalTimeZonePeriod *daylight, *standard; - NSCalendarDate *dlStartValue, *stStartValue; - NSString *strOffsetFrom, *strOffsetTo, *tzID; - char *keyName; - struct Binary_r *binValue; - struct SYSTEMTIME initDate; - struct TimeZoneDefinition *definition; - struct TZRule rule; - uint16_t count; - - binValue = [value asBinaryInMemCtx: memCtx]; - definition = get_TimeZoneDefinition (memCtx, binValue); - - if (!definition) - return nil; - - if (!definition->cRules) - goto end; - - for (count = 0; count < definition->cRules; count++) - { - /* ([MS-OXCICAL] 2.1.3.1.1.19) The TZRule with the - TZRULE_FLAG_EFFECTIVE_TZREG bit set in the TZRule flags field - is the one that MUST be exported */ - if (definition->TZRules[count].flags & TZRULE_FLAG_EFFECTIVE_TZREG) - { - rule = definition->TZRules[count]; - ruleFound = YES; - break; - } - } - - if (!ruleFound) - goto end; - - if (!description) - { - /* The cbHeader field contains the size, in bytes of the Reserved (2b), - cchKeyName (2b) keyName (variable Unicode string) and cRules (2b) - ([MS-OXOCAL] 2.2.1.41). The keyName field is a non-NULL-terminated - char array. */ - keyName = talloc_strndup (memCtx, definition->keyName, (definition->cbHeader - 6) / 2); - tzID = [NSString stringWithCString: keyName - encoding: [NSString defaultCStringEncoding]]; - talloc_free (keyName); - } - else - tzID = [NSString stringWithString: description]; - - tz = [iCalTimeZone groupWithTag: @"vtimezone"]; - [tz addChild: [CardElement simpleElementWithTag: @"tzid" - value: tzID]]; - - if (rule.stStandardDate.wMonth != 0) - daylightDefined = YES; - - /* STANDARD TIME ([MS-OXCICAL] 2.1.3.1.1.19.2) */ - standard = [iCalTimeZonePeriod groupWithTag: @"standard"]; - - /* TZOFFSETFROM = -1 * (PidLidTimeZoneStruct.lBias + PidLidTimeZoneStruct.lDaylightBias) */ - strOffsetFrom = [self _offsetStringFromOffset: -1 * (rule.lBias + rule.lDaylightBias)]; - [standard addChild: [CardElement simpleElementWithTag: @"tzoffsetfrom" - value: strOffsetFrom]]; - - /* TZOFFSETTO = -1 * (PidLidTimeZoneStruct.lBias + PidLidTimeZoneStruct.lStandardBias) */ - strOffsetTo = [self _offsetStringFromOffset: -1 * (rule.lBias + rule.lStandardBias)]; - [standard addChild: [CardElement simpleElementWithTag: @"tzoffsetto" - value: strOffsetTo]]; - - /* DTSTART & RRULE are derived from the stStandardDate and wYear properties */ - standardStart = [iCalDateTime elementWithTag: @"dtstart"]; - - initDate = rule.stStandardDate; - stStartValue = [NSCalendarDate dateFromSystemTime: initDate - andRuleYear: rule.wYear]; - - [standardStart setDateTime: stStartValue]; - [standard addChild: standardStart]; - - if (daylightDefined) - { - standardRRule = [[iCalRecurrenceRule alloc] initWithString: [self _rRuleStringFromSystemTime: initDate]]; - [standard addChild: standardRRule]; - - /* DAYLIGHT SAVING TIME ([MS-OXCICAL] 2.1.3.1.1.19.3) */ - daylight = [iCalTimeZonePeriod groupWithTag: @"daylight"]; - /* TZOFFSETFROM = -1 * (PidLidTimeZoneStruct.lBias + PidLidTimeZoneStruct.lStandardBias) */ - [daylight addChild: [CardElement simpleElementWithTag: @"tzoffsetfrom" - value: strOffsetTo]]; - /* TZOFFSETTO = -1 * (PidLidTimeZoneStruct.lBias + PidLidTimeZoneStruct.lDaylightBias) */ - [daylight addChild: [CardElement simpleElementWithTag: @"tzoffsetto" - value: strOffsetFrom]]; - - /* DTSTART & RRULE are derived from the stDaylightDate and wYear properties */ - daylightStart = [iCalDateTime elementWithTag: @"dtstart"]; - initDate = rule.stDaylightDate; - dlStartValue = [NSCalendarDate dateFromSystemTime: initDate - andRuleYear: rule.wYear]; - - [daylightStart setDateTime: dlStartValue]; - [daylight addChild: daylightStart]; - - daylightRRule = [[iCalRecurrenceRule alloc] initWithString: [self _rRuleStringFromSystemTime: initDate]]; - [daylight addChild: daylightRRule]; - [tz addChild: daylight]; - } - [tz addChild: standard]; - -end: - - talloc_free (definition); - return tz; -} - -/** - * Adjust a date in this vTimeZone to its representation in UTC - * Example: Timezone is +0001, the date is 2015-12-15 00:00:00 +0000 - * it returns 2015-12-14 23:00:00 +0000 - * @param date the date to adjust to the timezone. - * @return a new GMT date adjusted with the offset of the timezone. - */ -- (NSCalendarDate *) shiftedCalendarDateForDate: (NSCalendarDate *) date -{ - NSCalendarDate *tmpDate; - - tmpDate = [date copy]; - [tmpDate autorelease]; - - [tmpDate setTimeZone: utcTZ]; - - return [tmpDate addYear: 0 month: 0 day: 0 - hour: 0 minute: 0 - second: -[[self periodForDate: tmpDate] secondsOffsetFromGMT]]; -} - -@end diff --git a/Attic/OpenChange/plreader.m b/Attic/OpenChange/plreader.m deleted file mode 100644 index 69d0cd099..000000000 --- a/Attic/OpenChange/plreader.m +++ /dev/null @@ -1,99 +0,0 @@ -/* plreader.m - this file is part of SOGo - * - * Copyright (C) 2011-2012 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. - */ - -/* A format-agnostic property list dumper. - Usage: plreader [filename] */ - -#import -#import -#import - -#import "NSObject+PropertyList.m" - -static void -OCDumpPListData (NSData *content) -{ - //NSDictionary *d; - //NSPropertyListFormat format; - //NSString *error = nil; - //const char *formatName; - - //d = [NSPropertyListSerialization propertyListFromData: content - // mutabilityOption: NSPropertyListImmutable - // format: &format - // errorDescription: &error]; - //d = [content BSONValue]; - - // if (d) - // { - // switch (format) - // { - // case NSPropertyListOpenStepFormat: - // formatName = "OpenStep"; - // break; - // case NSPropertyListXMLFormat_v1_0: - // formatName = "XML"; - // break; - // case NSPropertyListBinaryFormat_v1_0: - // formatName = "Binary"; - // break; - // case NSPropertyListGNUstepFormat: - // formatName = "GNUstep"; - // break; - // case NSPropertyListGNUstepBinaryFormat: - // formatName = "GNUstep binary"; - // break; - // default: formatName = "unknown"; - // } - - // printf ("File format is: %s\n", formatName); - // [d displayWithIndentation: 0]; - // printf ("\n"); - // } - // else - // printf ("an error occurred: %s\n", [error UTF8String]); -} - -static void -PLReaderDumpPListFile (NSString *filename) -{ - NSData *content; - - content = [NSData dataWithContentsOfFile: filename]; - OCDumpPListData (content); -} - -int main() -{ - NSAutoreleasePool *p; - NSProcessInfo *pi; - NSArray *arguments; - - p = [NSAutoreleasePool new]; - pi = [NSProcessInfo processInfo]; - arguments = [pi arguments]; - if ([arguments count] > 1) - PLReaderDumpPListFile ([arguments objectAtIndex: 1]); - [p release]; - - return 0; -} diff --git a/Attic/OpenChange/product.plist b/Attic/OpenChange/product.plist deleted file mode 100644 index 87075ccfb..000000000 --- a/Attic/OpenChange/product.plist +++ /dev/null @@ -1,3 +0,0 @@ -{ - requires = ( MAIN, Appointments, Contacts, Mailer ); -} diff --git a/Attic/OpenChange/samba-get-config.py b/Attic/OpenChange/samba-get-config.py deleted file mode 100755 index 06311d996..000000000 --- a/Attic/OpenChange/samba-get-config.py +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/python - -import sys -import samba.param - -a = samba.param.LoadParm() -a.set('debug level', '0') -a.load_default() -print a.get(sys.argv[1]) diff --git a/Attic/SOGoNativeOutlookConfigurationGuide.asciidoc b/Attic/SOGoNativeOutlookConfigurationGuide.asciidoc deleted file mode 100644 index d9cdef9b6..000000000 --- a/Attic/SOGoNativeOutlookConfigurationGuide.asciidoc +++ /dev/null @@ -1,878 +0,0 @@ -Native Microsoft Outlook Configuration Guide -============================================ -:toc: left -:icons: font - -//// - - This file is part of the SOGo project. - - See SOGo Native Microsoft Outlook Configuration-docinfo.xml for - authors, copyright and license information. - -//// - -include::includes/global-attributes.asciidoc[] - -About this Guide ----------------- - -This guide will walk you through the installation and configuration of -the native Microsoft Outlook compatibility layer SOGo offers. - -Prior going over this guide, you should have a working SOGo -installation. Please refer to the _SOGo Installation and Configuration -Guide_ for more information on installing and configuring SOGo. - -This guide also includes instructions for configuring Microsoft Outlook -with SOGo. - -The instructions are based on version {release_version} of SOGo. - -The latest version of this guide is available -at http://www.sogo.nu/downloads/documentation.html. - -Introduction ------------- - -SOGo is a free and modern scalable groupware server. It offers shared -calendars, address books, and emails through your favourite Web browser -and by using a native client such as Mozilla Thunderbird and Lightning. - -SOGo is standard-compliant. It supports CalDAV, CardDAV, GroupDAV, iMIP -and iTIP and reuses existing IMAP, SMTP and database servers — making -the solution easy to deploy and interoperable with many applications. - -SOGo features: - -* Scalable architecture suitable for deployments from dozen to many -thousand users -* Rich Web-based interface that shares the look and feel, the features -and the data of Mozilla Thunderbird and Lightning -* Improved integration with Mozilla Thunderbird and Lightning by using -the SOGo Connector and the SOGo Integrator -* Native compatibility for Microsoft Outlook 2003, 2007, 2010, and 2013 -* Two-way synchronization support with any Microsoft ActiveSync-capable -device, and Outlook 2013 - -SOGo is developed by a community of developers located mainly in North -America and Europe. More information can be found -on http://www.sogo.nu/. - -Architecture ------------- - -The following diagram demonstrates the architecture of the native -Outlook compatibility layer of SOGo. - -image::images/openchange.png[] - -With Samba 4 and OpenChange, Microsoft Outlook clients can communicate -natively with SOGo using the Microsoft Exchange protocol, without -requiring costly and hard-to-maintain third-party MAPI connectors for -Microsoft Outlook. - -Requirements ------------- - -Organizations generally have solutions to authenticate users such as -LDAP servers or Microsoft Active Directory servers. - -The solution being used will influence how users are provisioned in -Samba 4, a key component for native Outlook compatibility in SOGo. - -LDAP Server -~~~~~~~~~~~ - -If your organization uses a LDAP server such OpenLDAP, Novell -eDirectory, Apache Directory or any other solution, you must use -Samba 4's internal directory server and synchronize the data between -both. - -Synchronization scripts are not provided and unless you have clear-text -passwords of your existing users, they will have to be changed during -your initial synchronization so that your LDAP's server passwords are -identical to the ones from Samba 4. - -Any modifications to your existing LDAP server (password change, user -addition or deletion, etc.) will have to be replicated to Samba 4's -internal directory server. - -Note that if you install Samba 4 on a server that is already running a -LDAP service, you will have to change to TCP port on which your LDAP -server listens to. Samba 4 will use the TCP port 389 and it can't be -changed. - -For example, with OpenLDAP, you can use the `-h` parameter for `slapd` -to make it listen on an other TCP port. - -Microsoft Active Directory -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If your organization uses Microsoft Active Directory, Samba 4 will need -to be joined to your Active Directory domain, as a DC. - -Samba 4 will be able to reuse all the information contained in Microsoft -Active Directory and no synchronization process needs to be put in place -as information will get replicated to Samba 4 automatically. - -For more information on joining Samba 4 to an existing Microsoft Active -Directory domain, please refer to the Samba 4 documentation available at -the following URL: - -http://wiki.samba.org/index.php/Samba4 - -More specifically, have a look at the `samba-tool domain join` command. -Note that joining Samba 4 to your Active Directory domain as a member -will currently not work. An authentication bug is present in Samba 4 -which then prevents all Outlook users to successfully authenticate -through Samba 4. This issue has been reported to the Samba team and is -being worked on. - -Other or No Solution -~~~~~~~~~~~~~~~~~~~~ - -If your organization neither uses a LDAP server or Microsoft Active -Directory, you can start using Samba 4 as your directory server. - -Samba 4's directory can be queried over LDAP just like Microsoft Active -Directory and can also serve as a domain controller for Windows-based -environments. - -For example, SOGo can very well use Samba 4's built-in directory server -to authenticate users. A SOGoUserSources entry to achieve this wold look -like this: - ----- -su - sogo -defaults write sogod SOGoUserSources '( - { - CNFieldName = displayName; - IDFieldName = cn; - UIDFieldName = sAMAccountName; - baseDN = "cn=Users,dc=example,dc=com"; - bindDN = "cn=Administrator,cn=Users,dc=example,dc=com"; - bindFields = ( - sAMAccountName - ); - bindPassword = "%1OpenChange"; - canAuthenticate = YES; - displayName = "Shared Addresses"; - hostname = "127.0.0.1"; - id = samba; - isAddressBook = YES; - port = 389; - } -)' ----- - -Please refer to the _SOGo Installation and Configuration Guide_ for more -information regarding `SOGoUserSources`. - -IMAP Server and Trust -~~~~~~~~~~~~~~~~~~~~~ - -An IMAP server supporting the ACL, UIDPLUS and QRESYNC IMAP extensions -is required, such as Cyrus IMAP version 2.4 or later, or Dovecot version -2.1 or later. If your current IMAP server does not support these -extensions, you can use Dovecot's proxying capabilities. The follow -configuration example makes Dovecot proxy all IMAP request to an -existing server: - ----- -auth_mechanisms = plain login -imapc_host = inverse.ca -imapc_port = 993 -imapc_ssl = imaps -imapc_ssl_verify = no -mail_gid = imapproxy -mail_home = /home/imapproxy/%u -mail_location = imapc:~/imapc -mail_uid = imapproxy -passdb { - args = host=inverse.ca ssl=imaps port=993 ssl_ca_dir=/etc/pki/tls/certs - default_fields = userdb_imapc_user=%u userdb_imapc_password=%w - driver = imap -} -protocols = imap -ssl = no -userdb { - driver = prefetch -} ----- - -SOGo would then be configured to use Dovecot's proxy as the IMAP server. - -Moreover, the authentication mode in use by Windows with Samba and -Exchange servers prevent the backend from knowing the real password -being used by the user. This implies that the IMAP server must accept -any passwords from the host on which Samba is running. - -To accomplish this with Cyrus IMAP Server, set `sasl_pwcheck_method` -to `alwaystrue` in `/etc/imapd.conf`. You should restrain this to -an `imapd` instance dedicated to SOGo. - -For Dovecot, use an authentication source similar to: - ----- -passdb { - driver = static - args = nopassword=y allow_nets=127.0.0.1/32 -} ----- - -You should also make sure that you restrain this only to the SOGo -processes. - -For any other IMAP server, refer to the product's documentation. If such -capability is not offered, you can alternatively define the cleartext -password for each user. Please refer to the _Adding Users_ section from -this document. - -Installation ------------- - -This section will guide you through the installation of the native -Microsoft Outlook compatibility layer SOGo offers. - -//// -Red Hat Enterprise Linux v6 x86_64 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you are using Red Hat Enterprise Linux version 6 x86_64, packages -for Samba 4, OpenChange and SOGo and the SOGo OpenChange backend are -available from SOGo's web site. Please follow the instructions from -http://www.sogo.nu/english/downloads/backend.html. - -In order to satisfy certain dependencies, you should also add the EPEL -source corresponding to your distribution and architecture. More -information on this is available here: -http://fedoraproject.org/wiki/EPEL - or more specifically, -http://fedoraproject.org/wiki/EPEL/FAQ#How_can_I_install_the_packages_from_the_EPEL_software_repository.3F. - -Once ready, install the OpenChange packages on top of an existing SOGo -installation: - ----- -yum clean all && yum makecache -yum install samba \ - openchange \ - sogo-openchange-backend \ - openchange-ocsmanager \ - openchange-rpcproxy \ - mysql-server \ - MySQL-python ----- - -Once the packages are installed, refer to the _Configuration_ chapter -from this guide. - -[NOTE] -Samba4/OpenChange are not available for now on CentOS 5 i386/x86_64, -and CentOS 7. On Debian-based systems, packages are available only on -the x86_64 platform. - -Debian 7 (Wheezy) and Ubuntu 12.04 (Precise Pangolin) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -SOGo, OpenChange and the SOGo OpenChange backend are now -available from SOGo's web site. Please follow the instructions from -http://www.sogo.nu/english/downloads/backend.html to setup your -apt sources. - -On Debian7, for some Samba 4 dependencies, you need to use the -_wheezy-backports_ repository. To do so, create -`/etc/apt/sources.list.d/backports.list` with the following -content: - - deb http://http.debian.net/debian wheezy-backports main - -Then install Samba 4 on top of an existing SOGo -installation: - ----- -apt-get update -apt-get install samba samba-dev ----- - -Once completed, install the packages related to OpenChange and the SOGo -provider: - ----- -apt-get install openchangeserver \ - sogo-openchange \ - openchangeproxy \ - python-ocsmanager \ - mysql-server \ - python-mysqldb \ - openchange-ocsmanager \ - openchange-rpcproxy \ - python-sievelib \ - python-spyne \ - python-rpclib ----- - -Once the packages are installed, refer to the _Configuration_ chapter -from this guide. - -[NOTE] -On Ubuntu 12.04, the Samba init scripts need to be modified to -disable the upstart check. For more details, refer to: -https://wiki.samba.org/index.php/Samba4/InitScript -//// - -Ubuntu 16.04 (Xenial Xerus) -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Please follow the instructions from -https://sogo.nu/download.html to setup your -apt sources. - -Then install Samba 4 on top of an existing SOGo -installation: - ----- -apt-get update -apt-get install samba samba-dev ----- - -Once completed, install the packages related to OpenChange and the SOGo -provider: - ----- -apt-get install openchangeserver \ - sogo-openchange \ - openchangeproxy \ - python-ocsmanager \ - mysql-server \ - python-mysqldb \ - openchange-ocsmanager \ - openchange-rpcproxy \ - python-sievelib \ - python-spyne \ - python-rpclib ----- - -Once the packages are installed, refer to the _Configuration_ chapter -from this guide. - -[NOTE] -The `ocsmanager.conf` and `rpcproxy.conf` are currently located in -`/etc/apache2/conf.d`. These should be moved to `/etc/apache2/conf-available`. -This is a packaging error that will soon be fixed. - -[NOTE] -You might have to adjust the `rpcproxy.conf` configuration file to add the -`Require all granted` permission if you get Apache errors such as -`client denied by server configuration`. - -Configuration -------------- - -In this section, you'll learn how to configure the native Microsoft -Outlook compatibility layer that SOGo offers. - -SOGo Configuration -~~~~~~~~~~~~~~~~~~ - -First thing to do is to configure SOGo to use your current services, -which are your IMAP, SMTP and SQL database servers. The configuration -instructions for this are available in the SOGo Installation and -Configuration Guide available from http://www.sogo.nu/. - -Please refer to that documentation before continuing with the -instructions included in this guide. - -Samba 4 Configuration -~~~~~~~~~~~~~~~~~~~~~ - -Run the following commands as root:  - ----- -samba-tool domain provision --realm=example.com \ - --domain=EXAMPLE \ - --adminpass='%1OpenChange' \ - --server-role='domain controller' - -samba-tool user setexpiry administrator --noexpiry ----- - -You might consider changing the realm and domain used, to suit your -environment. - -You might also have to -remove `/etc/samba/smb.conf` prior running this command. - -Add the following parameters to the `[global]` section of the -`/etc/samba/smb.conf` configuration file: - ----- -### Configuration required by OpenChange server ### -dsdb:schema update allowed = true -dcerpc endpoint servers = epmapper, mapiproxy, dnsserver -dcerpc_mapiproxy:server = true -dcerpc_mapiproxy:interfaces = exchange_emsmdb, exchange_nsp, exchange_ds_rfr -### Configuration required by OpenChange server ### ----- - -Your Samba 4 configuration file should look like this: - ----- -# Global parameters -[global] - server role = active directory domain controller - workgroup = EXAMPLE - realm = example.com - netbios name = sogo - passdb backend = samba4 - ### Configuration required by OpenChange server ### - dsdb:schema update allowed = true - dcerpc endpoint servers = +epmapper, +mapiproxy - dcerpc_mapiproxy:server = true - dcerpc_mapiproxy:interfaces = exchange_emsmdb, exchange_nsp, exchange_ds_rfr - ### Configuration required by OpenChange server ### - -[netlogon] - path = /var/lib/samba/sysvol/example.com/scripts - read only = No - -[sysvol] - path = /var/lib/samba/sysvol - read only = No ----- - -OpenChange Configuration -~~~~~~~~~~~~~~~~~~~~~~~~ - -Since v2.2, OpenChange stores its metadata in MySQL so you need to have it installed. - -First, create the OpenChange MySQL user: - ----- -$ mysql -u root -p -mysql> CREATE USER 'openchange-user'@'localhost' IDENTIFIED BY 'openchange$123'; -mysql> GRANT ALL PRIVILEGES ON `openchange`.* TO 'openchange-user'@'localhost' WITH GRANT OPTION; -mysql> FLUSH PRIVILEGES; ----- - -The Samba AD schema needs to be filled with additional object -definitions by running the following commands:  - ----- -openchange_provision --standalone - -NOTE: This operation can take several minutes -[+] Step 1: Register Exchange OIDs -[+] Step 2: Add Exchange attributes to Samba schema -[+] Step 3: Add Exchange auxiliary classes to Samba schema -[+] Step 4: Add Exchange objectCategory to Samba schema -[+] Step 5: Add Exchange containers to Samba schema -[+] Step 6: Add Exchange *sub* containers to Samba schema -[+] Step 7: Add Exchange CfgProtocol subcontainers to Samba schema -[+] Step 8: Add Exchange mailGateway subcontainers to Samba schema -[+] Step 9: Add Exchange classes to Samba schema -[+] Step 10: Add possSuperior attributes to Exchange classes -[+] Step 11: Extend existing Samba classes and attributes -[+] Step 12: Generic Exchange configuration objects -[+] Step 13: Finalize generic Exchange configuration objects -[SUCCESS] Done! -[+] Step 1: Exchange Samba registration -[SUCCESS] Done! -[+] Step 1: Register Exchange Samba as the main server -[SUCCESS] Done! ----- - -Create the OpenChange database:  - ----- -openchange_provision --openchangedb --openchangedb-uri 'mysql://openchange-user:openchange$123@localhost/openchange' - -Setting up openchange db -[+] Public Folders -=================== - * Public Folder Root : 0x0100000000000001 (72057594037927937) - * IPM_SUBTREE : 0x0200000000000001 (144115188075855873) - * NON_IPM_SUBTREE : 0x0300000000000001 (216172782113783809) - * EFORMS REGISTRY : 0x0400000000000001 (288230376151711745) - * OFFLINE ADDRESS BOOK : 0x0500000000000001 (360287970189639681) - * /o=First Organization/cn=addrlists/cn=oabs/cn=Default Offline Address Book: 0x0600000000000001 (432345564227567617) - * SCHEDULE+ FREE BUSY : 0x0700000000000001 (504403158265495553) - * EX:/o=first organization/ou=first administrative group: 0x0800000000000001 (576460752303423489) - * Events Root : 0x0900000000000001 (648518346341351425) ----- - -Finally, modify `/etc/samba/smb.conf` to specify OpenChange connection information -for its indexing database. Add the following at the end of the `[global]` section: - ----- -mapistore:namedproperties = mysql -namedproperties:mysql_user = openchange-user -namedproperties:mysql_pass = openchange$123 -namedproperties:mysql_host = localhost -namedproperties:mysql_db = openchange - -mapistore:indexing_backend = mysql://openchange-user:openchange$123@localhost/openchange -mapiproxy:openchangedb = mysql://openchange-user:openchange$123@localhost/openchange ----- - -//// -On RHEL, make sure SELinux is disabled: - - setenforce 0 -//// - -Next, you can start Samba using the usual command: - - /etc/init.d/samba start - -On upstart-based distributions, use: - - start samba-ad-dc - -You can also launch the OpenChange web services: - - /etc/init.d/openchange-ocsmanager start - -Apache Configuration for Web Services -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The OpenChange web services consist of two components: - -1. *OCS Manager* which is used for autodiscovery and freebusy lookups on -Outlook 2007 and 2010. This service runs in its own application server -which listens on `127.0.0.1:5000` by default. Apache needs to be -configured to forward certain requests to it to make it accessible from -the outside. -Note that this service *MUST* be accessible over*HTTPS*, otherwise Outlook -won't use it. -2. *RPC Proxy* which is used for RPC over HTTP ("Outlook Anywhere"). -This service runs as a WSGI application under apache (mod_wsgi). -While HTTPS is not required to access this service, it is strongly -recommended. - -//// -On RHEL-based distributions, the apache configuration required by these -services can be found in `/etc/httpd/conf.d/ocsmanager.conf` and -`/etc/httpd/conf.d/rpcproxy.conf`. -//// - -For Debian-based distributions, these files can be found -in `/etc/apache2/conf.d/` or `/etc/apache2/conf-available`. - -The configuration requires three Apache modules:  _mod_proxy_, -_mod_proxy_http_ and _mod_wsgi_. These are usually already installed but -might need to be activated on Debian-based installations: - - a2enmod proxy proxy_http wsgi - -The OCS Manager and RPC Proxy configuration module can be enabled using: - - a2enconf ocsmanager - a2enconf rpcproxy - -//// -On RHEL-based distributions, make sure the `LoadModule` directive is -uncommented in `/etc/httpd/conf.d/wsgi.conf`. -//// - -The _reqtimeout_ apache module is known to cause problems when using the -default configuration shipped with Debian-based systems. On such -distributions, Apache will close (HTTP/1.1 500) any HTTP request for -which the HTTP body hasn't arrived in 10 seconds. - -While this is arguably good practice with regular HTTP, it will disrupt -the RPC over HTTP protocol implemented by RPC Proxy: Outlook will -continuously disconnect and reconnect leading to suboptimal performance. - -To avoid this problem, use a much higher timeout or disable the module: - - a2dismod reqtimeout - -You should now restart the Apache service and make sure it will start on -boot. -//// -On RHEL-based distributions, do: - - chkconfig httpd on && /etc/init.d/httpd restart -//// -On Debian-based distributions, do: - - update-rc.d apache2 defaults && /etc/init.d/apache2 restart - -Finally, you must adjust the OCS Manager configuration file, which is -located in `/etc/ocsmanager/ocsmanager.ini`. You should enable LDAP-based -authentication in the `main` section and configure it accordingly. You should -also enable rpcproxy. You file should be similar to this one: - ----- -[DEFAULT] -debug = true -email_to = you@yourdomain.com -smtp_server = localhost -error_email_from = paste@localhost - -[main] -auth = ldap -mapistore_root = /var/lib/samba/private -mapistore_data = /var/lib/samba/private/mapistore -debug = yes - -[auth:file] - -[auth:ldap] -host = ldap://127.0.0.1 -port = 389 -bind_dn = cn=administrator,cn=Users,dc=example,dc=com -bind_pw = %1OpenChange -basedn = cn=Users,dc=example,dc=com - -[auth:single] -username = openchange -password = {SSHA}I6Hy5Wv0wuxyXvMBFWFQDVVN12_CLaX9 - -[server:main] -use = egg:Paste#http -host = 127.0.0.1 -port = 5000 -protocol_version = HTTP/1.1 - -[app:main] -use = egg:ocsmanager -full_stack = true -static_files = true -cache_dir = %(here)s/data -beaker.session.key = ocsmanager -beaker.session.secret = SDyKK3dKyDgW0mlpqttTMGU1f -app_instance_uuid = {ee533ebc-f266-49d1-ae10-d017ee6aa98c} -NTLMAUTHHANDLER_WORKDIR = /var/cache/ntlmauthhandler -SAMBA_HOST = 127.0.0.1 - -[rpcproxy:ldap] -host = localhost -port = 389 -basedn = CN=Users,DC=example,DC=com -set debug = true ----- - ----- -[autodiscover] - -[autodiscover:rpcproxy] -enabled = true - -[outofoffice] - -[outofoffice:file] -sieve_script_path = /var/vmail/$domain/$user/sieve-script -sieve_script_path_mkdir = false - -[outofoffice:managesieve] -secret = secret - -[loggers] -keys = root - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s] [%(threadName)s] %(message)s ----- - -Once completed, start the OCS Manager service: - - /etc/init.d/openchange-ocsmanager start - -Name Service Configuration for Web Services -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The autodiscovery service must be made accessible in order to advertise -the web services provided by OpenChange. This can be done in two ways. - -1. The first is to associate the FQDN `autodiscover.example.com.` with -the machine that hosts Samba 4 / OpenChange, by adding a `CNAME` entry -in your DNS configuration. Note that, instead or changing your DNS -server configuration, you can simply add a similar entry to the _hosts_ -file of the Windows machine from where you'll run Outlook, which is -handy for testing purposes. -2. The second option is to add a `SRV` entry to your DNS configuration -where the `_service` value would be `Autodiscover` and the `_protocol` -would be `_tcp`. - -For example: - - _autodiscover._tcp.example.com. IN SRV 0 0 443 sogo.example.com. - -Again, the autodiscovery service must be accessible over HTTPS. - -Adding Users ------------- - -Users that wish to connect natively to SOGo must be provisioned in -Samba 4 and in OpenChange - even if they already exist in your current -LDAP or Microsoft Active Directory server. - -To add a user, execute the following commands:  - ----- -# add user to samba -samba-tool domain passwordsettings set --complexity=off -samba-tool domain passwordsettings set --min-pwd-length=1 -samba-tool user add -samba-tool user setexpiry --noexpiry -# create user in openchange -openchange_newuser --create ----- - -If you don't have a trust between your IMAP server and SOGo, you must at -this point set the cleartext password of the newly created user in -`/var/lib/samba/private/mapistore/ Mail => Email Accounts. -* Select _Add a new e-mail account_ -* Choose _Microsoft Exchange Server_ -* Fill the required information. Enter the DNS name or the IP address of -your SOGo server in the _Microsoft Exchange Server_ field -* Leave the _Use Cached Exchange Mode_ checkbox enabled -* Enter your username in the _User Name_ field -* Click on _More Settings_ and ignore the warning, if any, about -Exchange being offline by clicking on Cancel -* From the Security tab, enable Always prompt for user name and password -* From the _Connection_ tab, enable _"Outlook Anywhere"_ if you plan to -use Outlook outside of your LAN. Moreover, click on the _Exchange Proxy -Settings..._ button to enable it for slow and fast networks. Specify -also the host, which should be the same value you specified in the -Microsoft Exchange Server field. -* Finally, click on Check Name and confirm your username and password - -Start Microsoft Outlook and enter your username and password. It will -start to synchronize your mailbox. This could take a long time if you -have many emails, events, tasks and contacts. Once this step is -completed, check the autodiscovery service with Outlook 2007 or 2010 by -simultaneously holding the CTRL key on your keyboard and right-clicking -on the Outlook icon in the notification toolbar. A special entry named -"Test E-mail AutoConfiguration..." will appear and will enable you to -check the service. - -Known Issues or Limitations ---------------------------- - -* Make sure you periodically backup all your data regarding SOGo. -* Make sure you have no firewalls activated between your Microsoft -Outlook clients and the SOGo server with Native Outlook Compatibility -module. If you do, use "Outlook Anywhere" to connect Outlook to -SOGo/OpenChange. - -Current Limitations -~~~~~~~~~~~~~~~~~~~ - -The current version of the Native Microsoft Outlook compatibility layer -has some limitations. - -Those limitations will be overcome in the upcoming releases. If you are -interested in having those limitations fixed more rapidly, please -contact Inverse by sending an email to support@inverse.ca. - -General -^^^^^^^ - -* When you create a new Microsoft Outlook profile, not all folders might -be synchronized during the first start. Simply select the appropriate -folder and click "Send and Receive". Synchronizing a folder may take -some time. For example, a folder with 1000 email messages might take -around 5 minutes based on the underlying hardware. -* Errors when synchronizing the "Offline Address Book" are normal and -can be ignored for now. This feature is currently not supported. -* If you face strange issues from Microsoft Outlook, you might want to -remove any data associated with the user from the SOGo server and -recreate a Microsoft Outlook profile. -To remove any data associated to a user, use -the `openchange_user_cleanup` script distributed with OpenChange. The script -can be found in `/usr/share/openchange/`. -To reset a user, run the script as root: -`openchange_user_cleanup username`. See the usage output for additional options. -* The "Out of Office Assistant" will not currently work. This feature -has not been implemented. -* Creating folders below INBOX (when not normally permitted by the IMAP -server), below the Personal Calendar or Personal Address Book will work -in Outlook cached mode but the server-side operation will fail and these -folders will never be created. Potentially data loss can occur if the -Outlook profile is destroyed. If you wan to create additional top-level -mail folders, calendars or address books, open Outlook's folder list, -select the top level node (usually, "email@example.com") and choose "New -Folder..." from the contextual menu. Choose the relevant item types. - -Mail -^^^^ - -* Sharing mail folders is not supported. -* To avoid possibly lossy conversion from RTF to HTML, Outlook should be -configured to send all mails as HTML (or plaintext) instead of _Outlook -Rich Text Format_. - -Calendar -^^^^^^^^ - -* Labels will not work. -* It might be impossible to view event details from a shared calendar. -This issue is being worked on. - -Tasks -^^^^^ - -* Tasks with start/due dates created from Outlook might not appear -correctly in SOGo due to a timezone issue. -* Reminders are not yet supported. -* Assigning tasks will not work. - -Contacts -^^^^^^^^ - -* Categories will not work. -* Distribution lists will not work. -* Under Microsoft Outlook 2010, the special folder "Suggested Contacts" -will not work. -* The "Offline Address Book" will not work. This feature is not yet -supported. - -Notes -^^^^^ - -* Notes are not synchronized in any ways with SOGo. The current version -of SOGo lacks support for notes. - -If you notice anything else, please send contact Inverse by sending an -email to support@inverse.ca. - -include::includes/additional-info.asciidoc[] - -include::includes/commercial-support.asciidoc[] diff --git a/Attic/TestRTFHandler.m b/Attic/TestRTFHandler.m deleted file mode 100644 index 1eeb3843f..000000000 --- a/Attic/TestRTFHandler.m +++ /dev/null @@ -1,317 +0,0 @@ -/* TestRTFHandler.m - * - * Copyright (C) 2014 Zentyal - * - * Author: Jesús García Sáez - * - * 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 "RTFHandler.h" -#import "SOGoTest.h" - -#import -#import - - - -@interface TestRTFHandler : SOGoTest -@end - -@implementation TestRTFHandler - - -- (NSString *) rtf2html: (NSData *) rtf -{ - NSString *html; - if (!rtf) - return nil; - - RTFHandler *handler = [[RTFHandler alloc] initWithData: rtf]; - NSMutableData *data = [handler parse]; - if (data == nil) - { - NSString *error = [NSString stringWithFormat: @"Couldn't parse RTF data:\n %s", - (char *)[rtf bytes]]; - testWithMessage(NO, error); - } - - html = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding]; - if (html == nil) - { - NSString *error = [NSString stringWithFormat: @"Couldn't convert parsed data to UTF8 string"]; - testWithMessage(NO, error); - } - return html; -} - -- (NSData *) dataWithContentsOfFixture: (NSString*) name -{ - NSString *file_path = [NSString stringWithFormat: @"Fixtures/%@", name]; - - if(![[NSFileManager defaultManager] fileExistsAtPath: file_path]) { - NSString *error = [NSString stringWithFormat: @"File %@ doesn't exist", file_path]; - testWithMessage(NO, error); - } - return [NSData dataWithContentsOfFile: file_path]; -} - -- (NSData *) dataWithContentsOfZentyalCrash: (unsigned int) number -{ - NSString *fixture = [NSString stringWithFormat: @"zentyal_crash_%u.rtf", number]; - return [self dataWithContentsOfFixture: fixture]; - -} - -- (void) checkDoesNotCrash: (unsigned int) number -{ - // FIXME fork - [self rtf2html: [self dataWithContentsOfZentyalCrash: number]]; -} - -- (void) checkHTMLConversionOfRTFFile: (NSString*) file - againstExpectedHTML: (NSString*) expected -{ - NSData *in = nil; - NSString *out = nil, *error = nil; - - in = [self dataWithContentsOfFixture: file]; - out = [self rtf2html: in]; - error = [NSString stringWithFormat: - @"Html from rtf result is not what we expected.\n>> Actual:\n%@\n>> Expected:\n%@\n", out, expected]; - testWithMessage([out isEqualToString: expected], error); -} - -- (void) checkFonTableParsingOfRTFFile: (NSString*) file - againstExpectedTable: (NSString*) expected -{ - NSData *in = nil; - char *in_bytes; - char *table_pointer; - int newCurrentPos; - RTFHandler *handler; - RTFFontTable *out_table; - NSString *out_description, *error = nil; - - in = [self dataWithContentsOfFixture: file]; - in_bytes = (char *) [in bytes]; - table_pointer = strstr(in_bytes, "{\\fonttbl"); - if (table_pointer == NULL) - { - [NSException raise: @"NSInvalidArgumentException" - format: @"No font table in RTF file"]; - } - newCurrentPos = table_pointer - in_bytes; - - handler = [[RTFHandler alloc] initWithData: in]; - - [handler mangleInternalStateWithBytesPtr: table_pointer - andCurrentPos: newCurrentPos]; - out_table = [handler parseFontTable]; - out_description = [out_table description]; - if ([out_description isEqualToString: expected]) - { - testWithMessage(YES, @"no error"); - } - else - { - error = [NSString stringWithFormat: - @"Font table is not what we expected.\n>> Actual:\n%@-----\n>> Expected:\n%@-----\n", out_description, expected]; - testWithMessage(NO, error); - } - -} - - -- (void) test_zentyal_crash_2058 -{ - [self checkDoesNotCrash: 2058]; - // Output is not correct... but the original issue was segfault -} - -- (void) test_zentyal_crash_2089 -{ - NSData *in = nil; - NSString *out = nil, *error = nil, *expected = nil; - - in = [self dataWithContentsOfZentyalCrash: 2089]; - expected =@"Lorem Ipsum
"; - out = [self rtf2html: in]; - error = [NSString stringWithFormat: - @"Html from rtf result `%@` is not what we expected", out]; - testWithMessage([out isEqualToString: expected], error); -} - -- (void) test_zentyal_crash_6330 -{ - [self checkDoesNotCrash: 6330]; -} - -- (void) test_zentyal_crash_8346 -{ - [self checkDoesNotCrash: 8346]; -} - -- (void) test_zentyal_crash_6977 -{ - [self checkDoesNotCrash: 6977]; -} - -- (void) test_zentyal_crash_7067 -{ - [self checkDoesNotCrash: 7067]; -} - - -- (void) test_mini_russian_font_table -{ - NSString *file =@"mini_russian.rtf"; - NSMutableString *expected = [NSMutableString stringWithFormat: @"Number of fonts: 84\n"]; - [expected appendString: @"0 name=Times New Roman family=roman charset=0 pitch=2\n"]; - [expected appendString: @"31500 name=Times New Roman family=roman charset=0 pitch=2\n"]; - [expected appendString: @"31501 name=Times New Roman family=roman charset=0 pitch=2\n"]; - [expected appendString: @"31502 name=Cambria family=roman charset=0 pitch=2\n"]; - [expected appendString: @"37 name=Calibri family=swiss charset=0 pitch=2\n"]; - [expected appendString: @"31503 name=Times New Roman family=roman charset=0 pitch=2\n"]; - [expected appendString: @"39 name=Times New Roman CE family=roman charset=238 pitch=2\n"]; - [expected appendString: @"31504 name=Times New Roman family=roman charset=0 pitch=2\n"]; - [expected appendString: @"40 name=Times New Roman Cyr family=roman charset=204 pitch=2\n"]; - [expected appendString: @"31505 name=Times New Roman family=roman charset=0 pitch=2\n"]; - [expected appendString: @"31506 name=Calibri family=swiss charset=0 pitch=2\n"]; - [expected appendString: @"42 name=Times New Roman Greek family=roman charset=161 pitch=2\n"]; - [expected appendString: @"31507 name=Times New Roman family=roman charset=0 pitch=2\n"]; - [expected appendString: @"31508 name=Times New Roman CE family=roman charset=238 pitch=2\n"]; - [expected appendString: @"43 name=Times New Roman Tur family=roman charset=162 pitch=2\n"]; - [expected appendString: @"31509 name=Times New Roman Cyr family=roman charset=204 pitch=2\n"]; - [expected appendString: @"44 name=Times New Roman (Hebrew) family=roman charset=177 pitch=2\n"]; - [expected appendString: @"45 name=Times New Roman (Arabic) family=roman charset=178 pitch=2\n"]; - [expected appendString: @"31511 name=Times New Roman Greek family=roman charset=161 pitch=2\n"]; - [expected appendString: @"46 name=Times New Roman Baltic family=roman charset=186 pitch=2\n"]; - [expected appendString: @"31512 name=Times New Roman Tur family=roman charset=162 pitch=2\n"]; - [expected appendString: @"47 name=Times New Roman (Vietnamese) family=roman charset=163 pitch=2\n"]; - [expected appendString: @"31513 name=Times New Roman (Hebrew) family=roman charset=177 pitch=2\n"]; - [expected appendString: @"31514 name=Times New Roman (Arabic) family=roman charset=178 pitch=2\n"]; - [expected appendString: @"31515 name=Times New Roman Baltic family=roman charset=186 pitch=2\n"]; - [expected appendString: @"31516 name=Times New Roman (Vietnamese) family=roman charset=163 pitch=2\n"]; - [expected appendString: @"31518 name=Times New Roman CE family=roman charset=238 pitch=2\n"]; - [expected appendString: @"31519 name=Times New Roman Cyr family=roman charset=204 pitch=2\n"]; - [expected appendString: @"31521 name=Times New Roman Greek family=roman charset=161 pitch=2\n"]; - [expected appendString: @"31522 name=Times New Roman Tur family=roman charset=162 pitch=2\n"]; - [expected appendString: @"31523 name=Times New Roman (Hebrew) family=roman charset=177 pitch=2\n"]; - [expected appendString: @"31524 name=Times New Roman (Arabic) family=roman charset=178 pitch=2\n"]; - [expected appendString: @"31525 name=Times New Roman Baltic family=roman charset=186 pitch=2\n"]; - [expected appendString: @"31526 name=Times New Roman (Vietnamese) family=roman charset=163 pitch=2\n"]; - [expected appendString: @"31528 name=Cambria CE family=roman charset=238 pitch=2\n"]; - [expected appendString: @"31529 name=Cambria Cyr family=roman charset=204 pitch=2\n"]; - [expected appendString: @"31531 name=Cambria Greek family=roman charset=161 pitch=2\n"]; - [expected appendString: @"31532 name=Cambria Tur family=roman charset=162 pitch=2\n"]; - [expected appendString: @"31535 name=Cambria Baltic family=roman charset=186 pitch=2\n"]; - [expected appendString: @"31536 name=Cambria (Vietnamese) family=roman charset=163 pitch=2\n"]; - [expected appendString: @"31538 name=Times New Roman CE family=roman charset=238 pitch=2\n"]; - [expected appendString: @"31539 name=Times New Roman Cyr family=roman charset=204 pitch=2\n"]; - [expected appendString: @"31541 name=Times New Roman Greek family=roman charset=161 pitch=2\n"]; - [expected appendString: @"31542 name=Times New Roman Tur family=roman charset=162 pitch=2\n"]; - [expected appendString: @"31543 name=Times New Roman (Hebrew) family=roman charset=177 pitch=2\n"]; - [expected appendString: @"31544 name=Times New Roman (Arabic) family=roman charset=178 pitch=2\n"]; - [expected appendString: @"31545 name=Times New Roman Baltic family=roman charset=186 pitch=2\n"]; - [expected appendString: @"31546 name=Times New Roman (Vietnamese) family=roman charset=163 pitch=2\n"]; - [expected appendString: @"31548 name=Times New Roman CE family=roman charset=238 pitch=2\n"]; - [expected appendString: @"31549 name=Times New Roman Cyr family=roman charset=204 pitch=2\n"]; - [expected appendString: @"31551 name=Times New Roman Greek family=roman charset=161 pitch=2\n"]; - [expected appendString: @"31552 name=Times New Roman Tur family=roman charset=162 pitch=2\n"]; - [expected appendString: @"31553 name=Times New Roman (Hebrew) family=roman charset=177 pitch=2\n"]; - [expected appendString: @"31554 name=Times New Roman (Arabic) family=roman charset=178 pitch=2\n"]; - [expected appendString: @"31555 name=Times New Roman Baltic family=roman charset=186 pitch=2\n"]; - [expected appendString: @"31556 name=Times New Roman (Vietnamese) family=roman charset=163 pitch=2\n"]; - [expected appendString: @"31558 name=Times New Roman CE family=roman charset=238 pitch=2\n"]; - [expected appendString: @"31559 name=Times New Roman Cyr family=roman charset=204 pitch=2\n"]; - [expected appendString: @"31561 name=Times New Roman Greek family=roman charset=161 pitch=2\n"]; - [expected appendString: @"31562 name=Times New Roman Tur family=roman charset=162 pitch=2\n"]; - [expected appendString: @"31563 name=Times New Roman (Hebrew) family=roman charset=177 pitch=2\n"]; - [expected appendString: @"31564 name=Times New Roman (Arabic) family=roman charset=178 pitch=2\n"]; - [expected appendString: @"31565 name=Times New Roman Baltic family=roman charset=186 pitch=2\n"]; - [expected appendString: @"31566 name=Times New Roman (Vietnamese) family=roman charset=163 pitch=2\n"]; - [expected appendString: @"31568 name=Calibri CE family=swiss charset=238 pitch=2\n"]; - [expected appendString: @"31569 name=Calibri Cyr family=swiss charset=204 pitch=2\n"]; - [expected appendString: @"31571 name=Calibri Greek family=swiss charset=161 pitch=2\n"]; - [expected appendString: @"31572 name=Calibri Tur family=swiss charset=162 pitch=2\n"]; - [expected appendString: @"31575 name=Calibri Baltic family=swiss charset=186 pitch=2\n"]; - [expected appendString: @"31576 name=Calibri (Vietnamese) family=swiss charset=163 pitch=2\n"]; - [expected appendString: @"31578 name=Times New Roman CE family=roman charset=238 pitch=2\n"]; - [expected appendString: @"31579 name=Times New Roman Cyr family=roman charset=204 pitch=2\n"]; - [expected appendString: @"31581 name=Times New Roman Greek family=roman charset=161 pitch=2\n"]; - [expected appendString: @"31582 name=Times New Roman Tur family=roman charset=162 pitch=2\n"]; - [expected appendString: @"31583 name=Times New Roman (Hebrew) family=roman charset=177 pitch=2\n"]; - [expected appendString: @"31584 name=Times New Roman (Arabic) family=roman charset=178 pitch=2\n"]; - [expected appendString: @"409 name=Calibri CE family=swiss charset=238 pitch=2\n"]; - [expected appendString: @"31585 name=Times New Roman Baltic family=roman charset=186 pitch=2\n"]; - [expected appendString: @"410 name=Calibri Cyr family=swiss charset=204 pitch=2\n"]; - [expected appendString: @"31586 name=Times New Roman (Vietnamese) family=roman charset=163 pitch=2\n"]; - [expected appendString: @"412 name=Calibri Greek family=swiss charset=161 pitch=2\n"]; - [expected appendString: @"413 name=Calibri Tur family=swiss charset=162 pitch=2\n"]; - [expected appendString: @"416 name=Calibri Baltic family=swiss charset=186 pitch=2\n"]; - [expected appendString: @"417 name=Calibri (Vietnamese) family=swiss charset=163 pitch=2\n"]; - - [self checkFonTableParsingOfRTFFile: file - againstExpectedTable: expected]; -} - -- (void) test_mini_russian -{ - NSString *file =@"mini_russian.rtf"; - NSString *expected=@"XXзык польски, польщизнаXX"; - [self checkHTMLConversionOfRTFFile: file - againstExpectedHTML: expected]; -} - -- (void) test_escapes -{ - NSString *file =@"escapes.rtf"; - NSString *expected=@"x341x351x372x355x363x361xS SS-S\\SU老UřU
"; - [self checkHTMLConversionOfRTFFile: file - againstExpectedHTML: expected]; -} - -- (void) test_spanish_accents -{ - NSString *file =@"spanish_accents.rtf"; - NSString *expected=@"xñxáxéxíxóxú
"; - - [self checkHTMLConversionOfRTFFile: file - againstExpectedHTML: expected]; -} - -- (void) test_cyr_event_ru_editor -{ - NSString *file =@"cyr_event_ru_editor.rtf"; - NSString *expected=@"йчсмй
"; - - [self checkHTMLConversionOfRTFFile: file - againstExpectedHTML: expected]; -} - -- (void) test_bad_hex_and_cr -{ - NSString *file =@"bad_hex_and_cr.rtf"; - NSString *expected=@"Good hex:H Bad1Hex: Bad2Hex: Ignored Carriadge Return"; - - [self checkHTMLConversionOfRTFFile: file - againstExpectedHTML: expected]; -} - -@end