├── .gitignore ├── COPYING ├── ChangeLog.old ├── Makefile ├── README.md ├── RELEASE-NOTES ├── TODO ├── _locales ├── cs-CZ │ └── messages.json ├── de-DE │ └── messages.json ├── en-US │ └── messages.json ├── fr-FR │ └── messages.json ├── hu-HU │ └── messages.json ├── it-IT │ └── messages.json ├── nl-NL │ └── messages.json └── pt-BR │ └── messages.json ├── api └── WindowListener │ ├── implementation.js │ └── schema.json ├── background.js ├── chrome ├── components │ ├── CalDAVACLManager.js │ └── ContextManager.jsm ├── content │ ├── inverse-library │ │ ├── calendar-cache.js │ │ ├── quoted-printable.js │ │ ├── sogoWebDAV.js │ │ ├── test-sogowebdav.xul │ │ ├── tests-dialog.js │ │ ├── tests-dialog.xul │ │ └── uuid.js │ └── sogo-connector │ │ ├── addressbook │ │ ├── abEditCardDialog.groupdav.overlay.js │ │ ├── abNewCardDialog.groupdav.overlay.js │ │ ├── addressbook.groupdav.overlay.js │ │ ├── autocomplete-common.js │ │ ├── categories.js │ │ ├── common-card-overlay.js │ │ ├── common-card-overlay.xul │ │ ├── creation-dialog.xhtml │ │ ├── deletefailure-dialog.xhtml │ │ ├── edit-list-overlay.js │ │ ├── edit-list-overlay.xul │ │ ├── folder-handler.js │ │ ├── folder-handling.js │ │ ├── messagewindow-overlay.js │ │ ├── messagewindow-overlay.xul │ │ ├── newlist-overlay.js │ │ ├── newlist-overlay.xul │ │ ├── preferences.addressbook.groupdav.js │ │ ├── preferences.addressbook.groupdav.xhtml │ │ ├── roles-dialog.js │ │ └── roles-dialog.xhtml │ │ ├── calendar │ │ ├── calendar-event-dialog.js │ │ ├── calendar-invitations-dialog.js │ │ ├── calendar-invitations-dialog.xul │ │ ├── calendar-overlay.js │ │ ├── creation-dialog.xhtml │ │ ├── default-classifications.js │ │ ├── folder-handler.js │ │ ├── properties-overlay.js │ │ ├── roles-dialog.js │ │ ├── roles-dialog.xhtml │ │ └── utils.js │ │ ├── general │ │ ├── acl-dialog.js │ │ ├── acl-dialog.xhtml │ │ ├── creation-overlay.js │ │ ├── creation-utils.js │ │ ├── custom-preferences.js │ │ ├── mozilla.utils.inverse.ca.js │ │ ├── preference.service.addressbook.groupdav.js │ │ ├── subscription-dialog.js │ │ ├── subscription-dialog.xhtml │ │ ├── subscription-utils.js │ │ ├── sync.addressbook.groupdav.js │ │ └── vcards.utils.js │ │ ├── global │ │ ├── common-dialog-overlay.js │ │ ├── common-dialog-overlay.xul │ │ ├── extensions.rdf │ │ ├── i18n.js │ │ ├── newtag-overlay.js │ │ └── sogo-config.js │ │ ├── messenger │ │ ├── folders-update.js │ │ ├── mails-labels.js │ │ ├── startup-overlay.js │ │ ├── update-dialog.js │ │ └── update-dialog.xul │ │ ├── messengercompose │ │ └── messengercompose-overlay.xul │ │ └── preferences │ │ ├── edit-category.js │ │ └── edit-category.xhtml └── skin │ ├── abcard-anonymous.png │ ├── abcard-anyone.png │ ├── abcard.png │ ├── acl-dialog.css │ ├── add-contact.gif │ ├── addressbook-folder.png │ ├── addressbook │ ├── add-addressbook.png │ ├── add-user-addressbook.png │ ├── addressbook.groupdav.overlay.css │ ├── deletefailure-dialog.css │ ├── groupdav.png │ ├── remove-addressbook-disabled.png │ ├── remove-addressbook.png │ ├── search-filter.png │ ├── sogo.png │ ├── sync-16-disabled.png │ ├── sync-16.png │ ├── sync-24-disabled.png │ ├── sync-24.png │ ├── sync-32-disabled.png │ ├── sync-32.png │ └── sync-36.png │ ├── calendar-folder.png │ ├── calendar │ ├── accept-flat.png │ ├── accept-high.png │ ├── accept-off.png │ ├── add-calendar.png │ ├── add-user-calendar.png │ ├── calendar-overlay.css │ ├── decline-flat.png │ ├── decline-high.png │ ├── decline-off.png │ └── remove-calendar.png │ ├── close-window.png │ ├── creation-dialog.css │ ├── preferences │ ├── preferences.css │ ├── sogo-48.png │ └── sogo-mac.png │ ├── properties-overlay.css │ ├── remove-contact.gif │ ├── roles-dialog.css │ ├── sogo.png │ ├── subscription-dialog.css │ └── update-dialog.css ├── custom └── sogo-demo │ └── chrome │ └── content │ └── sogo-connector │ └── general │ └── custom-preferences.js └── manifest.json /.gitignore: -------------------------------------------------------------------------------- 1 | MANIFEST 2 | sogo-connector-*.xpi 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PACKAGE = sogo-connector 2 | GIT_REV = $(shell git rev-parse --verify HEAD | cut -c1-10) 3 | VERSION := $(shell awk '/ "version":/ {print $$2}' manifest.json | sed -e 's@[\",]@@g') 4 | FIND_FILTER = ! -path './custom/*' -type f 5 | XPI_ARCHIVE = $(PACKAGE)-$(VERSION)-$(GIT_REV).xpi 6 | 7 | SHELL=bash 8 | ZIP=zip 9 | 10 | FILENAMES = $(shell cat MANIFEST) 11 | 12 | all: MANIFEST-pre MANIFEST rest 13 | 14 | custom-build: 15 | @if test "x$$build" == "x"; then \ 16 | echo "Building package with default settings."; \ 17 | else \ 18 | echo "Building package with custom settings for '$$build'."; \ 19 | if ! test -d custom/$$build; then \ 20 | echo "Custom build '$$build' does not exist"; \ 21 | exit 1; \ 22 | fi; fi 23 | 24 | MANIFEST: MANIFEST-pre 25 | @if ! cmp MANIFEST MANIFEST-pre >& /dev/null; then \ 26 | mv -f MANIFEST-pre MANIFEST; \ 27 | echo MANIFEST updated; \ 28 | else \ 29 | rm -f MANIFEST-pre; \ 30 | fi; 31 | 32 | MANIFEST-pre: 33 | @echo manifest.json > $@ 34 | @echo ./api/WindowListener/schema.json >> $@ 35 | @echo COPYING >> $@ 36 | @echo ChangeLog.old >> $@ 37 | @find . $(FIND_FILTER) -name "*.manifest" >> $@ 38 | @find . $(FIND_FILTER) -name "*.xhtml" >> $@ 39 | @find . $(FIND_FILTER) -name "*.xml" >> $@ 40 | @find . $(FIND_FILTER) -name "*.dtd" >> $@ 41 | @find . $(FIND_FILTER) -name "*.idl" >> $@ 42 | @find . $(FIND_FILTER) -name "*.js" >> $@ 43 | @find . $(FIND_FILTER) -name "*.jsm" >> $@ 44 | @find . $(FIND_FILTER) -name "*.css" >> $@ 45 | @find . $(FIND_FILTER) -name "*.png" >> $@ 46 | @find . $(FIND_FILTER) -name "*.gif" >> $@ 47 | @find . $(FIND_FILTER) -name "*.jpg" >> $@ 48 | @find . $(FIND_FILTER) -name "*.xpt" >> $@ 49 | @find . $(FIND_FILTER) -name "*.properties" >> $@ 50 | @find . $(FIND_FILTER) -name "*.rdf" >> $@ 51 | @find . $(FIND_FILTER) -name "RELEASE-NOTES" >> $@ 52 | @echo _locales/cs-CZ/messages.json >> $@ 53 | @echo _locales/de-DE/messages.json >> $@ 54 | @echo _locales/en-US/messages.json >> $@ 55 | @echo _locales/fr-FR/messages.json >> $@ 56 | @echo _locales/hu-HU/messages.json >> $@ 57 | @echo _locales/it-IT/messages.json >> $@ 58 | @echo _locales/nl-NL/messages.json >> $@ 59 | @echo _locales/pt-BR/messages.json >> $@ 60 | 61 | rest: MANIFEST 62 | @+make $(XPI_ARCHIVE) 63 | 64 | $(XPI_ARCHIVE): $(FILENAMES) 65 | @echo Generating $(XPI_ARCHIVE)... 66 | @rm -f $(XPI_ARCHIVE) 67 | @$(ZIP) -9r $(XPI_ARCHIVE) $(FILENAMES) > /dev/null 68 | @if test "x$$build" != "x"; then \ 69 | cd custom/$$build; \ 70 | $(ZIP) -9r ../../$(XPI_ARCHIVE) * > /dev/null; \ 71 | fi 72 | 73 | clean: 74 | rm -f MANIFEST-pre $(XPI_ARCHIVE) 75 | rm -f *.xpi 76 | find . -name "*~" -exec rm -f {} \; 77 | 78 | distclean: clean 79 | rm -f MANIFEST 80 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # To package the extension 2 | 3 | First create a directory structure in custom/ that corresponds to your site 4 | name. Use "sogo-demo" as an example. You can do so by doing: 5 | 6 | ``` 7 | % cp -a custom/sogo-demo custom/mysite 8 | ``` 9 | 10 | Then customize the following file: 11 | 12 | * custom/mysite//chrome/content/sogo-connector/general/custom-preferences.js 13 | 14 | You must at least customize the sogo-connector.baseURL value. If you 15 | want to force-push preferences prefix your option with force_. 16 | 17 | To build the extension, do: 18 | 19 | ``` 20 | % make distclean 21 | % make build=mysite 22 | ``` 23 | 24 | # Logging 25 | 26 | ## For development enable debug messages 27 | 28 | Taken from: http://brainflush.wordpress.com/2008/01/17/mozilla-thunderbird-extension-development-environment-setup/ 29 | 30 | javascript.options.showInConsole = true. 31 | Logs errors in chrome files to the Error Console. 32 | 33 | browser.dom.window.dump.enabled = true. 34 | Enables the use of the dump() statement to print to the standard console. See window.dump for more info. You can also use nsIConsoleService from privileged script. 35 | 36 | javascript.options.strict = true. 37 | Enables strict JavaScript warnings in the Error Console. Note that since many people have this setting turned off when developing, you will see lots of warnings for problems with their code in addition to warnings for your own extension. You can filter those with Console2. 38 | 39 | You can do so automatically by setting these preferences in custom-preferences.js: 40 | 41 | ```javascript 42 | pref("javascript.options.showInConsole", true); 43 | pref("browser.dom.window.dump.enabled", true); 44 | pref("javascript.options.strict", true); 45 | ``` 46 | 47 | ## Making the standard output console visible 48 | 49 | Taken from: https://developer.mozilla.org/en-US/docs/DOM/window.dump?redirectlocale=en-US&redirectslug=DOM%3Awindow.dump 50 | 51 | On Windows, you will need a console to actually see anything. If you don't have one already, closing the application and re-opening it with the command line parameter -console should create the console. On other operating systems, it's enough to launch the application from a terminal. 52 | 53 | # Migrating to Thunderbird v68 from previous versions 54 | 55 | First of all, SOGo Integrator is no longer needed. All SOGo Integrator preferences have been renamed to 56 | "sogo-connector". For example: 57 | 58 | ``` 59 | sogo-integrator.disable-calendaring 60 | ``` 61 | 62 | was renamed to: 63 | 64 | ``` 65 | sogo-connector.disable-calendaring 66 | ``` 67 | 68 | Here is the list of renamed preference keys: 69 | 70 | ``` 71 | sogo-integrator.autocomplete.server.urlid 72 | sogo-integrator.disable-calendaring 73 | sogo-integrator.disable-send-invitations-checkbox 74 | ``` 75 | 76 | All SOGo Connector preferences: 77 | 78 | ``` 79 | sogo-connector.autoComplete.commentAttribute 80 | sogo-connector.autoComplete.delay 81 | sogo-connector.contacts.categories 82 | sogo-connector.identification.use_email_address 83 | sogo-connector.sogo-prefix 84 | ``` 85 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | - remove XUL files that are no longer used 2 | - fix sync toolbar icon not showing 3 | - handle X-MOZ-SEND-INVITATIONS-UNDISCLOSED and X-MOZ-SEND-INVITATIONS in SOGo directly 4 | - bring back reloadCalendarCache? 5 | - remove GroupDavSynchronizer 6 | - remove sync.addressbook.groupdav.js 7 | - when accepting IMIP/ITIP invitations, overlay Lightning to show only writable calendars 8 | - document startup.js 9 | -------------------------------------------------------------------------------- /_locales/nl-NL/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "General.tab": { 3 | "message": "Algemeen" 4 | }, 5 | "GroupDavConf.accesskey": { 6 | "message": "C" 7 | }, 8 | "GroupDavConf.label": { 9 | "message": "Configureren" 10 | }, 11 | "GroupDavSync.accesskey": { 12 | "message": "S" 13 | }, 14 | "GroupDavSync.label": { 15 | "message": "Synchroniseren" 16 | }, 17 | "GroupDavSync.tooltip": { 18 | "message": "Synchroniseer de adresboekingangen met de server" 19 | }, 20 | "GroupDavSyncAbort.accesskey": { 21 | "message": "A" 22 | }, 23 | "GroupDavSyncAbort.label": { 24 | "message": "Abort Synchronization" 25 | }, 26 | "GroupDavSyncAbort.tooltip": { 27 | "message": "Abort ongoing Synchronization (try if nothing happens)" 28 | }, 29 | "Offline.tab": { 30 | "message": "Offline" 31 | }, 32 | "ReadOnly.accesskey": { 33 | "message": "A" 34 | }, 35 | "ReadOnly.label": { 36 | "message": "Alleen-lezen" 37 | }, 38 | "SearchCategory.label": { 39 | "message": "Category" 40 | }, 41 | "SearchCriteriaButton.label": { 42 | "message": "Criteria" 43 | }, 44 | "URLAlreadyExist": { 45 | "message": "Er bestaat al een adresboek met die URL!" 46 | }, 47 | "attendee.toolbar.accept.label": { 48 | "message": "Accepteren" 49 | }, 50 | "attendee.toolbar.close.label": { 51 | "message": "Sluiten" 52 | }, 53 | "attendee.toolbar.decline.label": { 54 | "message": "Afwijzen" 55 | }, 56 | "calendar.preferences.general.classification.caption": { 57 | "message": "Default item classifications" 58 | }, 59 | "calendar.preferences.general.default-events-classification.label": { 60 | "message": "Events classification:" 61 | }, 62 | "calendar.preferences.general.default-todos-classification.label": { 63 | "message": "Tasks classification:" 64 | }, 65 | "contacts.categories": { 66 | "message": "Colleague,Competitor,Customer,Friend,Family,Business Partner,Provider,Press,VIP" 67 | }, 68 | "deletefailure.description": { 69 | "message": "Een of meer elementen van dit adresboek konden niet worden verwijderd. Mogelijk heeft u niet de juiste rechten." 70 | }, 71 | "deletefailure.title": { 72 | "message": "Fout bij verwijderen van elementen" 73 | }, 74 | "downloadNowButton.accesskey": { 75 | "message": "d" 76 | }, 77 | "downloadNowButton.label": { 78 | "message": "Nu downloaden" 79 | }, 80 | "event.confidential.label": { 81 | "message": "Vertrouwelijke gebeurtenis" 82 | }, 83 | "event.menu.options.privacy.confidential.label": { 84 | "message": "Vertrouwelijke gebeurtenis" 85 | }, 86 | "event.organizers.label": { 87 | "message": "Organisator:" 88 | }, 89 | "groupDavServerType.accesskey": { 90 | "message": "S" 91 | }, 92 | "groupDavServerType.label": { 93 | "message": "Soort server:" 94 | }, 95 | "groupdavHostname.accesskey": { 96 | "message": "s" 97 | }, 98 | "groupdavHostname.label": { 99 | "message": "servernaam: " 100 | }, 101 | "groupdavName.accesskey": { 102 | "message": "n" 103 | }, 104 | "groupdavName.label": { 105 | "message": "Naam: " 106 | }, 107 | "groupdavNotifications.label": { 108 | "message": "Show Notifications" 109 | }, 110 | "groupdavNotificationsManual.info": { 111 | "message": "When select 'Synchronize' from toolbar or context menu." 112 | }, 113 | "groupdavNotificationsManual.label": { 114 | "message": "Show Notifications for manual synchronizations" 115 | }, 116 | "groupdavNotificationsOINE.label": { 117 | "message": "Notify only if data synchronized" 118 | }, 119 | "groupdavNotificationsRestart.label": { 120 | "message": "Changes in options for 'Periodic sync' need a restart of Thunderbird." 121 | }, 122 | "groupdavNotificationsSave.info": { 123 | "message": "The default notification is a progress bar in the status bar. If checked, a general notification will be displayed." 124 | }, 125 | "groupdavNotificationsSave.label": { 126 | "message": "Show Notifications when saving a card" 127 | }, 128 | "groupdavNotificationsStart.label": { 129 | "message": "Show Notifications on startup" 130 | }, 131 | "groupdavPassword.accesskey": { 132 | "message": "w" 133 | }, 134 | "groupdavPassword.label": { 135 | "message": "wachtwoord:" 136 | }, 137 | "groupdavPeriodicSync.label": { 138 | "message": "Periodic sync" 139 | }, 140 | "groupdavPeriodicSync15m.label": { 141 | "message": "15 min" 142 | }, 143 | "groupdavPeriodicSync1h.label": { 144 | "message": "1 h" 145 | }, 146 | "groupdavPeriodicSync2h.label": { 147 | "message": "2 h" 148 | }, 149 | "groupdavPeriodicSync5m.label": { 150 | "message": "5 min" 151 | }, 152 | "groupdavSecure.accesskey": { 153 | "message": "b" 154 | }, 155 | "groupdavSecure.label": { 156 | "message": "Gebruik beveiligde verbinding (SSL)" 157 | }, 158 | "groupdavURL.accesskey": { 159 | "message": "L" 160 | }, 161 | "groupdavURL.label": { 162 | "message": "URL: " 163 | }, 164 | "groupdavUser.accesskey": { 165 | "message": "g" 166 | }, 167 | "groupdavUser.label": { 168 | "message": "gebruiker:" 169 | }, 170 | "inverse.CalDAV.tab": { 171 | "message": "CalDAV" 172 | }, 173 | "inverse.FbUrl.label": { 174 | "message": "Beschikbaarheids (Free/Busy) URL:" 175 | }, 176 | "missingDescriptionMsg": { 177 | "message": "Kan geen adresboek zonder naam aanmaken!" 178 | }, 179 | "missingDescriptionURL": { 180 | "message": "Kan geen adresboek zonder URL aanmaken!" 181 | }, 182 | "newDirectoryTitle.label": { 183 | "message": "Eigenschappen van adresboek op server" 184 | }, 185 | "newDirectoryWidth": { 186 | "message": "36em" 187 | }, 188 | "newGroupDavCmd.accesskey": { 189 | "message": "A" 190 | }, 191 | "newGroupDavCmd.label": { 192 | "message": "Adresboek op server" 193 | }, 194 | "notificationsDelete": { 195 | "message": "\\u0020delete." 196 | }, 197 | "notificationsDeletes": { 198 | "message": "\\u0020deletes." 199 | }, 200 | "notificationsDownload": { 201 | "message": "\\u0020download,\\u0020" 202 | }, 203 | "notificationsDownloads": { 204 | "message": "\\u0020downloads,\\u0020" 205 | }, 206 | "notificationsFailure": { 207 | "message": "\\u0020failure,\\u0020" 208 | }, 209 | "notificationsFailures": { 210 | "message": "\\u0020failures,\\u0020" 211 | }, 212 | "notificationsNoChanges": { 213 | "message": "No changes." 214 | }, 215 | "notificationsTitle": { 216 | "message": "SOGO :\\u0020" 217 | }, 218 | "notificationsUpload": { 219 | "message": "\\u0020upload,\\u0020" 220 | }, 221 | "notificationsUploads": { 222 | "message": "\\u0020uploads,\\u0020" 223 | }, 224 | "offlineText.label": { 225 | "message": "Er kan een kopie van dit adresboek worden gedownload wanneer u offline werkt." 226 | }, 227 | "sogo-connector.preferences.contacts.categories.add.title": { 228 | "message": "Add Category" 229 | }, 230 | "sogo-connector.preferences.contacts.categories.addButton.accesskey": { 231 | "message": "A" 232 | }, 233 | "sogo-connector.preferences.contacts.categories.addButton.label": { 234 | "message": "Add..." 235 | }, 236 | "sogo-connector.preferences.contacts.categories.edit.title": { 237 | "message": "Edit Category" 238 | }, 239 | "sogo-connector.preferences.contacts.categories.editButton.accesskey": { 240 | "message": "E" 241 | }, 242 | "sogo-connector.preferences.contacts.categories.editButton.label": { 243 | "message": "Edit..." 244 | }, 245 | "sogo-connector.preferences.contacts.categories.noBlankCategories": { 246 | "message": "You must enter a category name." 247 | }, 248 | "sogo-connector.preferences.contacts.categories.none.label": { 249 | "message": "None" 250 | }, 251 | "sogo-connector.preferences.contacts.categories.overwrite": { 252 | "message": "A category already exists with that name. \\n Do you want to overwrite it?" 253 | }, 254 | "sogo-connector.preferences.contacts.categories.overwrite.title": { 255 | "message": "Warning: Duplicate name" 256 | }, 257 | "sogo-connector.preferences.contacts.categories.removeButton.accesskey": { 258 | "message": "R" 259 | }, 260 | "sogo-connector.preferences.contacts.categories.removeButton.label": { 261 | "message": "Remove" 262 | }, 263 | "sogo-connector.preferences.panes.contacts.categories.title": { 264 | "message": "Contact Categories" 265 | }, 266 | "sogo-connector.tabs.categories.label": { 267 | "message": "Categories" 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /api/WindowListener/schema.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "WindowListener", 4 | "functions": [ 5 | { 6 | "name": "registerDefaultPrefs", 7 | "type": "function", 8 | "parameters": [ 9 | { 10 | "name": "aPath", 11 | "type": "string", 12 | "description": "Relative path to the default file." 13 | } 14 | ] 15 | }, 16 | { 17 | "name": "registerOptionsPage", 18 | "type": "function", 19 | "parameters": [ 20 | { 21 | "name": "aPath", 22 | "type": "string", 23 | "description": "Path to the options page, which should be made accessible in the (legacy) Add-On Options menu." 24 | } 25 | ] 26 | }, 27 | { 28 | "name": "registerChromeUrl", 29 | "type": "function", 30 | "description": "Register folders which should be available as chrome:// urls (as defined in the legacy chrome.manifest)", 31 | "parameters": [ 32 | { 33 | "name": "data", 34 | "type": "array", 35 | "items": { 36 | "type": "array", 37 | "items" : { 38 | "type": "string" 39 | } 40 | }, 41 | "description": "Array of manifest url definitions (content, locale, resource)" 42 | } 43 | ] 44 | }, 45 | { 46 | "name": "waitForMasterPassword", 47 | "type": "function", 48 | "async": true, 49 | "parameters": [] 50 | }, 51 | { 52 | "name": "openOptionsDialog", 53 | "type": "function", 54 | "parameters": [ 55 | { 56 | "name": "windowId", 57 | "type": "integer", 58 | "description": "Id of the window the dialog should be opened from." 59 | } 60 | ] 61 | }, 62 | { 63 | "name": "startListening", 64 | "type": "function", 65 | "async": true, 66 | "parameters": [] 67 | }, 68 | { 69 | "name": "registerWindow", 70 | "type": "function", 71 | "parameters": [ 72 | { 73 | "name": "windowHref", 74 | "type": "string", 75 | "description": "Url of the window, which should be listen for." 76 | }, 77 | { 78 | "name": "jsFile", 79 | "type": "string", 80 | "description": "Path to the JavaScript file, which should be loaded into the window." 81 | } 82 | ] 83 | }, 84 | { 85 | "name": "registerStartupScript", 86 | "type": "function", 87 | "parameters": [ 88 | { 89 | "name": "aPath", 90 | "type": "string", 91 | "description": "Path to a JavaScript file, which should be executed on add-on startup. The script will be executed after the main application window has been sucessfully loaded." 92 | } 93 | ] 94 | }, 95 | { 96 | "name": "registerShutdownScript", 97 | "type": "function", 98 | "parameters": [ 99 | { 100 | "name": "aPath", 101 | "type": "string", 102 | "description": "Path to a JavaScript file, which should be executed on add-on shutdown." 103 | } 104 | ] 105 | } 106 | ] 107 | } 108 | ] 109 | -------------------------------------------------------------------------------- /background.js: -------------------------------------------------------------------------------- 1 | /* background.js - This file is part of "SOGo Connector", a Thunderbird extension. 2 | * 3 | * Copyright: Inverse inc., 2006-2020 4 | * Email: support@inverse.ca 5 | * URL: http://inverse.ca 6 | * 7 | * "SOGo Connector" is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU General Public License version 2 as published by 9 | * the Free Software Foundation; 10 | * 11 | * "SOGo Connector" is distributed in the hope that it will be useful, but 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 14 | * details. 15 | * 16 | * You should have received a copy of the GNU General Public License along with 17 | * "SOGo Connector"; if not, write to the Free Software Foundation, Inc., 51 18 | * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | (async () => { 22 | 23 | messenger.WindowListener.registerChromeUrl([ 24 | ["content", "sogo-connector", "chrome/content/sogo-connector/"], 25 | ["content", "inverse-library", "chrome/content/inverse-library/"], 26 | ["resource", "sogo-connector", "chrome/"] 27 | ]); 28 | 29 | messenger.WindowListener.registerStartupScript("chrome://sogo-connector/content/messenger/startup-overlay.js"); 30 | 31 | // rework unload? 32 | messenger.WindowListener.registerWindow("chrome://messenger/content/messenger.xhtml", 33 | "chrome://sogo-connector/content/calendar/calendar-overlay.js"); 34 | 35 | // TODO: not working remove xul 36 | messenger.WindowListener.registerWindow("chrome://messenger/content/messageWindow.xhtml", 37 | "chrome://sogo-connector/content/addressbook/messagewindow-overlay.js"); 38 | 39 | messenger.WindowListener.registerWindow("chrome://messenger/content/addressbook/addressbook.xhtml", 40 | "chrome://sogo-connector/content/addressbook/addressbook.groupdav.overlay.js"); 41 | 42 | messenger.WindowListener.registerWindow("chrome://messenger/content/addressbook/abNewCardDialog.xhtml", 43 | "chrome://sogo-connector/content/addressbook/abNewCardDialog.groupdav.overlay.js"); 44 | messenger.WindowListener.registerWindow("chrome://messenger/content/addressbook/abEditCardDialog.xhtml", 45 | "chrome://sogo-connector/content/addressbook/abEditCardDialog.groupdav.overlay.js"); 46 | 47 | messenger.WindowListener.registerWindow("chrome://messenger/content/addressbook/abMailListDialog.xhtml", 48 | "chrome://sogo-connector/content/addressbook/edit-list-overlay.js"); 49 | messenger.WindowListener.registerWindow("chrome://messenger/content/addressbook/abEditListDialog.xhtml", 50 | "chrome://sogo-connector/content/addressbook/edit-list-overlay.js"); 51 | 52 | // TODO: must create JS file. use for autocomplete 53 | // we might just drop that entirely 54 | //messenger.WindowListener.registerWindow("chrome://messenger/content/messengercompose/messengercompose.xhtml", 55 | // "chrome://sogo-connector/content/messengercompose/messengercompose-overlay.js"); 56 | 57 | messenger.WindowListener.registerWindow("chrome://calendar/content/calendar-invitations-dialog.xhtml", 58 | "chrome://sogo-connector/content/calendar/calendar-invitations-dialog.js"); 59 | 60 | // need to test if the unload function is called 61 | messenger.WindowListener.registerWindow("chrome://global/content/commonDialog.xhtml", 62 | "chrome://sogo-connector/content/global/common-dialog-overlay.js"); 63 | 64 | messenger.WindowListener.registerWindow("chrome://messenger/content/newTagDialog.xhtml", 65 | "chrome://sogo-connector/content/global/newtag-overlay.js"); 66 | 67 | // kPersonalAddressbookURI is undefined and makes use of RDF 68 | messenger.WindowListener.registerWindow("chrome://messenger/content/addressbook/abMailListDialog.xhtml", 69 | "chrome://sogo-connector/content/addressbook/newlist-overlay.js"); 70 | 71 | messenger.WindowListener.registerWindow("chrome://calendar/content/calendar-properties-dialog.xhtml", 72 | "chrome://sogo-connector/content/calendar/properties-overlay.js"); 73 | 74 | messenger.WindowListener.registerWindow("chrome://calendar/content/calendar-event-dialog.xhtml", 75 | "chrome://sogo-connector/content/calendar/calendar-event-dialog.js"); 76 | 77 | messenger.WindowListener.startListening(); 78 | })(); 79 | -------------------------------------------------------------------------------- /chrome/components/ContextManager.jsm: -------------------------------------------------------------------------------- 1 | /* ContextManager.jsm - This file is part of "SOGo Connector", a Thunderbird extension. 2 | * 3 | * Copyright: Inverse inc., 2006-2019 4 | * Email: support@inverse.ca 5 | * URL: http://inverse.ca 6 | * 7 | * "SOGo Connector" is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU General Public License version 2 as published by 9 | * the Free Software Foundation; 10 | * 11 | * "SOGo Connector" is distributed in the hope that it will be useful, but 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 14 | * details. 15 | * 16 | * You should have received a copy of the GNU General Public License along with 17 | * "SOGo Connector"; if not, write to the Free Software Foundation, Inc., 51 18 | * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | var EXPORTED_SYMBOLS = ["contextManagerInstance"]; 22 | 23 | var { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); 24 | var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); 25 | 26 | function ContextManager() { 27 | this.contexts = {}; 28 | //this.wrappedJSObject = this; 29 | } 30 | 31 | ContextManager.prototype = { 32 | /* nsIClassInfo */ 33 | classID: Components.ID("{dc93fc98-bec6-11dc-b37a-00163e47dbb4}"), 34 | contractID: "@inverse.ca/context-manager;1", 35 | classDescription: "Global context manager", 36 | 37 | /*getInterfaces: function cDACLM_getInterfaces(count) { 38 | dump("ContextManager getInterfaces()\n"); 39 | const ifaces = [Components.interfaces.inverseIJSContextManager, 40 | Components.interfaces.nsIClassInfo, 41 | Components.interfaces.nsISupports]; 42 | count.value = ifaces.length; 43 | return ifaces; 44 | },*/ 45 | getHelperForLanguage: function cDACLM_getHelperForLanguage(language) { 46 | return null; 47 | }, 48 | //implementationLanguage: Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT, 49 | flags: 0, 50 | 51 | /* inverseIJSContextManager */ 52 | contexts: null, 53 | //wrappedJSObject: null, 54 | 55 | getContext: function(name) { 56 | dump("ContextManager getContext()\n"); 57 | 58 | let context = this.contexts[name]; 59 | if (!context) { 60 | context = {}; 61 | this.contexts[name] = context; 62 | } 63 | 64 | return context; 65 | }, 66 | resetContext: function(name) { 67 | dump("ContextManager resetContext()\n"); 68 | 69 | let context = this.contexts[name]; 70 | if (context) 71 | this.contexts[name] = null; 72 | } 73 | /*QueryInterface: function(aIID) { 74 | dump("ContextManager QueryInterface()\n"); 75 | 76 | if (!aIID.equals(Components.interfaces.inverseIJSContextManager) 77 | && !aIID.equals(Components.interfaces.nsISupports)) 78 | throw Components.results.NS_ERROR_NO_INTERFACE; 79 | 80 | return this; 81 | } 82 | */ 83 | /*QueryInterface: ChromeUtils.generateQI([Ci.inverseIJSContextManager])*/ 84 | }; 85 | 86 | var contextManagerInstance = new ContextManager(); 87 | 88 | /** Module Registration */ 89 | //function NSGetFactory(cid) { 90 | // return (XPCOMUtils.generateNSGetFactory([ContextManager]))(cid); 91 | //} 92 | //this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ContextManager]); 93 | -------------------------------------------------------------------------------- /chrome/content/inverse-library/calendar-cache.js: -------------------------------------------------------------------------------- 1 | Components.utils.import("resource://gre/modules/Preferences.jsm"); 2 | 3 | function reloadCalendarCache(aCalendar) { 4 | if (aCalendar.type == "caldav") { 5 | let sortOrderPref = Preferences.get("calendar.list.sortOrder", "").split(" "); 6 | let initialSortOrderPos = null; 7 | for (let i = 0; i < sortOrderPref.length; ++i) { 8 | if (sortOrderPref[i] == aCalendar.id) { 9 | initialSortOrderPos = i; 10 | } 11 | } 12 | 13 | var mgr = (Components.classes["@mozilla.org/calendar/manager;1"] 14 | .getService(Components.interfaces.calICalendarManager) 15 | .wrappedJSObject); 16 | 17 | mgr.unregisterCalendar(aCalendar); 18 | mgr.removeCalendar(aCalendar); 19 | 20 | var newCal = mgr.createCalendar(aCalendar.type, aCalendar.uri); 21 | newCal.name = aCalendar.name; 22 | 23 | let propsToCopy = [ "color", 24 | "disabled", 25 | "auto-enabled", 26 | "cache.enabled", 27 | "refreshInterval", 28 | "suppressAlarms", 29 | "calendar-main-in-composite", 30 | "calendar-main-default", 31 | "readOnly", 32 | "imip.identity.key", 33 | "aclManagerClass", 34 | "calendar.sogo.notify-on-personal-modifications", 35 | "calendar.sogo.notify-on-external-modifications", 36 | "calendar.sogo.notify-user-on-personal-modifications", 37 | "calendar.sogo.notified-user-on-personal-modifications"]; 38 | 39 | for (let prop of propsToCopy ) { 40 | newCal.setProperty(prop, 41 | aCalendar.getProperty(prop)); 42 | } 43 | 44 | if (initialSortOrderPos != null) { 45 | newCal.setProperty("initialSortOrderPos", 46 | initialSortOrderPos); 47 | } 48 | 49 | mgr.registerCalendar(newCal); 50 | 51 | if (aCalendar.wrappedJSObject.setupCachedCalendar) { 52 | aCalendar.wrappedJSObject.setupCachedCalendar(); 53 | } 54 | else { 55 | // Invoked from CalDAVACLManager.js 56 | aCalendar.superCalendar.wrappedJSObject.setupCachedCalendar(); 57 | aCalendar.aclEntry.refresh(); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /chrome/content/inverse-library/quoted-printable.js: -------------------------------------------------------------------------------- 1 | function QuotedPrintableDecoder() { 2 | this.mCharset = "iso-8859-1"; 3 | } 4 | 5 | QuotedPrintableDecoder.prototype = { 6 | get charset() { 7 | return this.mCharset; 8 | }, 9 | set charset(newCharset) { 10 | this.mCharset = newCharset; 11 | }, 12 | 13 | decode: function(value) { 14 | let decoded = []; 15 | 16 | let count = 0; 17 | let i = 0; 18 | while (i < value.length) { 19 | let currentChar = value[i]; 20 | if (currentChar == "=") { 21 | let hexValue = (value[i+1] + value[i+2]).toLowerCase(); 22 | let decodedChar = String.fromCharCode(this._decodeHEX(hexValue)); 23 | decoded.push(decodedChar); 24 | i += 3; 25 | } 26 | else { 27 | decoded.push(currentChar); 28 | i++; 29 | } 30 | count++; 31 | } 32 | 33 | let converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"] 34 | .createInstance(Components.interfaces.nsIScriptableUnicodeConverter); 35 | converter.charset = this.charset; 36 | 37 | return converter.ConvertToUnicode(decoded.join("")); 38 | }, 39 | _decodeHEX: function(string) { 40 | let t = 0; 41 | let currentInt = 0; 42 | let charCode0 = "0".charCodeAt(0); 43 | let charCodea = "a".charCodeAt(0); 44 | let charCodez = "z".charCodeAt(0); 45 | 46 | for (let i = 0; i < string.length; i++) { 47 | let code = string.charCodeAt(i); 48 | let currentInt = code - charCode0; 49 | if (currentInt > 9) 50 | currentInt = 10 + code - charCodea; 51 | t = t * 16 + currentInt; 52 | } 53 | 54 | return t; 55 | } 56 | }; 57 | 58 | function QuotedPrintableEncoder() { 59 | this.MaxLineSize = 76; 60 | // Exclamation point through less than, and greater than through tilde 61 | // Tab is not listed here as UnAltered but could be 62 | this.UnAltered = String.fromCharCode(32) + String.fromCharCode(60) + String.fromCharCode(62) + String.fromCharCode(126); 63 | this.UnAlteredEnd = String.fromCharCode(33) + String.fromCharCode(60) + String.fromCharCode(62) + String.fromCharCode(126); 64 | } 65 | 66 | QuotedPrintableEncoder.prototype = { 67 | Encode: function(InputText) { 68 | let re = new RegExp("\r\n","g"); 69 | let SplitText, i, s=""; 70 | SplitText = InputText.split(re); 71 | for (i=0; i= UnAltered.charCodeAt(i) && Character <= UnAltered.charCodeAt(i+1)) 100 | Alter=false; 101 | if (!Alter) 102 | return String.fromCharCode(Character); 103 | x = Character.toString(16).toUpperCase(); 104 | 105 | return (x.length == 1) ? "=0" + x : "=" + x; 106 | } 107 | }; 108 | -------------------------------------------------------------------------------- /chrome/content/inverse-library/test-sogowebdav.xul: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 |