Merge to 2.0.5

maint-2.1.1 SOGo-2.0.5
Francis Lachapelle 2013-04-11 12:56:34 -04:00
commit e9eb8bdc86
219 changed files with 6102 additions and 13249 deletions

View File

@ -4,6 +4,7 @@ host = https://www.transifex.net
[sogo.ui-mailerui]
source_file = UI/MailerUI/English.lproj/Localizable.strings
source_lang = en
trans.ar = UI/MailerUI/Arabic.lproj/Localizable.strings
trans.ca = UI/MailerUI/Catalan.lproj/Localizable.strings
trans.cs = UI/MailerUI/Czech.lproj/Localizable.strings
trans.cy = UI/MailerUI/Welsh.lproj/Localizable.strings
@ -29,6 +30,7 @@ trans.uk = UI/MailerUI/Ukrainian.lproj/Localizable.strings
[sogo.ui-preferencesui]
source_file = UI/PreferencesUI/English.lproj/Localizable.strings
source_lang = en
trans.ar = UI/PreferencesUI/Arabic.lproj/Localizable.strings
trans.ca = UI/PreferencesUI/Catalan.lproj/Localizable.strings
trans.cs = UI/PreferencesUI/Czech.lproj/Localizable.strings
trans.cy = UI/PreferencesUI/Welsh.lproj/Localizable.strings
@ -54,6 +56,7 @@ trans.uk = UI/PreferencesUI/Ukrainian.lproj/Localizable.strings
[sogo.ui-scheduler]
source_file = UI/Scheduler/English.lproj/Localizable.strings
source_lang = en
trans.ar = UI/Scheduler/Arabic.lproj/Localizable.strings
trans.ca = UI/Scheduler/Catalan.lproj/Localizable.strings
trans.cs = UI/Scheduler/Czech.lproj/Localizable.strings
trans.cy = UI/Scheduler/Welsh.lproj/Localizable.strings
@ -79,6 +82,7 @@ trans.uk = UI/Scheduler/Ukrainian.lproj/Localizable.strings
[sogo.ui-contacts]
source_file = UI/Contacts/English.lproj/Localizable.strings
source_lang = en
trans.ar = UI/Contacts/Arabic.lproj/Localizable.strings
trans.ca = UI/Contacts/Catalan.lproj/Localizable.strings
trans.cs = UI/Contacts/Czech.lproj/Localizable.strings
trans.cy = UI/Contacts/Welsh.lproj/Localizable.strings
@ -104,6 +108,7 @@ trans.uk = UI/Contacts/Ukrainian.lproj/Localizable.strings
[sogo.ui-mainui]
source_file = UI/MainUI/English.lproj/Localizable.strings
source_lang = en
trans.ar = UI/MainUI/Arabic.lproj/Localizable.strings
trans.ca = UI/MainUI/Catalan.lproj/Localizable.strings
trans.cs = UI/MainUI/Czech.lproj/Localizable.strings
trans.cy = UI/MainUI/Welsh.lproj/Localizable.strings
@ -129,6 +134,7 @@ trans.uk = UI/MainUI/Ukrainian.lproj/Localizable.strings
[sogo.ui-common]
source_file = UI/Common/English.lproj/Localizable.strings
source_lang = en
trans.ar = UI/Common/Arabic.lproj/Localizable.strings
trans.ca = UI/Common/Catalan.lproj/Localizable.strings
trans.cs = UI/Common/Czech.lproj/Localizable.strings
trans.cy = UI/Common/Welsh.lproj/Localizable.strings
@ -154,6 +160,7 @@ trans.uk = UI/Common/Ukrainian.lproj/Localizable.strings
[sogo.ui-administrationui]
source_file = UI/AdministrationUI/English.lproj/Localizable.strings
source_lang = en
trans.ar = UI/AdministrationUI/Arabic.lproj/Localizable.strings
trans.ca = UI/AdministrationUI/Catalan.lproj/Localizable.strings
trans.cs = UI/AdministrationUI/Czech.lproj/Localizable.strings
trans.cy = UI/AdministrationUI/Welsh.lproj/Localizable.strings
@ -179,6 +186,7 @@ trans.uk = UI/AdministrationUI/Ukrainian.lproj/Localizable.strings
[sogo.soobjects-appointments]
source_file = SoObjects/Appointments/English.lproj/Localizable.strings
source_lang = en
trans.ar = SoObjects/Appointments/Arabic.lproj/Localizable.strings
trans.ca = SoObjects/Appointments/Catalan.lproj/Localizable.strings
trans.cs = SoObjects/Appointments/Czech.lproj/Localizable.strings
trans.cy = SoObjects/Appointments/Welsh.lproj/Localizable.strings
@ -204,6 +212,7 @@ trans.uk = SoObjects/Appointments/Ukrainian.lproj/Localizable.strings
[sogo.soobjects-contacts]
source_file = SoObjects/Contacts/English.lproj/Localizable.strings
source_lang = en
trans.ar = SoObjects/Contacts/Arabic.lproj/Localizable.strings
trans.ca = SoObjects/Contacts/Catalan.lproj/Localizable.strings
trans.cs = SoObjects/Contacts/Czech.lproj/Localizable.strings
trans.cy = SoObjects/Contacts/Welsh.lproj/Localizable.strings
@ -229,6 +238,7 @@ trans.uk = SoObjects/Contacts/Ukrainian.lproj/Localizable.strings
[sogo.ui-mailpartviewers]
source_file = UI/MailPartViewers/English.lproj/Localizable.strings
source_lang = en
trans.ar = UI/MailPartViewers/Arabic.lproj/Localizable.strings
trans.ca = UI/MailPartViewers/Catalan.lproj/Localizable.strings
trans.cs = UI/MailPartViewers/Czech.lproj/Localizable.strings
trans.cy = UI/MailPartViewers/Welsh.lproj/Localizable.strings

View File

@ -0,0 +1,26 @@
# use *:8843 for SSL
<VirtualHost *:8800>
RewriteEngine Off
ProxyRequests Off
SetEnv proxy-nokeepalive 1
ProxyPreserveHost On
ProxyPassInterpolateEnv On
ProxyPass /principals http://127.0.0.1:20000/SOGo/dav/ interpolate
ProxyPass /SOGo http://127.0.0.1:20000/SOGo interpolate
ProxyPass / http://127.0.0.1:20000/SOGo/dav/ interpolate
<Location />
Order allow,deny
Allow from all
</Location>
<Proxy http://127.0.0.1:20000>
RequestHeader set "x-webobjects-server-port" "8800"
RequestHeader set "x-webobjects-server-name" "changethis:8800"
RequestHeader set "x-webobjects-server-url" "http://changethis:8800"
RequestHeader set "x-webobjects-server-protocol" "HTTP/1.0"
AddDefaultCharset UTF-8
</Proxy>
ErrorLog /var/log/apache2/ab-error.log
CustomLog /var/log/apache2/ab-access.log combined
</VirtualHost>

View File

@ -59,7 +59,6 @@ ProxyPass /SOGo http://127.0.0.1:20000/SOGo retry=0
# RequestHeader set "x-webobjects-remote-user" "%{REMOTE_USER}e"
RequestHeader set "x-webobjects-server-protocol" "HTTP/1.0"
RequestHeader set "x-webobjects-remote-host" %{REMOTE_HOST}e env=REMOTE_HOST
AddDefaultCharset UTF-8
@ -67,8 +66,3 @@ ProxyPass /SOGo http://127.0.0.1:20000/SOGo retry=0
Allow from all
</Proxy>
## We use mod_rewrite to pass remote address to the SOGo proxy.
# The remote address will appear in SOGo's log files and in the X-Forward
# header of emails.
RewriteEngine On
RewriteRule ^/SOGo/(.*)$ /SOGo/$1 [env=REMOTE_HOST:%{REMOTE_ADDR},PT]

936
ChangeLog
View File

@ -1,3 +1,912 @@
commit 30f10ee8f06157b1222d68b0502c80162fcbb277
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Thu Apr 11 11:30:23 2013 -0400
Update translations
M SoObjects/Appointments/Russian.lproj/Localizable.strings
M UI/Common/BrazilianPortuguese.lproj/Localizable.strings
M UI/Common/Russian.lproj/Localizable.strings
M UI/Contacts/Polish.lproj/Localizable.strings
M UI/MailerUI/BrazilianPortuguese.lproj/Localizable.strings
M UI/MailerUI/Czech.lproj/Localizable.strings
M UI/MailerUI/Dutch.lproj/Localizable.strings
M UI/MailerUI/French.lproj/Localizable.strings
M UI/MailerUI/German.lproj/Localizable.strings
M UI/MailerUI/Hungarian.lproj/Localizable.strings
M UI/MailerUI/Polish.lproj/Localizable.strings
M UI/MailerUI/Russian.lproj/Localizable.strings
M UI/MailerUI/Slovak.lproj/Localizable.strings
M UI/MailerUI/SpanishArgentina.lproj/Localizable.strings
M UI/MailerUI/SpanishSpain.lproj/Localizable.strings
M UI/Scheduler/BrazilianPortuguese.lproj/Localizable.strings
M UI/Scheduler/Czech.lproj/Localizable.strings
M UI/Scheduler/Dutch.lproj/Localizable.strings
M UI/Scheduler/Finnish.lproj/Localizable.strings
M UI/Scheduler/French.lproj/Localizable.strings
M UI/Scheduler/German.lproj/Localizable.strings
M UI/Scheduler/Hungarian.lproj/Localizable.strings
M UI/Scheduler/Polish.lproj/Localizable.strings
M UI/Scheduler/Russian.lproj/Localizable.strings
M UI/Scheduler/Slovak.lproj/Localizable.strings
M UI/Scheduler/SpanishArgentina.lproj/Localizable.strings
M UI/Scheduler/SpanishSpain.lproj/Localizable.strings
commit dfb8788270ff3b30133417a52c9052fafea19ae2
Author: Jean Raby <jraby@inverse.ca>
Date: Thu Apr 11 10:37:34 2013 -0400
don't build SAML support on debian yet
M packaging/debian/control-squeeze
M packaging/debian/rules
commit 3810833e1b5c1e02cdac731da15b68057e1176af
Author: Jean Raby <jraby@inverse.ca>
Date: Thu Apr 11 10:22:28 2013 -0400
remove unrtf leftovers
M OpenChange/GNUmakefile
D OpenChange/GNUmakefile.unrtf
M packaging/debian-multiarch/rules
M packaging/debian/rules
commit 29e05c7c81b1a92d4b6bbc9be96d40f8ae3f2482
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Thu Apr 11 10:20:10 2013 -0400
Bump version to 2.0.5
M Documentation/SOGo Installation Guide.odt
M Documentation/SOGo Mobile Devices Configuration.odt
M Documentation/SOGo Mozilla Thunderbird Configuration.odt
M Documentation/SOGo Native Microsoft Outlook Configuration.odt
M NEWS
M Version
commit 0a08285facce833fecba8319c4f0b2bdf641746e
Author: Jean Raby <jraby@inverse.ca>
Date: Thu Apr 11 10:09:02 2013 -0400
Add note regarding precedence of .GNUstepDefaults
M Scripts/sogo.conf
commit 01f20a42ad55356c772ca2a4a758d5421e986987
Author: Jean Raby <jraby@inverse.ca>
Date: Thu Apr 11 09:18:43 2013 -0400
packaging fixups
M packaging/debian/sogo.postinst
M packaging/rhel/sogo.spec
commit 3a61a2566bf2c6e95b665f2474350c8e1c59328b
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Wed Apr 10 18:24:03 2013 -0400
Updated installation guide: version 2.0.5
M Documentation/SOGo Installation Guide.odt
commit d2dda86529b3fe6a1d383522640f4898c00b5f25
Author: Jean Raby <jraby@inverse.ca>
Date: Wed Apr 10 16:30:16 2013 -0400
... dir fixup again
M packaging/debian-multiarch/sogo.postinst
commit cc125d2192a8b1fb84c7d239c708735d18c33772
Author: Jean Raby <jraby@inverse.ca>
Date: Wed Apr 10 16:27:03 2013 -0400
directory fixup
M packaging/debian-multiarch/rules
M packaging/debian/rules
commit 4da1e41d936fb0fc3bc24be5a104f0c4339fcd68
Author: Jean Raby <jraby@inverse.ca>
Date: Wed Apr 10 16:20:47 2013 -0400
deb: install a sample sogo.conf in /etc/sogo
While there, replace mkdir + cp combo with 'install'
M packaging/debian-multiarch/rules
M packaging/debian-multiarch/sogo.install
M packaging/debian-multiarch/sogo.postinst
M packaging/debian-multiarch/sogo.preinst
M packaging/debian/rules
M packaging/debian/sogo.install
M packaging/debian/sogo.postinst
M packaging/debian/sogo.preinst
commit e24eb10c4fa9ce6b53021ef04a23254ad7fb7cab
Author: Jean Raby <jraby@inverse.ca>
Date: Wed Apr 10 16:20:16 2013 -0400
rpm: install a sample sogo.conf in /etc/sogo
M packaging/rhel/sogo.spec
commit dd9e51fd16822ac453b944b7e9a7efc3cd9caefa
Author: Jean Raby <jraby@inverse.ca>
Date: Wed Apr 10 16:16:30 2013 -0400
sogo.conf - new example configuration file
A Scripts/sogo.conf
commit 9932d1413b23a50bfb0665af24acb17b59f5f55f
Author: Jean Raby <jraby@inverse.ca>
Date: Wed Apr 10 12:29:48 2013 -0400
update NEWS
M NEWS
commit ff13c4954032566676b42a4cebd857de5644632a
Author: Jean Raby <jraby@inverse.ca>
Date: Wed Apr 10 12:16:26 2013 -0400
updated NEWS
M NEWS
commit 1e33b4bf269d660c77fbc891adb4776a83d0b601
Author: Jean Raby <jraby@inverse.ca>
Date: Wed Apr 10 12:05:44 2013 -0400
Add notes regarding UIDField: value must be unique
M Documentation/SOGo Installation Guide.odt
commit e23a7df125cd081c078f0baf5fd63acbe8b5f21a
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Wed Apr 10 11:33:41 2013 -0400
Update NEWS file
M NEWS
commit 4ca476db9e8a81b412a0b15525eeeaa76a78237a
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Wed Apr 10 11:30:40 2013 -0400
Updated NEWS file
M NEWS
commit 33840c71cd38a22766f3e0463a17361e6fea8292
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Wed Apr 10 10:48:25 2013 -0400
Changed noop by unselect/select.
M OpenChange/MAPIStoreMailVolatileMessage.m
commit 1b983ef691f55e3588cc9afcb9ba841ca472d3d7
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Wed Apr 10 09:56:23 2013 -0400
Fixed a potential timing issue with Dovecot when getting the modseq
M OpenChange/MAPIStoreMailVolatileMessage.m
commit eec8c07d4f061a2006bd7ec9967a2b1c92e7618b
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Tue Apr 9 11:35:53 2013 -0400
Avoid appending the domain if already present.
M SoObjects/SOGo/SOGoWebAuthenticator.m
commit 84ba93fc0a5c5a650482d1afdee6f93fdd9ea277
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Mon Apr 8 13:58:55 2013 -0400
Now set ForceAuthn to false by default
M SoObjects/SOGo/SOGoSAML2Session.m
commit 37a6f8265978b2a2ec019527b16b68ed10051cf3
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Mon Apr 8 11:05:45 2013 -0400
Initial Arabic translation
M .tx/config
A SoObjects/Appointments/Arabic.lproj/Localizable.strings
M SoObjects/Appointments/GNUmakefile
A SoObjects/Contacts/Arabic.lproj/Localizable.strings
M SoObjects/Contacts/GNUmakefile
M SoObjects/Mailer/GNUmakefile
A SoObjects/Mailer/SOGoMailArabicForward.wo/SOGoMailArabicForward.html
A SoObjects/Mailer/SOGoMailArabicForward.wo/SOGoMailArabicForward.wod
A SoObjects/Mailer/SOGoMailArabicReply.wo/SOGoMailArabicReply.html
A SoObjects/Mailer/SOGoMailArabicReply.wo/SOGoMailArabicReply.wod
M SoObjects/Mailer/SOGoMailForward.h
M SoObjects/Mailer/SOGoMailForward.m
M SoObjects/Mailer/SOGoMailReply.h
M SoObjects/Mailer/SOGoMailReply.m
M SoObjects/SOGo/SOGoDefaults.plist
M Tests/Integration/preferences.py
A UI/AdministrationUI/Arabic.lproj/Localizable.strings
M UI/AdministrationUI/GNUmakefile
A UI/Common/Arabic.lproj/Localizable.strings
M UI/Common/GNUmakefile
A UI/Contacts/Arabic.lproj/Localizable.strings
M UI/Contacts/GNUmakefile
A UI/MailPartViewers/Arabic.lproj/Localizable.strings
M UI/MailPartViewers/GNUmakefile
A UI/MailerUI/Arabic.lproj/Localizable.strings
M UI/MailerUI/GNUmakefile
A UI/MainUI/Arabic.lproj/Locale
A UI/MainUI/Arabic.lproj/Localizable.strings
M UI/MainUI/BrazilianPortuguese.lproj/Localizable.strings
M UI/MainUI/Catalan.lproj/Localizable.strings
M UI/MainUI/Czech.lproj/Localizable.strings
M UI/MainUI/Danish.lproj/Localizable.strings
M UI/MainUI/Dutch.lproj/Localizable.strings
M UI/MainUI/English.lproj/Localizable.strings
M UI/MainUI/Finnish.lproj/Localizable.strings
M UI/MainUI/French.lproj/Localizable.strings
M UI/MainUI/GNUmakefile
M UI/MainUI/German.lproj/Localizable.strings
M UI/MainUI/Hungarian.lproj/Localizable.strings
M UI/MainUI/Icelandic.lproj/Localizable.strings
M UI/MainUI/Italian.lproj/Localizable.strings
M UI/MainUI/NorwegianBokmal.lproj/Localizable.strings
M UI/MainUI/NorwegianNynorsk.lproj/Localizable.strings
M UI/MainUI/Polish.lproj/Localizable.strings
M UI/MainUI/Russian.lproj/Localizable.strings
M UI/MainUI/SpanishArgentina.lproj/Localizable.strings
M UI/MainUI/SpanishSpain.lproj/Localizable.strings
M UI/MainUI/Swedish.lproj/Localizable.strings
M UI/MainUI/Ukrainian.lproj/Localizable.strings
M UI/MainUI/Welsh.lproj/Localizable.strings
A UI/PreferencesUI/Arabic.lproj/Localizable.strings
M UI/PreferencesUI/BrazilianPortuguese.lproj/Localizable.strings
M UI/PreferencesUI/Catalan.lproj/Localizable.strings
M UI/PreferencesUI/Czech.lproj/Localizable.strings
M UI/PreferencesUI/Danish.lproj/Localizable.strings
M UI/PreferencesUI/Dutch.lproj/Localizable.strings
M UI/PreferencesUI/English.lproj/Localizable.strings
M UI/PreferencesUI/Finnish.lproj/Localizable.strings
M UI/PreferencesUI/French.lproj/Localizable.strings
M UI/PreferencesUI/GNUmakefile
M UI/PreferencesUI/German.lproj/Localizable.strings
M UI/PreferencesUI/Hungarian.lproj/Localizable.strings
M UI/PreferencesUI/Icelandic.lproj/Localizable.strings
M UI/PreferencesUI/Italian.lproj/Localizable.strings
M UI/PreferencesUI/NorwegianBokmal.lproj/Localizable.strings
M UI/PreferencesUI/NorwegianNynorsk.lproj/Localizable.strings
M UI/PreferencesUI/Polish.lproj/Localizable.strings
M UI/PreferencesUI/Russian.lproj/Localizable.strings
M UI/PreferencesUI/Slovak.lproj/Localizable.strings
M UI/PreferencesUI/SpanishArgentina.lproj/Localizable.strings
M UI/PreferencesUI/SpanishSpain.lproj/Localizable.strings
M UI/PreferencesUI/Swedish.lproj/Localizable.strings
M UI/PreferencesUI/Ukrainian.lproj/Localizable.strings
M UI/PreferencesUI/Welsh.lproj/Localizable.strings
A UI/Scheduler/Arabic.lproj/Localizable.strings
M UI/Scheduler/GNUmakefile
A UI/Templates/SOGoACLArabicAdditionAdvisory.wox
A UI/Templates/SOGoACLArabicModificationAdvisory.wox
A UI/Templates/SOGoACLArabicRemovalAdvisory.wox
A UI/Templates/SOGoFolderArabicAdditionAdvisory.wox
A UI/Templates/SOGoFolderArabicRemovalAdvisory.wox
commit b4aaa68d85edbaee9f555efef3f82f64598c050f
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Fri Apr 5 10:26:17 2013 -0400
Also consider the "mail" attribute in order to get the user's login
M SoObjects/SOGo/SOGoSAML2Session.m
commit 5487f34b9ee9b9639e3f1d4a7abf4fad2d240d66
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Fri Apr 5 08:57:47 2013 -0400
Disable hint verification for now.
M SoObjects/SOGo/SOGoSAML2Session.m
commit e07734fa5f57325a92ea70bcb4410b73340aa026
Author: Jean Raby <jraby@inverse.ca>
Date: Fri Mar 29 10:38:52 2013 -0400
Filter sql source entries based on the user domain
When using dynamic domains with SQL sources (DomainFieldName),
let WebUI and dav lookups return entries from current domain
and other domains visible from the originating domain.
Fixes #2269
SQLSource.m: _visibleDomainsQualifierFromDomain:
returns a EOQualifier OR'ing all visible domains from specified domain
(including specified domain)
SQLSource.m: allEntryIDsVisibleFromDomain
Replacement for allEntryIDs.
Instead of returning all entries from the sql source,
only return the entries visible from the specified domain.
SoObjects/SOGo/SQLSource.m: allEntryIDs
Changed to call allEntryIDsVisibleFromDomain with an empty domain.
SQLSource.m fetchContactsMatching:inDomain:
Use _visibleDomainsQualifierFromDomain to filter entries
LDAPSource.m: allEntryIDsVisibleFromDomain
Simply call allEntryIDs, discarding the domain.
LDAP does need to do the extra domain filtering
SOGoContactSourceFolder.m: toOneRelationshipKeys
Call new method: allEntryIDsVisibleFromDomain
M SoObjects/Contacts/SOGoContactSourceFolder.m
M SoObjects/SOGo/LDAPSource.m
M SoObjects/SOGo/SOGoSource.h
M SoObjects/SOGo/SQLSource.m
commit 6a8e6cd762c51514224eb3cf24ae08c8a2a08d23
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Thu Mar 28 08:32:00 2013 -0400
Fixed the GNUmakfile and const's for charset tables.
M OpenChange/GNUmakefile
M OpenChange/RTFHandler.m
commit 663351029ac49e1c9802e07d1c874a872f147ca3
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Tue Mar 26 19:32:08 2013 -0400
Replaced unrtf by our own RTF to HTML converter.
Faster, thread safe, a hell lot cleaner.
M OpenChange/GNUmakefile
M OpenChange/MAPIStoreMessage.m
A OpenChange/RTFHandler.h
A OpenChange/RTFHandler.m
D OpenChange/unrtf-0.21.2.diff
D OpenChange/unrtf-0.21.2.tar.gz
D OpenChange/unrtf_config_h
commit c26e5fa7fed83bae25529679fead923e8a8fe1f2
Author: Jean Raby <jraby@inverse.ca>
Date: Tue Mar 26 14:01:04 2013 -0400
semi-colon
M OpenChange/gen-charset-table.py
commit 74c01dc44841c696ed322c9b0bff542e7f2b4115
Author: Jean Raby <jraby@inverse.ca>
Date: Tue Mar 26 13:42:22 2013 -0400
gen-charset-table.py: script to import ms charmaps
For example: http://msdn.microsoft.com/en-us/goglobal/cc305147
A OpenChange/gen-charset-table.py
commit a009c71034826e3755a987a0f5730724dfc9f063
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Mon Mar 25 15:58:36 2013 -0400
Fixed table initialization.
M SoObjects/SOGo/SOGoSAML2Session.m
commit b4ebc90dd0b452dfe134efc137de2f62b8ece59e
Author: Jean Raby <jraby@inverse.ca>
Date: Mon Mar 25 14:12:12 2013 -0400
replace subprocess.check_output with Popen magic
check_output isn't available in py 2.6...
M Scripts/openchange_cleanup.py
commit 95dc134ca618a47be6e2eafca71e6c7f9c9cbccc
Author: Jean Raby <jraby@inverse.ca>
Date: Fri Mar 22 15:13:39 2013 -0400
Revamped openchange_cleanup.py
This is now usable again.
- Don't delete password files in mapistoreCleanup()
- reworked the ldb cleanup and enabled it
- sql cleanup should now be able to figure out the db info from the config
regardless of the format used (xml, plist, sogo.conf or GNUstepDefaults)
(We really need a python plist parser.. the current solution is not elegant)
- Inform user of missing python packages
M Scripts/openchange_cleanup.py
commit 9c4b7d848141166eb9742e080831b017d660ec78
Author: Jean Raby <jraby@inverse.ca>
Date: Thu Mar 21 15:39:02 2013 -0400
Add notes regarding html mails and mod_reqtimeout
M Documentation/SOGo Native Microsoft Outlook Configuration.odt
commit 9fb9f2cae667aa966e285216846a6b688418f753
Author: Jean Raby <jraby@inverse.ca>
Date: Wed Mar 20 11:51:37 2013 -0400
Enable saml2 support on squeeze (temporary fix)
M packaging/debian/control-squeeze
M packaging/debian/rules
commit 15f9b7d22e6a5937224570b580dee31e391789dd
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Fri Mar 15 11:23:27 2013 -0400
Fix comments in UIxContactFolderActions.*
M UI/Contacts/UIxContactFolderActions.h
M UI/Contacts/UIxContactFolderActions.m
commit 5f179ed6b0726504bbe7f300df3a8cbaa5d3c9a6
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Fri Mar 15 11:06:26 2013 -0400
Activate the menu option "Mark Folder Read"
Fixes #1473
M NEWS
M UI/MailerUI/BrazilianPortuguese.lproj/Localizable.strings
M UI/MailerUI/Catalan.lproj/Localizable.strings
M UI/MailerUI/Czech.lproj/Localizable.strings
M UI/MailerUI/Danish.lproj/Localizable.strings
M UI/MailerUI/Dutch.lproj/Localizable.strings
M UI/MailerUI/English.lproj/Localizable.strings
M UI/MailerUI/Finnish.lproj/Localizable.strings
M UI/MailerUI/French.lproj/Localizable.strings
M UI/MailerUI/German.lproj/Localizable.strings
M UI/MailerUI/Hungarian.lproj/Localizable.strings
M UI/MailerUI/Icelandic.lproj/Localizable.strings
M UI/MailerUI/Italian.lproj/Localizable.strings
M UI/MailerUI/NorwegianBokmal.lproj/Localizable.strings
M UI/MailerUI/NorwegianNynorsk.lproj/Localizable.strings
M UI/MailerUI/Polish.lproj/Localizable.strings
M UI/MailerUI/Russian.lproj/Localizable.strings
M UI/MailerUI/Slovak.lproj/Localizable.strings
M UI/MailerUI/SpanishArgentina.lproj/Localizable.strings
M UI/MailerUI/SpanishSpain.lproj/Localizable.strings
M UI/MailerUI/Swedish.lproj/Localizable.strings
M UI/MailerUI/UIxMailFolderActions.m
M UI/MailerUI/Ukrainian.lproj/Localizable.strings
M UI/MailerUI/Welsh.lproj/Localizable.strings
M UI/MailerUI/product.plist
M UI/Templates/MailerUI/UIxMailMainFrame.wox
M UI/WebServerResources/MailerUI.js
commit 93f9a7273e96970106259e4902cf378a425d1322
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Wed Mar 13 15:04:11 2013 -0400
Now handle mem context when saving messages and removed useless debugging.
M OpenChange/EOQualifier+MAPI.m
M OpenChange/MAPIStoreCalendarEmbeddedMessage.m
M OpenChange/MAPIStoreCalendarFolder.m
M OpenChange/MAPIStoreCalendarMessage.m
M OpenChange/MAPIStoreContext.m
M OpenChange/MAPIStoreDBFolder.m
M OpenChange/MAPIStoreDBMessage.m
M OpenChange/MAPIStoreDBMessageTable.m
M OpenChange/MAPIStoreEmbeddedMessage.m
M OpenChange/MAPIStoreFAIMessage.m
M OpenChange/MAPIStoreFolder.m
M OpenChange/MAPIStoreGCSMessageTable.m
M OpenChange/MAPIStoreMailFolder.m
M OpenChange/MAPIStoreMailMessage.m
M OpenChange/MAPIStoreMailMessageTable.m
M OpenChange/MAPIStoreMailVolatileMessage.m
M OpenChange/MAPIStoreMessage.h
M OpenChange/MAPIStoreMessage.m
M OpenChange/MAPIStoreSOGo.m
M OpenChange/MAPIStoreTable.m
M OpenChange/MAPIStoreTypes.m
M OpenChange/NSObject+MAPIStore.m
M OpenChange/SOGoMAPIDBObject.m
M OpenChange/iCalEvent+MAPIStore.h
M OpenChange/iCalEvent+MAPIStore.m
commit 15e082896ce62665ca7b655521a1b43505fd9401
Author: Jean Raby <jraby@inverse.ca>
Date: Tue Mar 12 09:08:19 2013 -0400
Update sogo-tool expire-autoreply syntax in cron
M Scripts/sogo.cron
commit 63ff9751d78d271aba7a1148cf8c1f98003fa543
Author: Jean Raby <jraby@inverse.ca>
Date: Mon Mar 11 11:37:59 2013 -0400
Add ics_compare and use it in _testRespondTo()
This new class uses vobject.ics_diff() to compare 2 VCALENDAR components.
We should use this instead of textually comparing events for equality
in future tests.
M Tests/Integration/test-davacl.py
M Tests/Integration/utilities.py
commit d12c651d59cb6891ce21e21aa8d56f349c75cc2d
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Mon Mar 11 09:34:36 2013 -0400
New system default SOGoEncryptionKey
To be used to encrypt the passwords of remote Web calendars when
SOGoTrustProxyAuthentication is enabled.
M NEWS
M SoObjects/Appointments/SOGoWebAppointmentFolder.m
M SoObjects/SOGo/SOGoDefaults.plist
M SoObjects/SOGo/SOGoSystemDefaults.h
M SoObjects/SOGo/SOGoSystemDefaults.m
commit 41a6c02aa31b5bfb3b9ec0337eb31d22ef1d7e8e
Author: Jean Raby <jraby@inverse.ca>
Date: Fri Mar 8 16:20:27 2013 -0500
Rework web services section
State that HTTPS is mandatory for autodiscovery services.
Add example named config for SRV record.
M Documentation/SOGo Native Microsoft Outlook Configuration.odt
commit a026e75c0e383db73c4096e23bb0370380e914be
Author: Jean Raby <jraby@inverse.ca>
Date: Fri Mar 8 15:57:10 2013 -0500
Removed note about linefeed in password files
This is handled by the code now
M Documentation/SOGo Native Microsoft Outlook Configuration.odt
commit 46815042c94dc79cbf93aafeaae91e382be79c1c
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Thu Mar 7 09:29:56 2013 -0500
Fixed bug when modifying/deleting exceptions of recurring events.
M SoObjects/Appointments/SOGoAppointmentObject.m
commit c79af52b67cdfe76d250e5607e2243b446df26a8
Author: Jean Raby <jraby@inverse.ca>
Date: Wed Mar 6 11:03:19 2013 -0500
Fix BSONCodec.m includes
include objc.h instead of runtime.h so that it works on older gcc objc runtime
M OpenChange/BSONCodec.m
commit e882dedac9e25320c2190fbce0654697e19586ec
Author: Jean Raby <jraby@inverse.ca>
Date: Tue Mar 5 11:01:51 2013 -0500
Update News
M NEWS
M Scripts/sql-update-2.0.4b_to_2.0.5-mysql.sh
commit 13277bbdb955a18200b26919c14171e7f391bc65
Author: Jean Raby <jraby@inverse.ca>
Date: Tue Mar 5 10:47:09 2013 -0500
c_content TEXT to LONGTEXT for OpenChange tables
Add an script to update existing tables.
Note that if a row already have 65535 char in it,
the data is most likely broken.
M OpenChange/GCSSpecialQueries+OpenChange.m
A Scripts/sql-update-2.0.4b_to_2.0.5-mysql.sh
commit 7e8a83aefb5bd1e89225dd2bd6be847bcbb39470
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Tue Mar 5 10:22:20 2013 -0500
Fix Slovak templates for mail reply/forward
M SoObjects/Mailer/GNUmakefile
M SoObjects/Mailer/SOGoMailForward.h
M SoObjects/Mailer/SOGoMailForward.m
M SoObjects/Mailer/SOGoMailReply.h
M SoObjects/Mailer/SOGoMailReply.m
commit f1846191d5d47717e7c5dff710e265e21c8f0fe2
Author: Jean Raby <jraby@inverse.ca>
Date: Fri Mar 1 16:24:16 2013 -0500
Use an autorelease pool in member expansion
Otherwise, we would hold one ldap connection for each member of a group.
And close them all later. With large groups, we could hit the open file limit
(or the open file limit of the ldap server).
Fixes #2256
M SoObjects/SOGo/SOGoGroup.m
commit a7c3f33447a3e0c6902913013574052763c36eaa
Author: Jean Raby <jraby@inverse.ca>
Date: Fri Mar 1 01:26:15 2013 -0500
Whitespace
M SoObjects/SOGo/SOGoGroup.m
commit 89766b2e7e037be88d1460520c762c77d66f302e
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Wed Feb 20 12:10:34 2013 -0500
Temporary fix for unsigned long long values.
M OpenChange/BSONCodec.m
commit 7d65d808f6ff80a2a5bac2a8c55ad218ba44aaa6
Author: Jean Raby <jraby@inverse.ca>
Date: Wed Feb 20 10:50:58 2013 -0500
Strip newline characters from user password files
Makes it easier to create those files with a regular editor.
M OpenChange/MAPIStoreUserContext.m
commit fa5e99d58dd9a70602e47481bd02e70c76e2727f
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Tue Feb 19 15:54:52 2013 -0500
Much better fix over previous commit.
M OpenChange/BSONCodec.m
M OpenChange/NSString+MAPIStore.m
commit 67c2d508ea2d0b6007d110d67383c7030711e0b9
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Tue Feb 19 15:42:05 2013 -0500
Added rationale around previous commit.
M OpenChange/NSString+MAPIStore.m
commit 19923d10dbcba8598f4b2ed3aec86b2fe508a68f
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Tue Feb 19 15:30:29 2013 -0500
Also handle date-strings as date objects.
Dates are stored as string in BSON - might change in the future.
M OpenChange/NSString+MAPIStore.m
commit e57b6835e63f4a888edfdee4c382a6c9c1d6c872
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Mon Feb 18 16:50:54 2013 -0500
Fix for objective-c runtimes.
M OpenChange/BSONCodec.m
commit bcab7e7dc9eb664ece3f4bf9301e5c2acd8036b1
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Mon Feb 18 16:42:59 2013 -0500
C99 style fixes.
M OpenChange/BSONCodec.m
commit 2572eedd8988f8a3d3e3d819c27ad070aa250c0b
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Mon Feb 18 16:28:06 2013 -0500
Added BSON encoder/decoder for Outlook cache files.
A OpenChange/BSONCodec.h
A OpenChange/BSONCodec.m
M OpenChange/GNUmakefile
M OpenChange/MAPIStoreTypes.h
M OpenChange/NSObject+PropertyList.m
M OpenChange/SOGoMAPIDBObject.m
commit efb45bfba69ca5dac10f9de5cb59f353e2bd0a34
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Fri Feb 15 15:17:08 2013 -0500
Fix issue with exceptions in repeating events
Fixed the display of an exception when its recurrence id is outside the
current view.
M NEWS
M SoObjects/Appointments/SOGoAppointmentFolder.m
commit 4f38b5cf3f3118784125b495167923a9027d243a
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Thu Feb 14 15:59:19 2013 -0500
Alse use hex-formatted keys for deleted mails.
M OpenChange/MAPIStoreMailFolder.m
commit 71b9772546b83df5bd671ad46a9d10155da596af
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Thu Feb 14 15:22:48 2013 -0500
Ensure we hit the cache with hex-formatted keys.
M OpenChange/MAPIStoreMailMessageTable.m
M OpenChange/MAPIStoreSOGo.m
commit c13c389ae5f55b89f78db4f114e7fb413eb1e201
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Tue Feb 12 08:42:47 2013 -0500
Update Danish translation
M SoObjects/Appointments/Danish.lproj/Localizable.strings
M UI/Common/Danish.lproj/Localizable.strings
M UI/Contacts/Danish.lproj/Localizable.strings
M UI/MailerUI/Danish.lproj/Localizable.strings
M UI/PreferencesUI/Danish.lproj/Localizable.strings
M UI/Scheduler/Danish.lproj/Localizable.strings
commit caf6f0ec6cdc0a43a7026036b26b54ab944ceafc
Author: Jean Raby <jraby@inverse.ca>
Date: Mon Feb 11 10:41:50 2013 -0500
Add example apache configuration for apple AB
A Apache/SOGo-apple-ab.conf
M packaging/debian-multiarch/sogo.docs
M packaging/debian/sogo.docs
M packaging/rhel/sogo.spec
commit 4952ff7914dd0f3aa5c9c2bf5e04e29bf4317836
Author: Jean Raby <jraby@inverse.ca>
Date: Fri Feb 8 16:22:14 2013 -0500
Use SOGoSystemDefaults in all tools
sogo-ealarms-notify and sogo-slapd-sockd will now be able to use sogo.conf
Fixes #2226
M Tools/sogo-ealarms-notify.m
M Tools/sogo-slapd-sockd.m
commit 8981dcd64503f1fa907e98593a76b6bff9cbb02d
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Fri Feb 8 09:42:31 2013 -0500
Fix segfault in SOGoSieveManager.m
M SoObjects/SOGo/SOGoSieveManager.m
commit 470a53a548c46af72d8956475fdacba045458d10
Author: Jean Raby <jraby@inverse.ca>
Date: Thu Feb 7 13:00:27 2013 -0500
Add example configuration for fail2ban
From Arnd Brandes. (#2229)
A Scripts/fail2ban/sogo-filter.conf
A Scripts/fail2ban/sogo-jail.local
commit 7b65b7400e269bdc8d020d29bd8cf0b33aea09e1
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Thu Feb 7 09:00:16 2013 -0500
Update Finnish translation
M UI/MailerUI/Finnish.lproj/Localizable.strings
commit 90c61abdb654e00ad172ab88cc75059c3d45bd6d
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Wed Feb 6 15:16:09 2013 -0500
Update Polish translation
M SoObjects/Mailer/SOGoMailPolishReply.wo/SOGoMailPolishReply.html
commit f8387b90ffd3f016f4a4de88577b1280a84aefc8
Author: Jean Raby <jraby@inverse.ca>
Date: Wed Feb 6 09:23:47 2013 -0500
Log x-webobjects-remote-host in login process
Most of the time, the remote-host will contain data from the x-forwarded-for header.
Which could have more than one ip in it if the request went through multiple proxies.
eg. x-forwarded-for: real.client.ip, load.balancer.ip
M UI/MainUI/SOGoRootPage.m
commit feb02c54b918154919c224e257b79765c0770649
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Tue Feb 5 16:13:18 2013 -0500
Add missing localizable string
M UI/Scheduler/English.lproj/Localizable.strings
M UI/WebServerResources/SchedulerUI.js
commit 49a22994148d25d0f22464f5de69d45112475c95
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Tue Feb 5 16:11:37 2013 -0500
Avoid going out of bounds for special URL chars ending mail contents.
M SoObjects/SOGo/NSString+Utilities.m
commit 43044bf88fdbfe630572ad89a32ef9b2f155ea6d
Author: Jean Raby <jraby@inverse.ca>
Date: Tue Feb 5 15:09:55 2013 -0500
Plug sieve connection leak
Fixes #2228
Fix from 'bofhus'
M SoObjects/SOGo/SOGoSieveManager.m
commit 0532d331a3497d97b91d59fdf3670dc4a21e8b0a
Author: Jean Raby <jraby@inverse.ca>
Date: Tue Feb 5 15:09:20 2013 -0500
whitespace (tabkill)
M SoObjects/SOGo/SOGoSieveManager.m
commit 70fc05091f2f3cdbac1c66291a940a8223e46876
Author: Jean Raby <jraby@inverse.ca>
Date: Tue Feb 5 14:27:16 2013 -0500
Remove x-webobjects-remote-host from apache conf
SOPE now handles this on its own by setting x-webobjects-remote-host
to the content of the x-forward or x-forwarded-for headers if it wasn't defined
M Apache/SOGo.conf
M NEWS
commit 469e5c647e74a53fc03d22c35b6da22fcbf1922d
Author: Jean Raby <jraby@inverse.ca>
Date: Tue Feb 5 11:52:26 2013 -0500
Updated NEWS
M NEWS
commit 3daa7e55b74890a1c03a37290826759f5d0ec05a
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Mon Feb 4 14:24:03 2013 -0500
Update ChangeLog
M ChangeLog
commit 6913502810ec21479889c4ecf0a393de5ede2635
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Mon Feb 4 14:22:37 2013 -0500
@ -77,6 +986,33 @@ Date: Sun Feb 3 20:40:06 2013 -0500
M UI/WebServerResources/UIxPreferences.js
commit 7b5da8a2c9a30d36969fa6aa09b8e168f3e6e243
Author: Jean Raby <jraby@inverse.ca>
Date: Fri Feb 1 19:58:25 2013 -0500
don't use cache for login page
M UI/MainUI/SOGoRootPage.m
commit 451c82c8154b4e2bd4fb4cee5bded7109a1e1942
Author: Jean Raby <jraby@inverse.ca>
Date: Fri Feb 1 18:35:10 2013 -0500
Don't use user/password cache from the login page
The idea is to always use memcached for credentials to avoid hitting
the authentication backend on every click but to check with the auth backend
for every login requests.
This should fix #2169
While there, fix whitespace (killtab)
M SoObjects/SOGo/SOGoUserManager.h
M SoObjects/SOGo/SOGoUserManager.m
M SoObjects/SOGo/SOGoWebAuthenticator.h
M SoObjects/SOGo/SOGoWebAuthenticator.m
commit a4bd966cc0c3429261747384dc746ec5f71423de
Author: Jean Raby <jraby@inverse.ca>
Date: Fri Feb 1 16:26:01 2013 -0500

33
NEWS
View File

@ -1,3 +1,36 @@
2.0.5 (2013-04-11)
------------------
New features
- new system default SOGoEncryptionKey to be used to encrypt the passwords of
remote Web calendars when SOGoTrustProxyAuthentication is enabled
- activated the menu option "Mark Folder Read" in the Webmail (#1473)
Enhancements
- added logging of the X-Forwarded-For HTTP header (#2229)
- now use BSON instead of GNUstep's binary format for serializing
Outlook related cache files
- updated Danish, Finnish, Polish and Slovak translations
- added Arabic translation - thanks to Anass Ahmed
Bug fixes
- don't use the cache for password lookups from login page (#2169)
- fixed issue with exceptions in repeating events
- avoid data truncation issue in OpenChange with mysql backend
run sql-update-2.0.4b_to_2.0.5-mysql.sh to update existing tables
- avoid random crashes in OpenChange due to RTF conversion
- fixed issue when modifying/deleting exceptions of recurring events
- fixed major cache miss issue leading to slow Outlook resynchronizations
- fixed major memory corruption issue when Outlook was saving "messages"
- fixed filtering of sql contact entries when using dynamic domains (#2269)
- sogo.conf can now be used by all tools (#2226)
- SOPE: fixed handling of sieve capabilities after starttls (#2132)
- OpenChange: fixed 'stuck email' problem when sending a mail
- OpenChange NTLMAuthHandler: avoid tightloop when samba isn't available.
- OpenChange NTLMAuthHandler: avoid crash while parsing cookies
- OpenChange ocsmanager: a LOT of fixes, see git log
2.0.4b (2013-02-04)
------------------

View File

@ -0,0 +1,50 @@
//
// BSONCodec.h
// BSON Codec for Objective-C.
//
// Created by Martin Kou on 8/17/10.
// MIT License, see LICENSE file for details.
//
#import <Foundation/Foundation.h>
#import <stdint.h>
@protocol BSONCoding
- (uint8_t) BSONTypeID;
- (NSData *) BSONEncode;
- (NSData *) BSONRepresentation;
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) typeID;
@end
@protocol BSONObjectCoding
- (id) initWithBSONDictionary: (NSDictionary *) data;
- (NSDictionary *) BSONDictionary;
@end
@interface NSObject (BSONObjectCoding)
- (NSData *) BSONEncode;
- (NSData *) BSONRepresentation;
@end
@interface NSDictionary (BSON) <BSONCoding>
@end
@interface NSData (BSON) <BSONCoding>
- (NSDictionary *) BSONValue;
@end
@interface NSNumber (BSON) <BSONCoding>
@end
@interface NSString (BSON) <BSONCoding>
@end
@interface NSArray (BSON) <BSONCoding>
@end
@interface NSNull (BSON) <BSONCoding>
@end
@interface NSCalendarDate (BSON) <BSONCoding>
@end

View File

@ -0,0 +1,585 @@
//
// BSONCodec.m
// BSON Codec for Objective-C.
//
// Created by Martin Kou on 8/17/10.
// MIT License, see LICENSE file for details.
//
#import "BSONCodec.h"
#import <ctype.h>
#import <string.h>
#import <objc/objc.h>
#define BSONTYPE(tag,className) [className class], [NSNumber numberWithChar: (tag)]
#ifndef objc_msgSend
#define objc_msgSend(obj, sel, ...) \
objc_msg_lookup(obj, sel)(obj, sel, ## __VA_ARGS__)
#endif
static NSDictionary *BSONTypes()
{
static NSDictionary *retval = nil;
if (retval == nil)
{
retval = [[NSDictionary dictionaryWithObjectsAndKeys:
BSONTYPE(0x01, NSNumber),
BSONTYPE(0x02, NSString),
BSONTYPE(0x03, NSDictionary),
BSONTYPE(0x04, NSArray),
BSONTYPE(0x05, NSData),
BSONTYPE(0x08, NSNumber),
BSONTYPE(0x0A, NSNull),
BSONTYPE(0x10, NSNumber),
BSONTYPE(0x11, NSCalendarDate),
BSONTYPE(0x12, NSNumber),
nil] retain];
}
return retval;
}
#define SWAP16(x) \
((uint16_t)((((uint16_t)(x) & 0xff00) >> 8) | \
(((uint16_t)(x) & 0x00ff) << 8)))
#define SWAP32(x) \
((uint32_t)((((uint32_t)(x) & 0xff000000) >> 24) | \
(((uint32_t)(x) & 0x00ff0000) >> 8) | \
(((uint32_t)(x) & 0x0000ff00) << 8) | \
(((uint32_t)(x) & 0x000000ff) << 24)))
#define SWAP64(x) \
((uint64_t)((((uint64_t)(x) & 0xff00000000000000ULL) >> 56) | \
(((uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \
(((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \
(((uint64_t)(x) & 0x000000ff00000000ULL) >> 8) | \
(((uint64_t)(x) & 0x00000000ff000000ULL) << 8) | \
(((uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \
(((uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \
(((uint64_t)(x) & 0x00000000000000ffULL) << 56)))
#if BYTE_ORDER == LITTLE_ENDIAN
#define BSONTOHOST16(x) (x)
#define BSONTOHOST32(x) (x)
#define BSONTOHOST64(x) (x)
#define HOSTTOBSON16(x) (x)
#define HOSTTOBSON32(x) (x)
#define HOSTTOBSON64(x) (x)
#elif BYTE_ORDER == BIG_ENDIAN
#define BSONTOHOST16(x) SWAP16(x)
#define BSONTOHOST32(x) SWAP32(x)
#define BSONTOHOST64(x) SWAP64(x)
#define HOSTTOBSON16(x) SWAP16(x)
#define HOSTTOBSON32(x) SWAP16(x)
#define HOSTTOBSON64(x) SWAP16(x)
#endif
#define CLASS_NAME_MARKER @"$$__CLASS_NAME__$$"
@implementation NSObject (BSONObjectCoding)
- (NSData *) BSONEncode
{
if (!class_conformsToProtocol([self class], @protocol(BSONObjectCoding)))
[NSException raise: NSInvalidArgumentException format: @"BSON encoding is only valid on objects conforming to the BSONObjectEncoding protocol."];
id <BSONObjectCoding> myself = (id <BSONObjectCoding>) self;
NSMutableDictionary *values = [[myself BSONDictionary] mutableCopy];
const char* className = class_getName([self class]);
[values setObject: [NSData dataWithBytes: (void *)className length: strlen(className)] forKey: CLASS_NAME_MARKER];
NSData *retval = [values BSONEncode];
[values release];
return retval;
}
- (NSData *) BSONRepresentation
{
return [self BSONEncode];
}
@end
@implementation NSDictionary (BSON)
- (uint8_t) BSONTypeID
{
return 0x03;
}
- (NSData *) BSONEncode
{
// Initialize the components structure.
NSMutableArray *components = [[NSMutableArray alloc] init];
NSMutableData *lengthData = [[NSMutableData alloc] initWithLength: 4];
[components addObject: lengthData];
[lengthData release];
NSMutableData *contentsData = [[NSMutableData alloc] init];
[components addObject: contentsData];
[contentsData release];
[components addObject: [NSData dataWithBytes: "\x00" length: 1]];
// Ensure ordered keys. not in BSON spec, but ensures all BSONRepresentations
// of the same dict will be the same.
NSMutableArray *keys = [[NSMutableArray alloc] init];
[keys addObjectsFromArray: [self allKeys]];
//[keys sortUsingSelector: @selector(caseInsensitiveCompare:)];
// Encode data.- (NSData *) BSONEncode;
uint8_t elementType = 0;
int i;
for (i = 0; i < [keys count]; i++)
{
NSString *key = [keys objectAtIndex: i];
NSObject *value = [self objectForKey: key];
if ([value respondsToSelector: @selector(BSONTypeID)])
elementType = [(id <BSONCoding>) value BSONTypeID];
else
elementType = 3;
[contentsData appendBytes: &elementType length: 1];
[contentsData appendData: [key dataUsingEncoding: NSUTF8StringEncoding]];
[contentsData appendBytes: "\x00" length: 1];
[contentsData appendData: [value BSONEncode]];
}
[keys release];
// Write length.
uint32_t *length = (uint32_t *)[lengthData mutableBytes];
*length = HOSTTOBSON32([contentsData length]) + 4 + 1;
// Assemble the output data.
NSMutableData *retval = [NSMutableData data];
for (i = 0; i < [components count]; i++)
[retval appendData: [components objectAtIndex: i]];
[components release];
return retval;
}
- (NSData *) BSONRepresentation
{
return [self BSONEncode];
}
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) t
{
const void *current = [data bytes];
if ((id)base != nil)
current = *base;
else
base = &current;
uint32_t length = BSONTOHOST32(*((uint32_t *)current));
const void *endPoint = current + length;
current += 4;
NSMutableDictionary *retval = [NSMutableDictionary dictionary];
while (current < endPoint - 1)
{
uint8_t typeID = *((uint8_t *)current);
current++;
char *utf8Key = (char *) current;
while (*((char *)current) != 0 && current < endPoint - 1)
current++;
current++;
NSString *key = [NSString stringWithUTF8String: utf8Key];
*base = current;
Class typeClass = [BSONTypes() objectForKey: [NSNumber numberWithChar: typeID]];
id value = objc_msgSend(typeClass, @selector(BSONFragment:at:ofType:), data, base, typeID);
current = *base;
[retval setObject: value forKey: key];
}
*base = current + 1;
// If the dictionary has a class name marker, then it is to be converted to an object.
if ([retval objectForKey: CLASS_NAME_MARKER] != nil)
{
NSData *classNameData = [retval objectForKey: CLASS_NAME_MARKER];
char *className = malloc([classNameData length] + 1);
memcpy(className, [classNameData bytes], [classNameData length]);
className[[classNameData length]] = 0;
Class targetClass = objc_getClass(className);
if (targetClass == nil)
[NSException raise: NSInvalidArgumentException format: @"Class %s found in incoming data is undefined.", className];
id obj = [[targetClass alloc] initWithBSONDictionary: retval];
return obj;
}
return retval;
}
@end
@implementation NSData (BSON)
- (uint8_t) BSONTypeID
{
return 0x05;
}
- (NSData *) BSONEncode
{
uint32_t length = HOSTTOBSON32([self length]);
NSMutableData *retval = [NSMutableData data];
[retval appendBytes: &length length: 4];
[retval appendBytes: "\x00" length: 1];
[retval appendData: self];
return retval;
}
- (NSData *) BSONRepresentation
{
return [self BSONEncode];
}
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) t
{
const void *current = [data bytes];
if ((id)base != nil)
current = *base;
else
base = &current;
uint32_t length = BSONTOHOST32(*((uint32_t *)current));
current += 4 + 1;
NSData *retval = [NSData dataWithBytes: current length: length];
current += length;
*base = current;
return retval;
}
- (NSDictionary *) BSONValue
{
return [NSDictionary BSONFragment: self at: NULL ofType: 0x03];
}
@end
@implementation NSNumber (BSON)
- (uint8_t) BSONTypeID
{
const char encoding = tolower(*([self objCType]));
switch (encoding) {
case 'f':
case 'd': return 0x01;
case 'b': return 0x08;
case 'c':
case 's': return 0x10;
case 'i':
// Ok, if you're running Objective-C on 16-bit platforms...
// Then YOU have issues.
// So, yeah, we won't handle that case.
if (sizeof(int) == 4)
return 0x10;
else if (sizeof(int) == 8)
return 0x12;
case 'l':
if (sizeof(long) == 4)
return 0x10;
else if (sizeof(long) == 8)
return 0x12;
case 'q': return 0x12;
default:
[NSException raise: NSInvalidArgumentException format: @"%@::%s - invalid encoding type '%c'", [self class], _cmd, encoding];
}
return 0;
}
- (NSData *) BSONEncode
{
const char encoding = *([self objCType]);
if (encoding == 'd' || encoding == 'D')
{
double value = [self doubleValue];
return [NSData dataWithBytes: &value length: 8];
}
if (encoding == 'f' || encoding == 'F')
{
double value = [self floatValue];
return [NSData dataWithBytes: &value length: 8];
}
if (encoding == 'b' || encoding == 'B')
{
char value = [self boolValue];
return [NSData dataWithBytes: &value length: 1];
}
if (encoding == 'c' || encoding == 'C')
{
int32_t value = [self charValue];
value = HOSTTOBSON32(value);
return [NSData dataWithBytes: &value length: 4];
}
if (encoding == 's' || encoding == 'S')
{
int32_t value = [self shortValue];
value = HOSTTOBSON32(value);
return [NSData dataWithBytes: &value length: 4];
}
if (encoding == 'i' || encoding == 'I')
{
int value = [self intValue];
if (sizeof(int) == 4)
value = HOSTTOBSON32(value);
else if (sizeof(int) == 8)
value = HOSTTOBSON64(value);
return [NSData dataWithBytes: &value length: sizeof(int)];
}
if (encoding == 'l' || encoding == 'L')
{
long value = [self longValue];
if (sizeof(long) == 4)
value = HOSTTOBSON32(value);
else if (sizeof(long) == 8)
value = HOSTTOBSON64(value);
return [NSData dataWithBytes: &value length: sizeof(long)];
}
if (encoding == 'q')
{
long long value = HOSTTOBSON64([self longLongValue]);
return [NSData dataWithBytes: &value length: 8];
}
if (encoding == 'Q')
{
long long value = HOSTTOBSON64([self unsignedLongLongValue]);
return [NSData dataWithBytes: &value length: 8];
}
[NSException raise: NSInvalidArgumentException format: @"%@::%s - invalid encoding type '%c'", [self class], _cmd, encoding];
return nil;
}
- (NSData *) BSONRepresentation
{
return [self BSONEncode];
}
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) t
{
if (t == 0x01)
{
// #5: LLVM GCC requires double pointers to have a certain alignment in ARM CPUs.
// So we can't just read the double off directly from the data - need to copy it.
double value;
memcpy(&value, *base, sizeof(double));
*base += 8;
return [NSNumber numberWithDouble: value];
}
if (t == 0x08)
{
char value = ((char *) *base)[0];
*base += 1;
return [NSNumber numberWithBool: value];
}
if (t == 0x10)
{
int32_t value = BSONTOHOST32(((int32_t *) *base)[0]);
*base += 4;
if (sizeof(int) == 4)
return [NSNumber numberWithInt: value];
return [NSNumber numberWithLong: value];
}
if (t == 0x12)
{
int64_t value = BSONTOHOST64(((int64_t *) *base)[0]);
*base += 8;
return [NSNumber numberWithUnsignedLongLong: value];
}
return nil;
}
@end
@implementation NSString (BSON)
- (uint8_t) BSONTypeID
{
return 0x02;
}
- (NSData *) BSONEncode
{
NSData *utf8Data = [self dataUsingEncoding: NSUTF8StringEncoding];
uint32_t length = HOSTTOBSON32([utf8Data length] + 1);
NSMutableData *retval = [NSMutableData data];
[retval appendBytes: &length length: 4];
[retval appendData: utf8Data];
[retval appendBytes: "\x00" length: 1];
return retval;
}
- (NSData *) BSONRepresentation
{
return [self BSONEncode];
}
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) typeID
{
uint32_t length = BSONTOHOST32(((const uint32_t *) *base)[0]);
*base += 4;
const char *utf8Str = (const char *) *base;
*base += length;
return [NSString stringWithUTF8String: utf8Str];
}
@end
@implementation NSArray (BSON)
- (uint8_t) BSONTypeID
{
return 0x04;
}
- (NSData *) BSONEncode
{
// Initialize the components structure.
NSMutableArray *components = [[NSMutableArray alloc] init];
NSMutableData *lengthData = [[NSMutableData alloc] initWithLength: 4];
[components addObject: lengthData];
[lengthData release];
NSMutableData *contentsData = [[NSMutableData alloc] init];
[components addObject: contentsData];
[contentsData release];
[components addObject: [NSData dataWithBytes: "\x00" length: 1]];
// Encode data.
uint8_t elementType = 0;
int i, count = [self count];
for (i = 0 ; i < count ; i++)
{
NSObject *value = [self objectAtIndex: i];
if ([value respondsToSelector: @selector(BSONTypeID)])
elementType = [(id <BSONCoding>) value BSONTypeID];
else
elementType = 3;
[contentsData appendBytes: &elementType length: 1];
[contentsData appendData: [[NSString stringWithFormat: @"%d", i] dataUsingEncoding: NSUTF8StringEncoding]];
[contentsData appendBytes: "\x00" length: 1];
[contentsData appendData: [value BSONEncode]];
}
// Write length.
uint32_t *length = (uint32_t *)[lengthData mutableBytes];
*length = HOSTTOBSON32([contentsData length]) + 4 + 1;
// Assemble the output data.
NSMutableData *retval = [NSMutableData data];
for (i = 0; i < [components count]; i++)
[retval appendData: [components objectAtIndex: i]];
[components release];
return retval;
}
- (NSData *) BSONRepresentation
{
return [self BSONEncode];
}
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) typeID
{
NSDictionary *tmp = [NSDictionary BSONFragment: data at: base ofType: 0x03];
NSMutableArray *retval = [NSMutableArray arrayWithCapacity: [tmp count]];
int i;
for (i = 0; i < [tmp count]; i++)
[retval addObject: [tmp objectForKey: [NSString stringWithFormat: @"%d", i]]];
return retval;
}
@end
@implementation NSNull (BSON)
- (uint8_t) BSONTypeID
{
return 0x0a;
}
- (NSData *) BSONEncode
{
return [NSData data];
}
- (NSData *) BSONRepresentation
{
return [self BSONEncode];
}
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) typeID
{
return [NSNull null];
}
@end
@implementation NSCalendarDate (BSON)
- (uint8_t) BSONTypeID
{
return 0x11;
}
- (NSData *) BSONEncode
{
NSString *v;
v = [self descriptionWithCalendarFormat: @"%Y-%m-%d %H:%M:%S %Z"
locale: nil];
return [v BSONEncode];
}
- (NSData *) BSONRepresentation
{
return [self BSONEncode];
}
+ (id) BSONFragment: (NSData *) data at: (const void **) base ofType: (uint8_t) typeID
{
NSString *v;
v = [NSString BSONFragment: data at: base ofType: 0x02];
return [NSCalendarDate dateWithString: v
calendarFormat: @"%Y-%m-%d %H:%M:%S %Z"];
}
@end

View File

@ -46,12 +46,12 @@
NSDictionary *properties;
BOOL rc;
[self logWithFormat: @"evaluating object '%@'", object];
//[self logWithFormat: @"evaluating object '%@'", object];
properties = [object properties];
rc = [self _evaluateSOGoMAPIDBObject: properties];
[self logWithFormat: @" evaluation result: %d", rc];
//[self logWithFormat: @" evaluation result: %d", rc];
return rc;
}
@ -150,9 +150,9 @@ typedef BOOL (*EOComparator) (id, SEL, id);
rc = ((isZero && (intValue & mask) == 0)
|| (!isZero && (intValue & mask) != 0));
[self logWithFormat: @"evaluation of bitmask qualifier:"
@" (%.8x & %.8x) %s 0: %d",
intValue, mask, (isZero ? "==" : "!="), rc];
//[self logWithFormat: @"evaluation of bitmask qualifier:"
// @" (%.8x & %.8x) %s 0: %d",
// intValue, mask, (isZero ? "==" : "!="), rc];
return rc;
}

View File

@ -79,7 +79,7 @@
@" c_lastmodified INT NOT NULL,"
@" c_version INT NOT NULL DEFAULT 0,"
@" c_deleted TINYINT NOT NULL DEFAULT 0,"
@" c_content TEXT)");
@" c_content LONGTEXT)");
return [NSString stringWithFormat: sqlFolderFormat, tableName];
}

View File

@ -7,8 +7,6 @@ include ../Version
BACKEND_VERSION = 1.0.0
UNRTF_VERSION = 0.21.2
### bootstrap library
MAPISTORESOGO = MAPIStoreSOGo
LIBRARY_NAME = $(MAPISTORESOGO)
@ -24,8 +22,6 @@ BUNDLE_NAME = $(SOGOBACKEND)
BUNDLE_EXTENSION = .MAPIStore
BUNDLE_INSTALL_DIR = $(SOGO_LIBDIR)
UNRTF_DIR = unrtf-$(UNRTF_VERSION)
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)
@ -37,8 +33,6 @@ all::
SAMBA_PRIVATE_DIR = $(shell $(PYTHON) ./samba-get-config.py "private dir")
$(SOGOBACKEND)_SUBPROJECTS += $(UNRTF_DIR)/src
$(SOGOBACKEND)_PRINCIPAL_CLASS = MAPIApplication
$(SOGOBACKEND)_OBJC_FILES += \
@ -133,32 +127,14 @@ $(SOGOBACKEND)_OBJC_FILES += \
\
EOQualifier+MAPI.m \
\
EOBitmaskQualifier.m
EOBitmaskQualifier.m \
\
BSONCodec.m \
RTFHandler.m
$(SOGOBACKEND)_RESOURCE_FILES += \
product.plist \
$(UNRTF_DIR)/charmaps/SYMBOL.charmap \
$(UNRTF_DIR)/outputs/html.conf
### unrtf
all:: $(UNRTF_DIR)/config.h $(UNRTF_DIR)/src/GNUmakefile
$(UNRTF_DIR): $(UNRTF_DIR).tar.gz $(UNRTF_DIR).diff
@echo " Extracting and patching $(UNRTF_DIR)..."
@rm -rf $(UNRTF_DIR)
@$(TAR) -xvzf $< > /dev/null
@(cd $(UNRTF_DIR) && patch -p1 < ../$(UNRTF_DIR).diff) > /dev/null
@touch $(UNRTF_DIR)
$(UNRTF_DIR)-stamp: $(UNRTF_DIR)
@touch $@
$(UNRTF_DIR)/config.h: $(UNRTF_DIR)-stamp unrtf_config_h
@cp unrtf_config_h $(UNRTF_DIR)/config.h
$(UNRTF_DIR)/src/GNUmakefile: $(UNRTF_DIR)-stamp GNUmakefile.unrtf
@cp GNUmakefile.unrtf $@
product.plist
### pl reader
PLREADER_TOOL = plreader
@ -210,7 +186,6 @@ ADDITIONAL_INCLUDE_DIRS += \
-DSAMBA_PRIVATE_DIR=@"\"$(SAMBA_PRIVATE_DIR)\"" \
$(LIBMAPI_CFLAGS) \
$(LIBMAPISTORE_CFLAGS) \
-I$(UNRTF_DIR)/src \
-I../SoObjects -I../SOPE \
-DBACKEND_BUNDLE_NAME="@\"$(BUNDLE_NAME)$(BUNDLE_EXTENSION)\"" \
-DSOGO_BUNDLES_DIR="@\"$(BUNDLE_INSTALL_DIR)\""

View File

@ -1,34 +0,0 @@
# -*-makefile-*-
# GNUstep makefile
include $(GNUSTEP_MAKEFILES)/common.make
UNRTF = unrtf
SUBPROJECT_NAME = $(UNRTF)
$(UNRTF)_C_FILES = \
attr.c \
convert.c \
error.c \
hash.c \
malloc.c \
my_iconv.c \
output.c \
parse.c \
unicode.c \
user.c \
util.c \
word.c
$(UNRTF)_CFLAGS = -DHAVE_CONFIG_H=1 -I. -I../
# Option include to set any additional variables
-include GNUmakefile.preamble
# Include in the rules for making libraries
include $(GNUSTEP_MAKEFILES)/subproject.make
# Option include to define any additional rules
-include GNUmakefile.postamble

View File

@ -161,7 +161,7 @@
return [self getNo: data inMemCtx: memCtx];
}
- (void) save
- (void) save: (TALLOC_CTX *) memCtx
{
// (gdb) po embeddedMessage->properties
// 2442592320 = "2012-07-11 22:30:00 +0000";
@ -208,7 +208,8 @@
[[container event] updateFromMAPIProperties: properties
inUserContext: [self userContext]
withActiveUser: activeUser];
withActiveUser: activeUser
inMemCtx: memCtx];
}
@end

View File

@ -63,7 +63,7 @@
SOGoAppointmentObject *newEntry;
NSString *name;
[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
//[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
name = [NSString stringWithFormat: @"%@.ics",
[SOGoObject globallyUniqueObjectId]];

View File

@ -200,6 +200,7 @@ static Class NSArrayK;
- (void) dealloc
{
//NSLog(@"MAPIStoreCalendarMessage: -dealloc (%p)", self);
[calendar release];
[super dealloc];
}
@ -417,7 +418,7 @@ static Class NSArrayK;
return [self getYes: data inMemCtx: memCtx];
}
- (NSString *) _uidFromGlobalObjectId
- (NSString *) _uidFromGlobalObjectId: (TALLOC_CTX *) memCtx
{
NSData *objectId;
NSString *uid = nil;
@ -431,7 +432,7 @@ static Class NSArrayK;
if (objectId)
{
length = [objectId length];
bytesDup = talloc_array (NULL, char, length + 1);
bytesDup = talloc_array (memCtx, char, length + 1);
memcpy (bytesDup, [objectId bytes], length);
bytesDup[length] = 0;
uidStart = bytesDup + length - 1;
@ -596,7 +597,7 @@ static Class NSArrayK;
}
}
- (void) save
- (void) save: (TALLOC_CTX *) memCtx
{
// iCalCalendar *vCalendar;
// NSCalendarDate *now;
@ -608,7 +609,7 @@ static Class NSArrayK;
if (isNew)
{
uid = [self _uidFromGlobalObjectId];
uid = [self _uidFromGlobalObjectId: memCtx];
if (uid)
{
/* Hack required because of what's explained in oxocal 3.1.4.7.1:
@ -650,12 +651,12 @@ static Class NSArrayK;
activeUser = [[self context] activeUser];
[masterEvent updateFromMAPIProperties: properties
inUserContext: [self userContext]
withActiveUser: activeUser];
withActiveUser: activeUser
inMemCtx: memCtx];
[self _updateAttachedEvents];
[[self userContext] activateWithUser: activeUser];
[sogoObject updateContentWithCalendar: calendar
fromRequest: nil];
[self updateVersions];
}

View File

@ -224,7 +224,7 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
NSURL *baseURL;
int rc = MAPISTORE_ERR_NOT_FOUND;
NSLog (@"METHOD '%s' (%d) -- uri: '%s'", __FUNCTION__, __LINE__, newUri);
//NSLog (@"METHOD '%s' (%d) -- uri: '%s'", __FUNCTION__, __LINE__, newUri);
context = nil;
@ -532,8 +532,8 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
mappingId = [mapping idFromURL: childURL];
if (mappingId == NSNotFound)
{
[self warnWithFormat: @"no id exist yet for '%@', requesting one...",
childURL];
//[self warnWithFormat: @"no id exist yet for '%@', requesting one...",
// childURL];
openchangedb_get_new_folderID (connInfo->oc_ctx, &mappingId);
[mapping registerURL: childURL withID: mappingId];
contextId = 0;

View File

@ -236,7 +236,7 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
messageKeys = [self messageKeys];
date = [NSCalendarDate date];
[self logWithFormat: @"current date: %@", date];
//[self logWithFormat: @"current date: %@", date];
max = [messageKeys count];
for (count = 0; count < max; count++)
@ -245,7 +245,7 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
fileDate = [msg lastModificationTime];
if ([date laterDate: fileDate] == fileDate)
{
[self logWithFormat: @"current date: %@", date];
//[self logWithFormat: @"current date: %@", date];
date = fileDate;
}

View File

@ -135,7 +135,7 @@
[super addProperties: newNewProperties];
}
- (void) save
- (void) save: (TALLOC_CTX *) memCtx
{
uint64_t newVersion;

View File

@ -65,7 +65,7 @@ static Class MAPIStoreDBMessageK = Nil;
cVersion = exchange_globcnt (([value unsignedLongLongValue] >> 16)
& 0x0000ffffffffffffLL);
version = [NSNumber numberWithUnsignedLongLong: cVersion];
[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
//[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
[self logWithFormat: @" version: %.16lx", cVersion];
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"version"
operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo

View File

@ -146,7 +146,7 @@ static Class MAPIStoreAttachmentK;
return ULLONG_MAX;
}
- (void) save
- (void) save: (TALLOC_CTX *) memCtx
{
[self subclassResponsibility: _cmd];
}

View File

@ -51,7 +51,7 @@
return [self getYes: data inMemCtx: memCtx];
}
- (enum mapistore_error) saveMessage
- (enum mapistore_error) saveMessage: (TALLOC_CTX *) memCtx;
{
enum mapistore_error rc;
MAPIStoreContext *context;
@ -60,7 +60,7 @@
context = [self context];
ownerUser = [[self userContext] sogoUser];
if ([[context activeUser] isEqual: ownerUser])
rc = [super saveMessage];
rc = [super saveMessage: memCtx];
else
rc = MAPISTORE_ERR_DENIED;

View File

@ -180,7 +180,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
- (void) dealloc
{
[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
//[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
// [messageKeys release];
// [faiMessageKeys release];
@ -366,7 +366,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
MAPIStoreMapping *mapping;
NSString *childURL;
[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
//[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
mapping = [self mapping];
childURL = [mapping urlFromID: fid];
@ -393,7 +393,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
MAPIStoreFolder *childFolder;
SOGoUser *ownerUser;
[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
//[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
ownerUser = [[self userContext] sogoUser];
if ([[context activeUser] isEqual: ownerUser]
@ -450,8 +450,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
NSArray *keys;
int rc = MAPISTORE_SUCCESS;
[self logWithFormat: @"METHOD '%s' (%d) -- tableType: %d",
__FUNCTION__, __LINE__, tableType];
//[self logWithFormat: @"METHOD '%s' (%d) -- tableType: %d",
//__FUNCTION__, __LINE__, tableType];
if (tableType == MAPISTORE_MESSAGE_TABLE)
keys = [self messageKeys];
@ -513,8 +513,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
MAPIStoreMapping *mapping;
SOGoUser *ownerUser;
[self logWithFormat: @"METHOD '%s' -- mid: 0x%.16llx associated: %d",
__FUNCTION__, mid, isAssociated];
//[self logWithFormat: @"METHOD '%s' -- mid: 0x%.16llx associated: %d",
// __FUNCTION__, mid, isAssociated];
context = [self context];
ownerUser = [[self userContext] sogoUser];
@ -699,7 +699,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
if (rc != MAPISTORE_SUCCESS)
goto end;
}
[destMsg save];
[destMsg save: memCtx];
if (!wantCopy)
rc = [sourceFolder deleteMessageWithMID: srcMid andFlags: 0];
@ -844,7 +844,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
[mapping registerURL: [targetMessage url]
withID: fmid];
}
[targetMessage save];
[targetMessage save: memCtx];
}
[pool release];
@ -865,7 +865,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
[mapping registerURL: [targetMessage url]
withID: fmid];
}
[targetMessage save];
[targetMessage save: memCtx];
}
[pool release];

View File

@ -92,8 +92,8 @@
value = NSObjectFromMAPISPropValue (&res->lpProp);
lastModified = [(MAPIStoreGCSFolder *)
container lastModifiedFromMessageChangeNumber: value];
[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
[self logWithFormat: @" c_lastmodified: %@", lastModified];
//[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
//[self logWithFormat: @" c_lastmodified: %@", lastModified];
if (lastModified)
{
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"c_lastmodified"

View File

@ -390,7 +390,7 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
else
value = [NSDate date];
[self logWithFormat: @"lastMessageModificationTime: %@", value];
//[self logWithFormat: @"lastMessageModificationTime: %@", value];
return value;
}
@ -613,8 +613,8 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
[messageEntry setObject: modseq forKey: @"modseq"];
[messageEntry setObject: changeNumber forKey: @"version"];
[self logWithFormat: @"added message entry for uid %@, modseq %@,"
@" version %@", uid, modseq, changeNumber];
//[self logWithFormat: @"added message entry for uid %@, modseq %@,"
// @" version %@", uid, modseq, changeNumber];
changeKey = [self getReplicaKeyFromGlobCnt: newChangeNum >> 16];
[self _setChangeKey: changeKey forMessageEntry: messageEntry];
@ -796,7 +796,7 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
if (tableType == MAPISTORE_MESSAGE_TABLE)
{
changeNumber = [NSString stringWithUnsignedLongLong: changeNum];
changeNumber = [NSString stringWithFormat: @"0x%.16llx", changeNum];
modseq = [[self modseqFromMessageChangeNumber: changeNumber]
unsignedLongLongValue];
if (modseq > 0)

View File

@ -1576,7 +1576,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
bodySetup = YES;
}
- (void) save
- (void) save: (TALLOC_CTX *) memCtx
{
NSNumber *value;

View File

@ -120,7 +120,7 @@ static Class MAPIStoreMailMessageK, NSDataK, NSStringK;
case PidLidAppointmentStartWhole:
case PidLidAppointmentEndWhole:
case PidLidRecurring:
[self logWithFormat: @"apt restriction on mail folder?"];
//[self logWithFormat: @"apt restriction on mail folder?"];
rc = MAPIRestrictionStateAlwaysFalse;
break;
@ -155,10 +155,11 @@ static Class MAPIStoreMailMessageK, NSDataK, NSStringK;
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]];
//[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
//[self logWithFormat: @" modseq: %.16lx", [modseq unsignedLongLongValue]];
if (modseq)
modseq = [NSNumber numberWithUnsignedLongLong:
[modseq unsignedLongLongValue] + 1];
@ -316,7 +317,7 @@ static Class MAPIStoreMailMessageK, NSDataK, NSStringK;
ASSIGN (sortOrderings, newSortOrderings);
else
ASSIGN (sortOrderings, [NSArray arrayWithObject: @"ARRIVAL"]);
[self logWithFormat: @"new sort orderings: '%@'", sortOrderings];
//[self logWithFormat: @"new sort orderings: '%@'", sortOrderings];
}
else
ASSIGN (sortOrderings, [NSArray arrayWithObject: @"ARRIVAL"]);

View File

@ -904,7 +904,7 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS
return MAPISTORE_SUCCESS;
}
- (void) save
- (void) save: (TALLOC_CTX *) memCtx
{
NSString *folderName, *flag, *newIdString, *messageKey;
NSData *changeKey, *messageData;
@ -943,7 +943,14 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS
[mapping registerURL: [self url] withID: mid];
/* synchronise the cache and update the change key with the one provided
by the client */
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)

View File

@ -64,7 +64,7 @@
- (int) getAttachmentTable: (MAPIStoreAttachmentTable **) tablePtr
andRowCount: (uint32_t *) countPtr;
- (int) setReadFlag: (uint8_t) flag;
- (enum mapistore_error) saveMessage;
- (enum mapistore_error) saveMessage: (TALLOC_CTX *) memCtx;
- (NSArray *) activeContainerMessageTables;
@ -74,7 +74,7 @@
- (void) copyToMessage: (MAPIStoreMessage *) newMessage inMemCtx: (TALLOC_CTX *) memCtx;
/* subclasses */
- (void) save;
- (void) save: (TALLOC_CTX *) memCtx;
/* attachments (subclasses) */
- (MAPIStoreAttachment *) createAttachment;

View File

@ -45,11 +45,10 @@
#import "NSData+MAPIStore.h"
#import "NSObject+MAPIStore.h"
#import "NSString+MAPIStore.h"
#import "RTFHandler.h"
#import "MAPIStoreMessage.h"
#include <unrtf.h>
#undef DEBUG
#include <stdbool.h>
#include <gen_ndr/exchange.h>
@ -60,17 +59,6 @@ static Class MAPIStoreFolderK, MAPIStoreEmbeddedMessageK;
static NSString *resourcesDir = nil;
/* rtf conversion via unrtf */
static int
unrtf_data_output (void *data, const char *str, size_t str_len)
{
NSMutableData *rtfData = data;
[rtfData appendBytes: str length: str_len];
return str_len;
}
static NSData *
uncompressRTF (NSData *compressedRTF)
{
@ -97,22 +85,17 @@ rtf2html (NSData *compressedRTF)
{
NSData *rtf;
NSMutableData *html = nil;
int rc;
struct unRTFOptions unrtfOptions;
rtf = uncompressRTF (compressedRTF);
if (rtf)
{
html = [NSMutableData data];
memset (&unrtfOptions, 0, sizeof (struct unRTFOptions));
unrtf_set_output_device (&unrtfOptions, unrtf_data_output, html);
unrtfOptions.config_directory = [resourcesDir UTF8String];
unrtfOptions.output_format = "html";
unrtfOptions.nopict_mode = YES;
rc = unrtf_convert_from_string (&unrtfOptions,
[rtf bytes], [rtf length]);
if (!rc)
html = nil;
//html = [NSMutableData data];
RTFHandler *handler;
handler = [[RTFHandler alloc] initWithData: rtf];
AUTORELEASE(handler);
html = [handler parse];
}
return html;
@ -139,7 +122,7 @@ rtf2html (NSData *compressedRTF)
- (id) init
{
[self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self];
//[self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self];
if ((self = [super init]))
{
@ -153,7 +136,7 @@ rtf2html (NSData *compressedRTF)
- (void) dealloc
{
[self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self];
//[self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self];
[activeUserRoles release];
[attachmentKeys release];
[attachmentParts release];
@ -260,7 +243,7 @@ rtf2html (NSData *compressedRTF)
struct mapistore_message_recipient *recipient;
NSUInteger count;
[self logWithFormat: @"METHOD '%s'", __FUNCTION__];
//[self logWithFormat: @"METHOD '%s'", __FUNCTION__];
recipients = [NSMutableDictionary new];
recipientProperties = [NSDictionary dictionaryWithObject: recipients
@ -450,7 +433,7 @@ rtf2html (NSData *compressedRTF)
NSString *key;
MAPIStoreAttachment *attachment, *newAttachment;
[self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self];
//[self logWithFormat: @"METHOD '%s' (%d) (%d)", __FUNCTION__, __LINE__, self];
//memCtx = talloc_zero (NULL, TALLOC_CTX);
@ -477,7 +460,7 @@ rtf2html (NSData *compressedRTF)
//talloc_free (memCtx);
}
- (enum mapistore_error) saveMessage
- (enum mapistore_error) saveMessage: (TALLOC_CTX *) memCtx
{
enum mapistore_error rc;
NSArray *containerTables;
@ -490,7 +473,7 @@ rtf2html (NSData *compressedRTF)
BOOL userIsOwner;
MAPIStoreMessage *mainMessage;
[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
//[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
context = [self context];
ownerUser = [[self userContext] sogoUser];
@ -518,7 +501,7 @@ rtf2html (NSData *compressedRTF)
/* folder modified */
notif_parameters
= talloc_zero(NULL, struct mapistore_object_notification_parameters);
= talloc_zero(memCtx, struct mapistore_object_notification_parameters);
notif_parameters->object_id = folderId;
if (isNew)
{
@ -542,7 +525,7 @@ rtf2html (NSData *compressedRTF)
if (isNew)
{
notif_parameters
= talloc_zero(NULL,
= talloc_zero(memCtx,
struct mapistore_object_notification_parameters);
notif_parameters->object_id = [self objectId];
notif_parameters->folder_id = folderId;
@ -562,7 +545,7 @@ rtf2html (NSData *compressedRTF)
[[containerTables objectAtIndex: count] restrictedChildKeys];
}
[self save];
[self save: memCtx];
/* We make sure that any change-related properties are removes from the
properties dictionary, to make sure that related methods will be
invoked the next time they are requested. */
@ -937,7 +920,7 @@ rtf2html (NSData *compressedRTF)
return MAPISTORE_ERROR;
}
- (void) save
- (void) save: (TALLOC_CTX *) memCtx
{
[self subclassResponsibility: _cmd];
}

View File

@ -68,7 +68,7 @@ sogo_backend_atexit (void)
GSRegisterCurrentThread ();
pool = [NSAutoreleasePool new];
NSLog (@"allocated classes:\n%s", GSDebugAllocationList (YES));
//NSLog (@"allocated classes:\n%s", GSDebugAllocationList (YES));
[pool release];
GSUnregisterCurrentThread ();
}
@ -1024,7 +1024,7 @@ sogo_message_set_read_flag (void *message_object, uint8_t flag)
}
static enum mapistore_error
sogo_message_save (void *message_object)
sogo_message_save (void *message_object, TALLOC_CTX *mem_ctx)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
@ -1039,7 +1039,7 @@ sogo_message_save (void *message_object)
message = wrapper->instance;
GSRegisterCurrentThread ();
pool = [NSAutoreleasePool new];
rc = [message saveMessage];
rc = [message saveMessage: mem_ctx];
// [context tearDownRequest];
[pool release];
GSUnregisterCurrentThread ();
@ -1229,7 +1229,7 @@ sogo_table_set_restrictions (void *table_object, struct mapi_SRestriction *restr
GSRegisterCurrentThread ();
pool = [NSAutoreleasePool new];
[table setRestrictions: restrictions];
[table cleanupCaches];
//[table cleanupCaches];
rc = MAPISTORE_SUCCESS;
*table_status = TBLSTAT_COMPLETE;
[pool release];

View File

@ -375,12 +375,12 @@ static Class NSDataK, NSStringK;
- (void) setRestrictions: (const struct mapi_SRestriction *) res
{
EOQualifier *oldRestriction;
//EOQualifier *oldRestriction;
// [self logWithFormat: @"set restriction to (table type: %d): %@",
// type, MAPIStringForRestriction (res)];
oldRestriction = restriction;
//oldRestriction = restriction;
[restriction autorelease];
if (res)
restrictionState = [self evaluateRestriction: res
@ -396,11 +396,11 @@ static Class NSDataK, NSStringK;
// 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];
//if (restriction)
// [self logWithFormat: @"restriction set to EOQualifier: %@",
// restriction];
// else if (oldRestriction)
// [self logWithFormat: @"restriction unset (was %@)", oldRestriction];
}
- (MAPIRestrictionState) evaluateNotRestriction: (struct mapi_SNotRestriction *) res

View File

@ -52,9 +52,9 @@ static inline NSNumber *
MAPIPropertyKey (enum MAPITAGS propTag)
{
#if (GS_SIZEOF_LONG == 4)
return [NSNumber numberWithUnsignedLong: propTag];
return [NSString stringWithFormat: @"%ul", propTag];
#elif (GS_SIZEOF_INT == 4)
return [NSNumber numberWithUnsignedInt: propTag];
return [NSString stringWithFormat: @"%u", propTag];
#else
#error No suitable type for 4 bytes integers
#endif

View File

@ -342,7 +342,8 @@ MAPIStoreDumpMessageProperties (NSDictionary *properties)
{
NSNumber *key;
NSArray *allKeys;
NSUInteger keyAsInt, count, max;
NSUInteger count, max;
NSUInteger keyAsInt;
id value;
allKeys = [properties allKeys];
@ -351,7 +352,7 @@ MAPIStoreDumpMessageProperties (NSDictionary *properties)
NSLog (@"message properties (%d):", max);
value = [properties objectForKey: @"recipients"];
if (value)
if (value)
NSLog (@" recipients: %@", value);
for (count = 0; count < max; count++)
@ -363,7 +364,7 @@ MAPIStoreDumpMessageProperties (NSDictionary *properties)
value = [properties objectForKey: key];
NSLog (@" 0x%.4x: %@ (%@)",
keyAsInt, value,
NSStringFromClass ([value class]));
NSStringFromClass ([value class]));
}
}
}

View File

@ -20,6 +20,7 @@
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSCharacterSet.h>
#import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSMapTable.h>
@ -107,15 +108,17 @@ static NSMapTable *contextsTable = nil;
password = nil;
path = [NSString stringWithFormat: SAMBA_PRIVATE_DIR
@"/mapistore/%@/password", newUsername];
@"/mapistore/%@/password", newUsername];
content = [NSData dataWithContentsOfFile: path];
if (content)
{
password = [[NSString alloc] initWithData: content
encoding: NSUTF8StringEncoding];
encoding: NSUTF8StringEncoding];
[password autorelease];
password = [password stringByTrimmingCharactersInSet:
[NSCharacterSet characterSetWithCharactersInString: @"\r\n"]];
}
return password;

View File

@ -50,8 +50,7 @@ MAPIStoreTallocWrapperDestroy (void *data)
GSRegisterCurrentThread ();
pool = [NSAutoreleasePool new];
wrapper = data;
//NSLog (@"destroying wrapped object (wrapper: %p; object: %p)...\n", wrapper, wrapper->MAPIStoreSOGoObject);
NSLog (@"destroying wrapped object (wrapper: %p)", wrapper);
//NSLog (@"destroying wrapped object (wrapper: %p; object: %p (%@))...\n", wrapper, wrapper->instance, NSStringFromClass([wrapper->instance class]));
[wrapper->instance release];
[pool release];
GSUnregisterCurrentThread ();
@ -67,8 +66,7 @@ MAPIStoreTallocWrapperDestroy (void *data)
talloc_set_destructor ((void *) wrapper, MAPIStoreTallocWrapperDestroy);
wrapper->instance = self;
[self retain];
NSLog (@"returning wrapper: %p; object: %p", wrapper, self);
//NSLog (@"returning wrapper: %p; object: %p (%@)", wrapper, self, NSStringFromClass([self class]));
return wrapper;
}

View File

@ -33,6 +33,8 @@
#import <Foundation/NSValue.h>
#import <NGExtensions/NSNull+misc.h>
#import "BSONCodec.h"
const char *indentationStep = " ";
@interface NSObject (plext)
@ -142,41 +144,43 @@ const char *indentationStep = " ";
static void
OCDumpPListData (NSData *content)
{
NSDictionary *d;
NSPropertyListFormat format;
NSString *error = nil;
const char *formatName;
//NSDictionary *d;
//NSPropertyListFormat format;
//NSString *error = nil;
//const char *formatName;
d = [NSPropertyListSerialization propertyListFromData: content
mutabilityOption: NSPropertyListImmutable
format: &format
errorDescription: &error];
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";
}
//d = [NSPropertyListSerialization propertyListFromData: content
// mutabilityOption: NSPropertyListImmutable
// format: &format
// errorDescription: &error];
//d = [content BSONValue];
printf ("File format is: %s\n", formatName);
[d displayWithIndentation: 0];
printf ("\n");
}
else
printf ("an error occurred: %s\n", [error UTF8String]);
// 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]);
}

View File

@ -0,0 +1,132 @@
/*
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 <Foundation/NSArray.h>
#include <Foundation/NSData.h>
#include <Foundation/NSMapTable.h>
#include <Foundation/NSObject.h>
#include <Foundation/NSString.h>
//
//
//
@interface RTFHandler : NSObject
{
NSMapTable *_charsets;
NSMutableData *_html;
NSData *_data;
const char *_bytes;
int _current_pos;
int _len;
}
- (id) initWithData: (NSData *) theData;
- (NSMutableData *) parse;
@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;
}
@end
//
//
//
@interface RTFFontInfo : NSObject
{
@public
NSString *family;
NSString *charset;
NSString *name;
unsigned int pitch;
unsigned int index;
}
@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;
@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

View File

@ -0,0 +1,945 @@
/*
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 <Foundation/NSValue.h>
//
// Useful macros
//
#define ADVANCE _bytes++; _current_pos++;
#define REWIND _bytes--; _current_pos--;
//
// 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
{
RELEASE(a);
[super dealloc];
}
- (void) push: (id) theObject
{
[a addObject: theObject];
}
- (id) pop
{
id o = nil;
if ([a count])
{
o = AUTORELEASE([[a lastObject] retain]);
[a removeLastObject];
}
return o;
}
- (id) top
{
id o = nil;
if ([a count])
{
o = AUTORELEASE([[a lastObject] retain]);
}
return o;
}
@end
//
//
//
@implementation RTFFormattingOptions
@end
//
//
//
@implementation RTFFontInfo
- (id) init
{
if ((self = [super init]))
{
}
return self;
}
- (void) dealloc
{
RELEASE(family);
RELEASE(charset);
RELEASE(name);
[super dealloc];
}
@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);
}
@end
//
//
//
@implementation RTFColorDef
@end
//
//
//
@implementation RTFColorTable
- (id) init
{
if ((self = [super init]))
{
colorDefs = [[NSMutableArray alloc] init];
}
return self;
}
- (void) dealloc
{
RELEASE(colorDefs);
[super dealloc];
}
- (void) addColorDef: (RTFColorDef *) theColorDef
{
[colorDefs addObject: theColorDef];
}
- (RTFColorDef *) colorDefAtIndex: (unsigned int) theIndex
{
return [colorDefs objectAtIndex: theIndex];
}
@end
//
//
//
@implementation RTFHandler
- (id) initWithData: (NSData *) theData
{
if ((self = [super init]))
{
ASSIGN(_data, theData);
_bytes = (char *)[_data bytes];
_len = [_data length];
_current_pos = 0;
_charsets = NSCreateMapTable(NSObjectMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, 10);
NSMapInsert(_charsets, @"ansicpg1250", ansicpg1250);
NSMapInsert(_charsets, @"ansicpg1251", ansicpg1251);
NSMapInsert(_charsets, @"ansicpg1252", ansicpg1252);
NSMapInsert(_charsets, @"ansicpg1253", ansicpg1253);
NSMapInsert(_charsets, @"ansicpg1254", ansicpg1254);
NSMapInsert(_charsets, @"ansicpg1255", ansicpg1255);
NSMapInsert(_charsets, @"ansicpg1256", ansicpg1256);
NSMapInsert(_charsets, @"ansicpg1257", ansicpg1257);
NSMapInsert(_charsets, @"ansicpg1258", ansicpg1258);
NSMapInsert(_charsets, @"ansicpg874", ansicpg874);
}
return self;
}
- (void) dealloc
{
NSFreeMapTable(_charsets);
RELEASE(_data);
[super dealloc];
}
- (const char *) parseControlWord: (unsigned int *) len
{
const char *start, *end;
start = ADVANCE;
while (isalnum(*_bytes) || *_bytes == '-')
{
ADVANCE;
}
end = _bytes;
*len = end-start-1;
return start+1;
}
//
// {\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
{
NSMutableString *fontName;
RTFFontTable *fontTable;
RTFFontInfo *fontInfo;
unsigned int count;
fontTable = [[[RTFFontTable alloc] init] autorelease];
fontName = nil;
count = 0;
do
{
if (*_bytes == '{')
{
if (fontTable)
{
fontInfo = [[[RTFFontInfo alloc] init] autorelease];
fontName = [[[NSMutableString alloc] init] autorelease];
}
ADVANCE;
count++;
}
else if (*_bytes == '}')
{
if (fontTable) //&& ![NSAllMapTableValues(fontTable->fontInfos) containsObject: fontInfo])
{
ASSIGN(fontInfo->name, fontName);
[fontTable addFontInfo: fontInfo atIndex: fontInfo->index];
}
ADVANCE;
count--;
}
else if (*_bytes == '\\')
{
const char *cw;
unsigned int len;
NSString *s;
cw = [self parseControlWord: &len];
// Skip our control word
if (strncmp((const char*)cw, "fonttbl", len) == 0)
continue;
// We must at least parse <fontnum><fontfamily><fcharset>
s = [[NSString alloc] initWithBytesNoCopy: (void *)cw+1
length: len-1
encoding: NSASCIIStringEncoding
freeWhenDone: NO];
[s autorelease];
// If we got a fontnum, let's parse all three fields at once)
if (isdigit(*(cw+1)))
{
fontInfo->index = [s intValue];
// We now parse <fontfamily><fcharset>
cw = [self parseControlWord: &len];
fontInfo->family = [[NSString alloc] initWithBytesNoCopy: (void *)cw+1
length: len-1
encoding: NSASCIIStringEncoding
freeWhenDone: NO];
cw = [self parseControlWord: &len];
fontInfo->charset = [[NSString alloc] initWithBytesNoCopy: (void *)cw+1
length: len-1
encoding: NSASCIIStringEncoding
freeWhenDone: NO];
// We now skip everything until we find our final group closer ('}')
int cc = 1;
do
{
if (*_bytes == '{')
cc++;
if (*_bytes == '}')
cc--;
ADVANCE;
}
while (cc != 0);
// move back our buffer;
REWIND;
}
}
else
{
if (isalnum(*_bytes))
[fontName appendFormat: @"%c", *_bytes];
ADVANCE;
}
} while (count != 0);
return fontTable;
}
//
//
//
- (void) parseStyleSheet
{
unsigned int count;
count = 0;
do
{
if (*_bytes == '{')
{
count++;
}
else if (*_bytes == '}')
{
count--;
}
ADVANCE;
} while (count != 0);
}
//
//
//
- (void) parsePicture
{
// Do the same as -parseStyleSheet for now, that is, ignore everything.
[self parseStyleSheet];
}
//
//
//
- (NSMutableData *) parse
{
RTFFormattingOptions *formattingOptions;
RTFColorTable *colorTable;
RTFFontTable *fontTable;
RTFStack *stack;
unsigned short *charset;
char c;
stack = [[RTFStack alloc] init];
fontTable = nil;
colorTable = nil;
charset = NULL;
_html = [[NSMutableData alloc] init];
[_html appendBytes: "<html><meta charset='utf-8'><body>" length: 34];
// Check if we got RTF data
if (_len > 4 && strncmp((const char*)_bytes, "{\\rtf", 4) != 0)
return NO;
while (_current_pos < _len)
{
c = *_bytes;
// RTF control code
if (c == '\\')
{
unsigned int len;
const char *cw;
NSString *s;
if (*(_bytes+1) == '\'' && charset)
{
// A hexadecimal value, based on the specified character set (may be used to identify 8-bit values).
NSString *s;
NSData *d;
const char *b1, *b2;
unsigned short index;
ADVANCE;
ADVANCE;
b1 = ADVANCE;
b2 = ADVANCE;
index = (isdigit(*b1) ? *b1 - 48 : toupper(*b1) - 55) * 16;
index += (isdigit(*b2) ? *b2 - 48 : toupper(*b2) - 55);
s = [NSString stringWithCharacters: &(charset[index]) length: 1];
d = [s dataUsingEncoding: NSUTF8StringEncoding];
[_html appendData: d];
continue;
}
else if (*(_bytes+1) == '*')
{
while (*_bytes != '}')
{
ADVANCE;
}
continue;
}
cw = [self parseControlWord: &len];
s = [[NSString alloc] initWithBytesNoCopy: (void *)cw
length: len
encoding: NSASCIIStringEncoding
freeWhenDone: NO];
[s autorelease];
if (strncmp(cw, "ansicpg", 7) == 0)
{
charset = NSMapGet(_charsets, s);
}
else if (strncmp(cw, "fonttbl", 7) == 0)
{
// We rewind our buffer so we start at the beginning of {\fonttbl...
_bytes = cw-2;
_current_pos -= 10;
fontTable = [self parseFontTable];
// We go back 1 byte in order to end our section properly ('}' character
REWIND;
}
else if (strncmp(cw, "stylesheet", 10) == 0)
{
_bytes = cw-2;
_current_pos -= 13;
[self parseStyleSheet];
REWIND;
}
else if (strncmp(cw, "colortbl", 8) == 0)
{
colorTable = [self parseColorTable];
}
else if (strncmp(cw, "pict", 4) == 0)
{
_bytes = cw-2;
_current_pos -= 7;
[self parsePicture];
REWIND;
}
else if ([s isEqualToString: @"b"] && formattingOptions)
{
[_html appendBytes: "<b>" length: 3];
formattingOptions->bold = YES;
}
else if ([s isEqualToString: @"b0"] && formattingOptions)
{
[_html appendBytes: "</b>" length: 4];
formattingOptions->bold = NO;
}
else if ([s hasPrefix: @"cf"] && [s length] > 2)
{
RTFColorDef *colorDef;
int color_index;
char *v;
color_index = [[s substringFromIndex: 2] intValue];
if (!formattingOptions)
continue;
if (formattingOptions->color_index >= 0) // && color_index != formattingOptions->color_index)
{
[_html appendBytes: "</font>" length: 7];
}
formattingOptions->color_index = color_index;
colorDef = [colorTable colorDefAtIndex: color_index];
v = malloc(23*sizeof(char));
memset(v, 0, 23);
sprintf(v, "<font color=\"#%02x%02x%02x\">", colorDef->red, colorDef->green, colorDef->blue);
[_html appendBytes: v length: strlen(v)];
free(v);
}
else if ([s hasPrefix: @"fs"])
{
// ignore
}
else if ([s hasPrefix: @"fbidis"])
{
// ignore
}
else if ([s hasPrefix: @"fromhtml"])
{
// ignore
}
else if ([s hasPrefix: @"f"] && [s length] > 1)
{
RTFFontInfo *fontInfo;
int font_index;
font_index = [[s substringFromIndex: 1] intValue];
if (!formattingOptions)
continue;
if (formattingOptions->font_index >= 0 &&
font_index != formattingOptions->font_index)
{
[_html appendBytes: "</font>" length: 7];
}
formattingOptions->font_index = font_index;
fontInfo = [fontTable fontInfoAtIndex: font_index];
char *v = malloc(128*sizeof(char));
memset(v, 0, 128);
sprintf(v, "<font face=\"%s\">", [fontInfo->name UTF8String]);
[_html appendBytes: v length: strlen(v)];
free(v);
}
else if ([s isEqualToString: @"i"] && formattingOptions)
{
[_html appendBytes: "<i>" length: 3];
formattingOptions->italic = YES;
}
else if ([s isEqualToString: @"i0"] && formattingOptions)
{
[_html appendBytes: "</i>" length: 4];
formattingOptions->italic = NO;
}
else if ([s isEqualToString: @"tab"])
{
[_html appendBytes: "&nbsp;&nbsp;" length: 12];
}
else if ([s isEqualToString: @"softline"] || [s isEqualToString: @"par"])
{
[_html appendBytes: "<br>" length: 4];
}
else if ([s isEqualToString: @"strike"] && formattingOptions)
{
[_html appendBytes: "<strike>" length: 8];
formattingOptions->strikethrough = YES;
}
else if ([s isEqualToString: @"strike0"] && formattingOptions)
{
[_html appendBytes: "</strike>" length: 9];
formattingOptions->strikethrough = NO;
}
else if ([s hasPrefix: @"u"] && [s length] > 1 && isdigit([s characterAtIndex: 1]))
{
NSData *d;
unichar ch;
ch = (unichar)[[s substringFromIndex: 1] intValue];
s = [NSString stringWithCharacters: &ch length: 1];
d = [s dataUsingEncoding: NSUTF8StringEncoding];
[_html appendData: d];
}
else if ([s isEqualToString: @"ul"] && formattingOptions)
{
[_html appendBytes: "<u>" length: 3];
formattingOptions->underline = YES;
}
else if (([s isEqualToString: @"ul0"] || [s isEqualToString: @"ulnone"])
&& formattingOptions)
{
[_html appendBytes: "</u>" length: 4];
formattingOptions->underline = NO;
}
// 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.
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];
[stack push: formattingOptions];
ADVANCE;
}
else if (c == '}')
{
formattingOptions = [stack pop];
if (formattingOptions)
{
// Handle {\b bold} vs. \b bold \b0
if (formattingOptions->bold)
{
[_html appendBytes: "</b>" length: 4];
}
if (formattingOptions->italic)
{
[_html appendBytes: "</i>" length: 4];
}
if (formattingOptions->strikethrough)
{
[_html appendBytes: "</strike>" length: 9];
}
if (formattingOptions->underline)
{
[_html appendBytes: "</u>" length: 4];
}
if (formattingOptions->font_index >= 0)
{
[_html appendBytes: "</font>" length: 7];
}
if (formattingOptions->color_index >= 0)
{
[_html appendBytes: "</font>" length: 7];
}
}
formattingOptions = [stack top];
ADVANCE;
}
else
{
// We avoid appending NULL bytes
if (*_bytes)
[_html appendBytes: _bytes length: 1];
ADVANCE;
}
}
[_html appendBytes: "</body></html>" length: 14];
RELEASE(stack);
return AUTORELEASE(_html);
}
@end

View File

@ -46,6 +46,7 @@
#import "GCSSpecialQueries+OpenChange.h"
#import "MAPIStoreTypes.h"
#import "SOGoMAPIDBFolder.h"
#import "BSONCodec.h"
#import "SOGoMAPIDBObject.h"
@ -156,9 +157,9 @@ static EOAttribute *textColumn = nil;
- (void) setupFromRecord: (NSDictionary *) record
{
NSInteger intValue;
NSString *propsValue, *error;
NSString *propsValue;//, *error;
NSDictionary *newValues;
NSPropertyListFormat format;
//NSPropertyListFormat format;
objectType = [[record objectForKey: @"c_type"] intValue];
intValue = [[record objectForKey: @"c_creationdate"] intValue];
@ -174,13 +175,8 @@ static EOAttribute *textColumn = nil;
propsValue = [record objectForKey: @"c_content"];
if ([propsValue isNotNull])
{
newValues = [NSPropertyListSerialization propertyListFromData: [propsValue dataByDecodingBase64]
mutabilityOption: NSPropertyListMutableContainers
format: &format
errorDescription: &error];
newValues = [[propsValue dataByDecodingBase64] BSONValue];
[properties addEntriesFromDictionary: newValues];
// [properties addEntriesFromDictionary: [propsValue
// objectFromJSONString]];
}
else
[properties removeAllObjects];
@ -255,13 +251,13 @@ static EOAttribute *textColumn = nil;
className = @"MAPIStoreNotesMessage";
else
className = @"MAPIStoreDBMessage";
[self logWithFormat: @"PidTagMessageClass = '%@', returning '%@'",
mapiMsgClass, className];
//[self logWithFormat: @"PidTagMessageClass = '%@', returning '%@'",
// mapiMsgClass, className];
}
else
{
[self warnWithFormat: @"PidTagMessageClass is not set, falling back"
@" to 'MAPIStoreDBMessage'"];
//[self warnWithFormat: @"PidTagMessageClass is not set, falling back"
// @" to 'MAPIStoreDBMessage'"];
className = @"MAPIStoreDBMessage";
}
break;
@ -526,10 +522,7 @@ static EOAttribute *textColumn = nil;
if ([properties count] > 0)
{
content = [NSPropertyListSerialization
dataFromPropertyList: properties
format: plistFormat
errorDescription: NULL];
content = [properties BSONRepresentation];
propsValue = [adaptor formatValue: [content stringByEncodingBase64]
forAttribute: textColumn];
}

View File

@ -0,0 +1,84 @@
#!/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}

View File

@ -23,6 +23,8 @@
#ifndef ICALEVENT_MAPISTORE_H
#define ICALEVENT_MAPISTORE_H
#include <talloc.h>
#import <NGCards/iCalEvent.h>
@class MAPIStoreUserContext;
@ -34,8 +36,8 @@
- (void) updateFromMAPIProperties: (NSDictionary *) properties
inUserContext: (MAPIStoreUserContext *) userContext
withActiveUser: (SOGoUser *) activeUser;
withActiveUser: (SOGoUser *) activeUser
inMemCtx: (TALLOC_CTX *) memCtx;
@end
#endif /* ICALEVENT_MAPISTORE_H */

View File

@ -20,7 +20,6 @@
* Boston, MA 02111-1307, USA.
*/
#include <talloc.h>
#include <util/attr.h>
#import <Foundation/NSArray.h>
@ -75,16 +74,17 @@
@implementation iCalEvent (MAPIStoreProperties)
- (void) _setupEventRecurrence: (NSData *) mapiRecurrenceData
inMemCtx: (TALLOC_CTX *) memCtx
{
struct Binary_r *blob;
struct AppointmentRecurrencePattern *pattern;
blob = [mapiRecurrenceData asBinaryInMemCtx: NULL];
pattern = get_AppointmentRecurrencePattern (blob, blob);
blob = [mapiRecurrenceData asBinaryInMemCtx: memCtx];
pattern = get_AppointmentRecurrencePattern (memCtx, blob);
[(iCalCalendar *) parent
setupRecurrenceWithMasterEntity: self
fromRecurrencePattern: &pattern->RecurrencePattern];
talloc_free (blob);
//talloc_free (blob);
}
- (void) _setupEventAlarmFromProperties: (NSDictionary *) properties
@ -134,6 +134,7 @@
- (void) updateFromMAPIProperties: (NSDictionary *) properties
inUserContext: (MAPIStoreUserContext *) userContext
withActiveUser: (SOGoUser *) activeUser
inMemCtx: (TALLOC_CTX *) memCtx
{
BOOL isAllDay;
iCalDateTime *start, *end;
@ -328,7 +329,7 @@
value = [properties
objectForKey: MAPIPropertyKey (PidLidAppointmentRecur)];
if (value)
[self _setupEventRecurrence: value];
[self _setupEventRecurrence: value inMemCtx: memCtx];
/* alarm */
[self _setupEventAlarmFromProperties: properties];

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -1,75 +0,0 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <ctype.h> header file. */
#define HAVE_CTYPE_H 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#define HAVE_MALLOC 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `memset' function. */
#define HAVE_MEMSET 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdio.h> header file. */
#define HAVE_STDIO_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `strchr' function. */
#define HAVE_STRCHR 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the `strstr' function. */
#define HAVE_STRSTR 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Name of package */
#define PACKAGE "unrtf"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "bug-unrtf@gnu.org"
/* Define to the full name of this package. */
#define PACKAGE_NAME "unrtf"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "unrtf 0.21.2"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "unrtf"
/* Define to the version of this package. */
#define PACKAGE_VERSION "0.21.2"
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Version number of package */
#define VERSION "0.21.2"
/* Define to rpl_malloc if the replacement function should be used. */
/* #undef malloc */

View File

@ -0,0 +1,20 @@
# /etc/fail2ban/filter.d/sogo.conf
#
# Fail2Ban configuration file
# By Arnd Brandes
# SOGo
#
[Definition]
# Option: failregex
# Filter Ban in /var/log/sogo/sogo.log
# Note: the error log may contain multiple hosts, whereas the first one
# is the client and all others are poxys. We match the first one, only
failregex = Login from '<HOST>.*' for user '.*' might not have worked
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex =

View File

@ -0,0 +1,9 @@
[SOGo]
enabled = true
port = http,https
# in proxy-free setup this would be:
# port = 20000
filter = sogo
logpath = /var/log/sogo/sogo.log
maxretry = 5

View File

@ -2,7 +2,7 @@
import getopt
import imaplib
#import ldb
import ldb
import plistlib
import os
import re
@ -16,7 +16,7 @@ imapport = 143
sambaprivate = '/var/lib/samba/private'
mapistorefolder = "%s/mapistore" % (sambaprivate)
sogoSysDefaultsFile = "/etc/sogo/sogo.conf"
sogoUserDefaultsFile = "/home/sogo/GNUstep/Defaults/.GNUstepDefaults"
sogoUserDefaultsFile = os.path.expanduser("~sogo/GNUstep/Defaults/.GNUstepDefaults")
# - takes a username and optionally its password
# - removes the entry in samba's ldap tree via ldbedit (NOTYET)
@ -79,13 +79,15 @@ def main():
except (shutil.Error, OSError) as e:
print "Error during mapistoreCleanup, continuing: %s" % str(e)
# try:
# pass
# #ldbCleanup(sambaprivate, username)
# except ldb.LdbError as e:
# print "Error during ldbCleanup, continuing: %s" % str(e)
try:
ldbCleanup(sambaprivate, username)
except ldb.LdbError as e:
print "Error during ldbCleanup, continuing: %s" % str(e)
sqlCleanup(username)
try:
sqlCleanup(username)
except Exception as e:
print "Error during sqlCleanup, continuing: %s" % str(e)
def extractmb(si):
inparen = False
@ -135,6 +137,7 @@ def cleanupmb(mb, client):
print "mailbox '%s' coult NOT be deleted (code = '%s')" % (mb, code)
def imapCleanup(imaphost, imapport, username, userpass):
print "Starting IMAP cleanup"
client = imaplib.IMAP4(imaphost, imapport)
(code, data) = client.login(username, userpass)
if code != "OK":
@ -152,24 +155,43 @@ def imapCleanup(imaphost, imapport, username, userpass):
client.logout()
def mapistoreCleanup(mapistorefolder, username):
print "Starting MAPIstore cleanup"
# delete the user's folder under the mapistore and under mapistore/SOGo
shutil.rmtree("%s/%s" % (mapistorefolder, username), ignore_errors=True)
mapistoreUserDir = "%s/%s" % (mapistorefolder, username)
for dirpath, dirnames, filenames in os.walk(mapistoreUserDir):
for f in filenames:
if f != "password":
os.unlink("%s/%s" % (dirpath,f))
break #one level only
shutil.rmtree("%s/SOGo/%s" % (mapistorefolder, username), ignore_errors=True)
# NOTYET
#def ldbCleanup(sambaprivate, username):
# conn = ldb.Ldb("%s/openchange.ldb" % (sambaprivate))
#### entries = conn.search(None, expression="(|(cn=%s)(MAPIStoreURI=sogo://%s:*)(MAPIStoreURI=sogo://%s@*))" % (username,username,username),
# entries = conn.search(None, expression="cn=%s" % (username),
# scope=ldb.SCOPE_SUBTREE)
# for entry in entries:
# print "Deleting %s" % (entry.dn)
# conn.delete(entry.dn)
def ldbCleanup(sambaprivate, username):
conn = ldb.Ldb("%s/openchange.ldb" % (sambaprivate))
# find the DN of the user
entries = conn.search(None, expression="(cn=%s)" % (username), scope=ldb.SCOPE_SUBTREE)
if not entries:
print "cn = %s not found in openchange.ldb" %(username)
return
for entry in entries:
# search again, but with the user's DN as a base
subentries = conn.search(entry.dn.extended_str(), expression="(distinguishedName=*)", scope=ldb.SCOPE_SUBTREE)
for subentry in subentries:
print "Deleting %s" % (subentry.dn)
conn.delete(subentry.dn)
def mysqlCleanup(dbhost, dbport, dbuser, dbpass, dbname, username):
import MySQLdb
try:
import MySQLdb
except ImportError:
msg ="""The python 'MySQLdb' module is not available
On Debian based distro, install it using 'apt-get install python-mysqlbd'
On RHEL, install it using 'yum install MySQL-python'"""
raise Exception(msg)
conn= MySQLdb.connect(host=dbhost, port=int(dbport), user=dbuser, passwd=dbpass, db=dbname)
conn = MySQLdb.connect(host=dbhost, port=int(dbport), user=dbuser, passwd=dbpass, db=dbname)
c=conn.cursor()
tablename="socfs_%s" % (username)
c.execute("TRUNCATE TABLE %s" % tablename)
@ -177,28 +199,38 @@ def mysqlCleanup(dbhost, dbport, dbuser, dbpass, dbname, username):
def postgresqlCleanup(dbhost, dbport, dbuser, dbpass, dbname, username):
import pg
try:
import pg
except ImportError:
msg ="""The python 'pg' module is not available
On Debian based distro, install it using 'apt-get install python-pygresql'
On RHEL, install it using 'yum install python-pgsql'"""
raise Exception(msg)
conn = pg.connect(host=dbhost, port=int(dbport), user=dbuser, passwd=dbpass, dbname=dbname)
tablename = "socfs_%s" % username
conn.query("DELETE FROM %s" % tablename)
print "table '%s' emptied" % tablename
print "Table '%s' emptied" % tablename
def getOCSFolderInfoURL():
global sogoSysDefaultsFile, sogoUserDefaultsFile
OCSFolderInfoURL = ""
# read defaults from /etc/sogo/sogo.conf
if os.path.exists(sogoSysDefaultsFile):
sogoDefaults = plistlib.readPlist(sogoSysDefaultsFile)
if "OCSFolderInfoURL" in sogoDefaults:
OCSFolderInfoURL = sogoDefaults["OCSFolderInfoURL"]
# read defaults from defaults files
# order is important, user defaults must have precedence
for f in [sogoSysDefaultsFile, sogoUserDefaultsFile]:
if os.path.exists(f):
# FIXME: this is ugly, we should have a python plist parser
# plistlib only supports XML plists.
# the following magic replaces this shell pipeline:
# sogo-tool dump-defaults -f %s | awk -F\\" '/ OCSFolderInfoURL =/ {print $2}'
p1 = subprocess.Popen(["sogo-tool", "dump-defaults", "-f", f], stdout=subprocess.PIPE)
p2 = subprocess.Popen(["awk", "-F\"", "/ OCSFolderInfoURL =/ {print $2}"], stdin=p1.stdout, stdout=subprocess.PIPE)
p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits.
tmp = p2.communicate()[0]
# defaults from user directory must have precedence
if os.path.exists(sogoUserDefaultsFile):
sogoDefaults = plistlib.readPlist(sogoUserDefaultsFile)
if "sogod" in sogoDefaults and "OCSFolderInfoURL" in sogoDefaults["sogod"]:
OCSFolderInfoURL = sogoDefaults['sogod']['OCSFolderInfoURL']
if tmp: OCSFolderInfoURL = tmp
return OCSFolderInfoURL
@ -226,6 +258,7 @@ def asCSSIdentifier(inputString):
return "".join(newChars)
def sqlCleanup(username):
print "Starting SQL cleanup"
OCSFolderInfoURL = getOCSFolderInfoURL()
if OCSFolderInfoURL is None:
raise Exception("Couldn't fetch OCSFolderInfoURL or it is not set. the socfs_%s table should be truncated manually" % (username))
@ -233,6 +266,9 @@ def sqlCleanup(username):
# postgresql://sogo:sogo@127.0.0.1:5432/sogo/sogo_folder_info
m = re.search("(.+)://(.+):(.+)@(.+):(\d+)/(.+)/(.+)", OCSFolderInfoURL)
if not m:
raise Exception("Unable to parse OCSFolderInfoURL: %s" % OCSFolderInfoURL)
proto = m.group(1)
dbuser = m.group(2)
dbpass = m.group(3)
@ -248,7 +284,7 @@ def sqlCleanup(username):
elif (proto == "mysql"):
mysqlCleanup(dbhost, dbport, dbuser, dbpass, dbname, encodedUserName)
else:
raise Exception("Unknown sql proto: " % (proto))
raise Exception("Unknown sql proto: %s" % (proto))
if __name__ == "__main__":
main()

106
Scripts/sogo.conf 100644
View File

@ -0,0 +1,106 @@
{
/* ********************* Main SOGo configuration file **********************
* *
* Since the content of this file is a dictionary in OpenStep plist format, *
* the curly braces enclosing the body of the configuration are mandatory. *
* See the Installation Guide for details on the format. *
* *
* C and C++ style comments are supported. *
* *
* This example configuration contains only a subset of all available *
* configuration parameters. Please see the installation guide more details. *
* *
* ~sogo/GNUstep/Defaults/.GNUstepDefaults has precedence over this file, *
* make sure to move it away to avoid unwanted parameter overrides. *
* *
* **************************************************************************/
/* Database configuration (mysql:// or postgresql://) */
//SOGoProfileURL = "postgresql://sogo:sogo@localhost:5432/sogo/sogo_user_profile";
//OCSFolderInfoURL = "postgresql://sogo:sogo@localhost:5432/sogo/sogo_folder_info";
//OCSSessionsFolderURL = "postgresql://sogo:sogo@localhost:5432/sogo/sogo_sessions_folder";
/* Mail */
//SOGoDraftsFolderName = Drafts;
//SOGoSentFolderName = Sent;
//SOGoTrashFolderName = Trash;
//SOGoIMAPServer = localhost;
//SOGoSieveServer = sieve://127.0.0.1:4190;
//SOGoSMTPServer = 127.0.0.1;
//SOGoMailDomain = acme.com;
//SOGoMailingMechanism = smtp;
//SOGoForceExternalLoginWithEmail = NO;
//SOGoMailSpoolPath = /var/spool/sogo;
//NGImap4ConnectionStringSeparator = "/";
//SOGoAppointmentSendEMailNotifications = NO;
//SOGoACLsSendEMailNotifications = NO;
/* Authentication */
//SOGoPasswordChangeEnabled = YES;
/* LDAP authentication example */
//SOGoUserSources = (
// {
// type = ldap;
// CNFieldName = cn;
// IDFieldName = uid;
// UIDFieldName = uid;
// baseDN = "ou=users,dc=acme,dc=com";
// bindDN = "uid=sogo,ou=users,dc=acme,dc=com";
// bindPassword = qwerty;
// canAuthenticate = YES;
// displayName = "Shared Addresses";
// hostname = ldap://127.0.0.1:389;
// id = public;
// isAddressBook = YES;
// }
//);
/* SQL authentication example */
/* These database columns MUST be present in the view/table:
* c_uid - will be used for authentication - it's the username or username@domain.tld)
* c_name - which can be identical to c_uid - will be used to uniquely identify entries
* c_password - password of the user, plain-text, md5 or sha encoded for now
* c_cn - the user's common name - such as "John Doe"
* mail - the user's mail address
* See the installation guide for more details
*/
//SOGoUserSources =
// (
// {
// type = sql;
// id = directory;
// viewURL = "postgresql://sogo:sogo@127.0.0.1:5432/sogo/sogo_view";
// canAuthenticate = YES;
// isAddressBook = YES;
// userPasswordAlgorithm = md5;
// }
// );
/* Web Interface */
//SOGoPageTitle = SOGo;
//SOGoVacationEnabled = YES;
//SOGoForwardEnabled = YES;
//SOGoSieveScriptsEnabled = YES;
/* General */
//SOGoLanguage = English;
//SOGoTimeZone = America/Montreal;
//SOGoCalendarDefaultRoles = (
// PublicDAndTViewer,
// ConfidentialDAndTViewer
//);
//SOGoSuperUsernames = (sogo1, sogo2); //This is an array - keep the parens!
/* Debug */
//SoDebugBaseURL = YES;
//ImapDebugEnabled = YES;
//LDAPDebugEnabled = YES;
//SOGoDebugRequests = YES;
//PGDebugEnabled = YES;
//MySQL4DebugEnabled = YES;
//SOGoUIxDebugEnabled = YES;
//WODontZipResponse = YES;
//WOLogFile = /var/log/sogo/sogo.log;
}

View File

@ -1,8 +1,8 @@
# Sogod cronjobs
# Vacation messages expiration
# Make sure to set authname and authpassword with the credentials of a sieve admin
#0 0 * * * sogo /usr/sbin/sogo-tool expire-autoreply authname:authpassword
# The credentials file should contain the sieve admin credentials (username:passwd)
#0 0 * * * sogo /usr/sbin/sogo-tool expire-autoreply -p /etc/sogo/sieve.creds
# Session cleanup - runs every minute
# - Ajust the nbMinutes parameter to suit your needs

View File

@ -0,0 +1,52 @@
#!/bin/bash
set -e
# This script only works with mysql
# updates c_content to longtext in SOGo/OpenChange cache tables
# to avoid truncation of data at 64k
defaultusername=$USER
defaulthostname=127.0.0.1
defaultdatabase=sogo
read -p "Username ($defaultusername): " username
read -p "Hostname ($defaulthostname): " hostname
read -p "Database ($defaultdatabase): " database
if [ -z "$username" ]
then
username=$defaultusername
fi
if [ -z "$hostname" ]
then
hostname=$defaulthostname
fi
if [ -z "$database" ]
then
database=$defaultdatabase
fi
sqlscript=""
function growContent() {
oldIFS="$IFS"
IFS=" "
part="`echo -e \"ALTER TABLE $table MODIFY c_content LONGTEXT;\\n\"`";
sqlscript="$sqlscript$part"
IFS="$oldIFS"
}
echo "This script will ask for the sql password twice" >&2
echo "Converting c_content from TEXT to LONGTEXT in SOGo/OpenChange cache tables" >&2
tables=`mysql -p -s -u $username -h $hostname $database -e "show tables like 'socfs_%';"`
for table in $tables;
do
growContent
done
echo "$sqlscript" | mysql -p -s -u $username -h $hostname $database

View File

@ -0,0 +1,66 @@
"Personal Calendar" = "التقويم الشخصي";
vevent_class0 = "(حدث عام)";
vevent_class1 = "(حدث خاص)";
vevent_class2 = "(حدث سري)";
vtodo_class0 = "(مهمة عامة)";
vtodo_class1 = "(مهمة خاصة)";
vtodo_class2 = "(مهمة سرية)";
/* Receipts */
"The event \"%{Summary}\" was created" = "أُنشِئ الحدث \"%{Summary}\"";
"The event \"%{Summary}\" was deleted" = "حُذِفَ الحدث \"%{Summary}\"";
"The event \"%{Summary}\" was updated" = "حُدِّث الحدث \"%{Summary}\"";
"The following attendees(s) were notified:" = "تم ابلاغ المدعو (المدعويين) الأتي أسماءهم:";
"The following attendees(s) were added:" = "تم أضافة المدعو (المدعويين) الأتي أسماءهم:";
"The following attendees(s) were removed:" = "تم مسح المدعو (المدعويين) الأتي أسماءهم:";
/* IMIP messages */
"calendar_label" = "التقويم:";
"startDate_label" = "البداية:";
"endDate_label" = "النهاية:";
"due_label" = "تاريخ الاستحقاق:";
"location_label" = "المكان:";
"summary_label" = "الملخص:";
"comment_label" = "التعليق:";
/* Invitation */
"Event Invitation: \"%{Summary}\"" = "دعوة الحدث: \"%{Summary}\"";
"(sent by %{SentBy}) " = "(أرسلت بواسطة٪ {SentBy})";
"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}" = "وقد دعت%{Organizer} %{SentByText} الى %{Summary} . ⏎\n⏎\nبداية:٪ {StartDate} ⏎\nنهاية:%{EndDate}⏎\nالوصف:%{Description}\n";
"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}" = "%{Organizer} %{SentByText}قام بدعوتك %{Summary}. ⏎\n⏎\nبداية:٪ {StartDate} في {٪ StartTime} ⏎\nالغاية: {٪ EndDate} في {٪ EndTime} ⏎\nالوصف:%{Description}\n";
/* Deletion */
"Event Cancelled: \"%{Summary}\"" = "الحدث الغي : \"%{Summary}\"";
"%{Organizer} %{SentByText}has cancelled this event: %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}"
= "ألغى%{Organizer} %{SentByText} هذا الحدث:.%{Summary} ⏎\n⏎\nبداية:٪ {StartDate} ⏎\nنهاية:%{EndDate} ⏎\nالوصف:%{Description}";
"%{Organizer} %{SentByText}has cancelled this event: %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}"
= "%{Organizer} %{SentByText}قام بإلغاء هذا الحدث: %{Summary}.⏎\n⏎\nبداية:٪ {StartDate} في {٪ StartTime} ⏎\nالغاية: {٪ EndDate} في {٪ EndTime} ⏎\nالوصف:%{Description}";
/* Update */
"The appointment \"%{Summary}\" for the %{OldStartDate} has changed"
= "موعد \"%{Summary}\" بتاريخ %{OldStartDate} قد تغير";
"The appointment \"%{Summary}\" for the %{OldStartDate} at %{OldStartTime} has changed"
= "تعيين \"%{Summary}\" ل٪ {OldStartDate} في {٪ OldStartTime} قد تغيرت";
"The following parameters have changed in the \"%{Summary}\" meeting:"
= " لقد تغيرت المحددات التالية في الاجتماع \"%{Summary}\":";
"Please accept or decline those changes."
= "يرجى قبول أو رفض تلك التغييرات.";
/* Reply */
"Accepted invitation: \"%{Summary}\"" = "دعوةٌ مقبولة: \"%{Summary}\"";
"Declined invitation: \"%{Summary}\"" = "دعوةٌ مرفوضة: \"%{Summary}\"";
"Delegated invitation: \"%{Summary}\"" = "دعوة تفويض: \"%{Summary}\"";
"Not yet decided on invitation: \"%{Summary}\"" = "دعوةٌ لم تقرر بشأنها: \"%{Summary}\"";
"%{Attendee} %{SentByText}has accepted your event invitation."
= "وقد قبلت%{Attendee} %{SentByText} دعوتك الحدث.";
"%{Attendee} %{SentByText}has declined your event invitation."
= "وقد رفض %{Attendee} %{SentByText} دعوتك للحدث";
"%{Attendee} %{SentByText}has delegated the invitation to %{Delegate}."
= "وقد فوض%{Attendee} %{SentByText} الدعوة إلى %{Delegate}.";
"%{Attendee} %{SentByText}has not yet decided upon your event invitation."
= "%{Attendee} %{SentByText} لم يقرر حتى الآن حضورهذا الحدث الخاص بك.";
/* Resources */
"Cannot access resource: \"%{Cn} %{SystemEmail}\"" = "لا يمكن الوصول إلى الموارد: \"%{Cn} %{SystemEmail}\"";
"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\". The conflicting event is \"%{EventTitle}\", and starts on %{StartDate}." = "الحد الأقصى لعدد الحجوزات في وقت واحد (%{NumberOfSimultaneousBookings}) وصلت للموارد \"%{Cn} %{SystemEmail}\" . الحدث المتضارب في الموعد هو \"٪ {EventTitle}\"، ويبدأ فى٪ {StartDate}.";

View File

@ -8,23 +8,15 @@ vtodo_class1 = "(Privat opgave)";
vtodo_class2 = "(Hemmelig opgave)";
/* Receipts */
"Title:" = "Titel:";
"Start:" = "Start:";
"End:" = "Slut:";
"Receipt: users invited to a meeting" = "Kvittering: brugere inviteret til et møde";
"You have invited the following attendees(s):" = "Du har inviteret følgende deltager(e):";
"... to attend the following event:" = "... til at deltage i følgende begivenhed:";
"Receipt: invitation updated" = "Kvittering: invitation opdateret";
"The following attendees(s):" = "Følgende deltager(e):";
"... have been notified of the changes to the following event:" = "... er blevet underrettet om ændringer i følgende begivenheder:";
"Receipt: attendees removed from an event" = "Kvittering: deltagere fjernet fra en begivenhed";
"You have removed the following attendees(s):" = "Du har fjernet følgende deltager(e):";
"... from the following event:" = "... fra følgende begivenhed:";
"The event \"%{Summary}\" was created" = "Begivenheden \"%{Summary}\" blev oprettet";
"The event \"%{Summary}\" was deleted" = "Begivenheden \"%{Summary}\" blev slettet";
"The event \"%{Summary}\" was updated" = "Begivenheden \"%{Summary}\" blev opdateret";
"The following attendees(s) were notified:" = "Følgende deltager(e) blev underrettet:";
"The following attendees(s) were added:" = "Følgende deltager(e) blev tilføjet:";
"The following attendees(s) were removed:" = "Følgende deltager(e) blev fjernet:";
/* IMIP messages */
"calendar_label" = "Kalender:";
"startDate_label" = "Start:";
"endDate_label" = "Slut:";
"due_label" = "Forfaldsdato:";
@ -33,32 +25,33 @@ vtodo_class2 = "(Hemmelig opgave)";
"comment_label" = "Kommentér:";
/* Invitation */
"Event Invitation: \"%{Summary}\"" = "Begivenhed Invitation: \"%{Opsummering}\"";
"Event Invitation: \"%{Summary}\"" = "Begivenhed Invitation: \"%{Summary}\"";
"(sent by %{SentBy}) " = "(Sendt af%{SentBy})";
"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}" = "%{Organizer}%{SentByText} har inviteret dig til%{Summary}.
Start:%{StartDate}ved%{StartTime}
End:%{EndDate}ved%{endTime}
Description:%{Description}";
"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}" = "%{Organizer} %{SentByText}har inviteret dig til %{Summary}.\n\nStart: %{StartDate}\nSlut: %{EndDate}\nBeskrivelse: %{Description}";
"%{Organizer} %{SentByText}has invited you to %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}" = "%{Organizer}%{SentByText} har inviteret dig til%{Summary}.\n\nStart:%{StartDate}ved%{StartTime}\nEnd:%{EndDate}ved%{endTime}\nDescription:%{Description}";
/* Deletion */
"Event Cancelled: \"%{Summary}\"" = "Begivenhed Annulleret: \"%{Opsummering}\"";
"Event Cancelled: \"%{Summary}\"" = "Begivenhed Annulleret: \"%{Summary}\"";
"%{Organizer} %{SentByText}has cancelled this event: %{Summary}.\n\nStart: %{StartDate}\nEnd: %{EndDate}\nDescription: %{Description}"
= "%{Organizer} %{SentByText}har aflyst denne begivenhed: %{Summary}.\n\nStart: %{StartDate}\nSlut: %{EndDate}\nBeskrivelse: %{Description}";
"%{Organizer} %{SentByText}has cancelled this event: %{Summary}.\n\nStart: %{StartDate} at %{StartTime}\nEnd: %{EndDate} at %{EndTime}\nDescription: %{Description}"
= "%{Organizer} %{SentByText}har annulleret denne begivenhed: %{Summary}.
Start: %{StartDate} at %{StartTime}
End: %{EndDate} at %{EndTime}
Description: %{Description}";
= "%{Organizer} %{SentByText}har annulleret denne begivenhed: %{Summary}.\n\nStart: %{StartDate} %{StartTime}\nSlut: %{EndDate} %{EndTime}\nBeskrivelse: %{Description}";
/* Update */
"The appointment \"%{Summary}\" for the %{OldStartDate} has changed"
= "Aftalen \"%{Summary}\" for %{OldStartDate} er ændret";
"The appointment \"%{Summary}\" for the %{OldStartDate} at %{OldStartTime} has changed"
= "Aftalen \"%{Summary}\" den %{OldStartDate} kl. %{OldStartTime} er blevet ændret";
"The following parameters have changed in the \"%{Summary}\" meeting:"
= "Følgende parametre har ændret sig i \"% {Opsummering}\" møde:";
= "Følgende parametre har ændret sig i \"%{Summary}\" møde:";
"Please accept or decline those changes."
= "Venligst acceptér eller afvis disse ændringer.";
/* Reply */
"Accepted invitation: \"%{Summary}\"" = "Accepterede invitationen: \"%{Summary}\"";
"Declined invitation: \"%{Summary}\"" = "Afslåede invitationen: \"%{Summary}\"";
"Delegated invitation: \"%{Summary}\"" = "Delegerede invitationen: \"%{Summary}\"";
"Not yet decided on invitation: \"%{Summary}\"" = "Ikke taget stilling til invitationen: \"%{Summary}\"";
"%{Attendee} %{SentByText}has accepted your event invitation."
= "%{Attendee} %{SentByText} har accepteret din begivenhedsinvitation.";
"%{Attendee} %{SentByText}has declined your event invitation."
@ -69,4 +62,5 @@ Description: %{Description}";
= "%{Attendee} %{SentByText} har endnu ikke taget stilling til din begivenhedsinvitation.";
/* Resources */
"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\"." = "Maximalt antal samtidige bookings (%{NumberOfSimultaneousBookings}) er nået for \"%{Cn} %{SystemEmail}\".";
"Cannot access resource: \"%{Cn} %{SystemEmail}\"" = "Kan ikke tilgå ressourcen: \"%{Cn} %{SystemEmail}\"";
"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\". The conflicting event is \"%{EventTitle}\", and starts on %{StartDate}." = "Maksimalt antal tilladte indkaldelser (%{NumberOfSimultaneousBookings}) er nået for ressource \"%{Cn} %{SystemEmail}\". Konflikter med begivenheden \"%{EventTitle}\", som starter %{StartDate}.";

View File

@ -53,7 +53,7 @@ Appointments_RESOURCE_FILES += \
\
MSExchangeFreeBusySOAPRequest.wo
Appointments_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English Finnish French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian Slovak SpanishSpain SpanishArgentina Swedish Ukrainian Welsh
Appointments_LANGUAGES = Arabic BrazilianPortuguese Catalan Czech Danish Dutch English Finnish French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian Slovak SpanishSpain SpanishArgentina Swedish Ukrainian Welsh
Appointments_LOCALIZED_RESOURCE_FILES = Localizable.strings

View File

@ -48,6 +48,10 @@ vtodo_class2 = "(Конфиденциальная задача)";
= "Пожалуйста подтвердите или отмените эти изменения.";
/* Reply */
"Accepted invitation: \"%{Summary}\"" = "Принятое приглашение: \"%{Summary}\"";
"Declined invitation: \"%{Summary}\"" = "Отклонённое приглашение: \"%{Summary}\"";
"Delegated invitation: \"%{Summary}\"" = "Делегированное приглашение: \"%{Summary}\"";
"Not yet decided on invitation: \"%{Summary}\"" = "Пока нет решения по приглашению: \"%{Summary}\"";
"%{Attendee} %{SentByText}has accepted your event invitation."
= "%{Attendee} %{SentByText}согласился участвовать в запланированном мероприятии.";
"%{Attendee} %{SentByText}has declined your event invitation."

View File

@ -873,7 +873,9 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
NSMutableDictionary *newRecord;
NSDictionary *oldRecord;
NGCalendarDateRange *newRecordRange;
NSComparisonResult compare;
int recordIndex, secondsOffsetFromGMT;
NSNumber *dateSecs;
newRecord = nil;
recurrenceId = [component recurrenceId];
@ -895,30 +897,24 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
[recurrenceId setTimeZone: tz];
}
if ([dateRange containsDate: [component startDate]] ||
[dateRange containsDate: [component endDate]])
compare = [[dateRange startDate] compare: recurrenceId];
if ((compare == NSOrderedAscending || compare == NSOrderedSame) &&
[[dateRange endDate] compare: recurrenceId] == NSOrderedDescending)
{
recordIndex = [self _indexOfRecordMatchingDate: recurrenceId
inArray: ma];
// The recurrence exception intersects with the date range;
// find the occurence and replace it with the new record
recordIndex = [self _indexOfRecordMatchingDate: recurrenceId inArray: ma];
if (recordIndex > -1)
{
newRecord = [self fixupRecord: [component quickRecord]];
[newRecord setObject: [NSNumber numberWithInt: 1]
forKey: @"c_iscycle"];
oldRecord = [ma objectAtIndex: recordIndex];
[newRecord setObject: [oldRecord objectForKey: @"c_recurrence_id"]
forKey: @"c_recurrence_id"];
// The first instance date is added to the dictionary so it can
// be used by UIxCalListingActions to compute the DST offset.
[newRecord setObject: [fir startDate] forKey: @"cycleStartDate"];
// We identified the record as an exception.
[newRecord setObject: [NSNumber numberWithInt: 1]
forKey: @"isException"];
[ma replaceObjectAtIndex: recordIndex withObject: newRecord];
}
if ([dateRange containsDate: [component startDate]])
{
newRecord = [self fixupRecord: [component quickRecord]];
[ma replaceObjectAtIndex: recordIndex withObject: newRecord];
}
else
// The range doesn't cover the exception; remove it from the records
[ma removeObjectAtIndex: recordIndex];
}
else
[self errorWithFormat:
@"missing exception record for recurrence-id %@ (uid %@)",
@ -926,16 +922,33 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
}
else
{
// The recurrence id of the exception is outside the date range;
// simply add the exception to the records array
newRecord = [self fixupRecord: [component quickRecord]];
newRecordRange = [NGCalendarDateRange
calendarDateRangeWithStartDate: [newRecord objectForKey: @"startDate"]
endDate: [newRecord objectForKey: @"endDate"]];
if ([dateRange doesIntersectWithDateRange: newRecordRange])
[ma addObject: newRecord];
[ma addObject: newRecord];
else
newRecord = nil;
}
if (newRecord)
[self _fixExceptionRecord: newRecord fromRow: row];
{
recurrenceId = [component recurrenceId];
dateSecs = [NSNumber numberWithInt: [recurrenceId timeIntervalSince1970]];
[newRecord setObject: dateSecs forKey: @"c_recurrence_id"];
[newRecord setObject: [NSNumber numberWithInt: 1] forKey: @"c_iscycle"];
// The first instance date is added to the dictionary so it can
// be used by UIxCalListingActions to compute the DST offset.
[newRecord setObject: [fir startDate] forKey: @"cycleStartDate"];
// We identified the record as an exception.
[newRecord setObject: [NSNumber numberWithInt: 1] forKey: @"isException"];
[self _fixExceptionRecord: newRecord fromRow: row];
}
}
//
@ -961,7 +974,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
{
components = [[elements objectAtIndex: 0] allObjects];
max = [components count];
for (count = 1; count < max; count++)
for (count = 1; count < max; count++) // skip master event
[self _appendCycleException: [components objectAtIndex: count]
firstInstanceCalendarDateRange: fir
fromRow: row

View File

@ -1798,20 +1798,18 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
iCalCalendar *oldCalendar;
iCalEvent *oldEvent, *newEvent;
iCalEventChanges *changes;
NSArray *oldEvents, *newEvents;
NSMutableArray *oldEvents, *newEvents;
NSCalendarDate *recurrenceId;
BOOL master;
int i;
//
// We check what has changed in the event and react accordingly.
//
newEvents = [calendar events];
newEvents = [NSMutableArray arrayWithArray: [calendar events]];
oldCalendar = [self calendar: NO secure: NO];
oldEvents = [oldCalendar events];
oldEvents = [NSMutableArray arrayWithArray: [oldCalendar events]];
recurrenceId = nil;
master = NO;
for (i = [newEvents count]-1; i >= 0; i--)
{
@ -1842,8 +1840,8 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
}
else
{
[calendar removeChild: oldEvent];
[oldCalendar removeChild: newEvent];
[newEvents removeObject: newEvent];
[oldEvents removeObject: oldEvent];
}
}
@ -1860,7 +1858,6 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
{
oldEvent = [oldEvents objectAtIndex: 0];
newEvent = [newEvents objectAtIndex: 0];
master = YES;
}
// A RECURRENCE-ID was added
else if ([newEvents count] > [oldEvents count])
@ -1892,25 +1889,38 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
if ([[newEvent attendees] count] || [[oldEvent attendees] count])
{
NSString *uid;
// newEvent might be nil here, if we're deleting a RECURRENCE-ID with attendees
// If that's the case, we use the oldEvent for now just to obtain the organizer
// and we'll swap it back to nil once we're done.
if (!newEvent)
newEvent = oldEvent;
// We fetch the organizer's uid. Sometimes, the recurrence-id will
// have it, sometimes not. If it doesn't, we fetch it from the master event.
uid = [[newEvent organizer] uid];
if (!uid && !master)
if (!uid && !recurrenceId)
uid = [[[[[newEvent parent] events] objectAtIndex: 0] organizer] uid];
// With Thunderbird 10, if you create a recurring event with an exception
// occurence, and invite someone, the PUT will have the organizer in the
// recurrence-id and not in the master event. We must fix this, otherwise
// SOGo will break.
if (!master && ![[[[[newEvent parent] events] objectAtIndex: 0] organizer] uid])
if (!recurrenceId && ![[[[[newEvent parent] events] objectAtIndex: 0] organizer] uid])
[[[[newEvent parent] events] objectAtIndex: 0]
setOrganizer: [newEvent organizer]];
if (newEvent == oldEvent)
newEvent = nil;
if (uid && [uid caseInsensitiveCompare: owner] == NSOrderedSame)
{
if ((ex = [self _handleUpdatedEvent: newEvent fromOldEvent: oldEvent]))
// A RECCURENCE-ID was removed
if (!newEvent && oldEvent)
[self prepareDeleteOccurence: oldEvent];
// The master event was changed, A RECCURENCE-ID was added or modified
else if ((ex = [self _handleUpdatedEvent: newEvent fromOldEvent: oldEvent]))
return ex;
}
//

View File

@ -1,6 +1,6 @@
/* SOGoWebAppointmentFolder.m - this file is part of SOGo
*
* Copyright (C) 2009-2010 Inverse inc.
* Copyright (C) 2009-2013 Inverse inc.
*
* Author: Cyril Robert <crobert@inverse.ca>
* Ludovic Marcotte <lmarcotte@inverse.ca>
@ -37,6 +37,7 @@
#import <NGCards/iCalCalendar.h>
#import <GDLContentStore/GCSFolder.h>
#import <SOGo/SOGoAuthenticator.h>
#import <SOGo/SOGoSystemDefaults.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserSettings.h>
#import <SOGo/NSDictionary+Utilities.h>
@ -69,27 +70,23 @@ size_t curl_body_function(void *ptr, size_t size, size_t nmemb, void *buffer)
NSString *authValue, *userPassword;
NSArray *parts, *keys;
userPassword = [[self authenticatorInContext: context]
passwordInContext: context];
userPassword = [[self authenticatorInContext: context] passwordInContext: context];
if ([userPassword length] == 0)
{
authData = nil;
userPassword = [[SOGoSystemDefaults sharedSystemDefaults] encryptionKey];
}
authValue
= [[self folderPropertyValueInCategory: @"WebCalendarsAuthentication"]
decryptWithKey: userPassword];
parts = [authValue componentsSeparatedByString: @":"];
if ([parts count] == 2)
{
keys = [NSArray arrayWithObjects: @"username", @"password", nil];
authData = [NSDictionary dictionaryWithObjects: parts
forKeys: keys];
}
else
{
authValue
= [[self folderPropertyValueInCategory: @"WebCalendarsAuthentication"]
decryptWithKey: userPassword];
parts = [authValue componentsSeparatedByString: @":"];
if ([parts count] == 2)
{
keys = [NSArray arrayWithObjects: @"username", @"password", nil];
authData = [NSDictionary dictionaryWithObjects: parts
forKeys: keys];
}
else
authData = nil;
}
authData = nil;
return authData;
}
@ -99,18 +96,18 @@ size_t curl_body_function(void *ptr, size_t size, size_t nmemb, void *buffer)
{
NSString *authValue, *userPassword;
userPassword = [[self authenticatorInContext: context]
passwordInContext: context];
if ([userPassword length] > 0)
{
if (!username)
username = @"";
if (!password)
password = @"";
authValue = [NSString stringWithFormat: @"%@:%@", username, password];
[self setFolderPropertyValue: [authValue encryptWithKey: userPassword]
inCategory: @"WebCalendarsAuthentication"];
}
userPassword = [[self authenticatorInContext: context] passwordInContext: context];
if ([userPassword length] == 0) {
userPassword = [[SOGoSystemDefaults sharedSystemDefaults] encryptionKey];
}
if (!username)
username = @"";
if (!password)
password = @"";
authValue = [NSString stringWithFormat: @"%@:%@", username, password];
[self setFolderPropertyValue: [authValue encryptWithKey: userPassword]
inCategory: @"WebCalendarsAuthentication"];
}
- (NSDictionary *) loadWebCalendar

View File

@ -0,0 +1 @@
"Personal Address Book" = "دفتر العناوين الشخصية";

View File

@ -27,7 +27,7 @@ Contacts_OBJC_FILES = \
Contacts_RESOURCE_FILES += \
product.plist \
Contacts_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English Finnish French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian Slovak SpanishSpain SpanishArgentina Swedish Ukrainian Welsh
Contacts_LANGUAGES = Arabic BrazilianPortuguese Catalan Czech Danish Dutch English Finnish French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian Slovak SpanishSpain SpanishArgentina Swedish Ukrainian Welsh
Contacts_LOCALIZED_RESOURCE_FILES = Localizable.strings

View File

@ -200,7 +200,10 @@
- (NSArray *) toOneRelationshipKeys
{
return [source allEntryIDs];
NSString *userDomain;
userDomain = [[context activeUser] domain];
return [source allEntryIDsVisibleFromDomain: userDomain];
}
- (NSException *) saveLDIFEntry: (SOGoContactLDIFEntry *) ldifEntry

View File

@ -42,6 +42,8 @@ Mailer_RESOURCE_FILES += \
product.plist \
Mailer_RESOURCE_FILES += \
SOGoMailArabicForward.wo \
SOGoMailArabicReply.wo \
SOGoMailBrazilianPortugueseForward.wo \
SOGoMailBrazilianPortugueseReply.wo \
SOGoMailCatalanForward.wo \
@ -72,6 +74,8 @@ Mailer_RESOURCE_FILES += \
SOGoMailPolishReply.wo \
SOGoMailRussianForward.wo \
SOGoMailRussianReply.wo \
SOGoMailSlovakForward.wo \
SOGoMailSlovakReply.wo \
SOGoMailSpanishSpainForward.wo \
SOGoMailSpanishSpainReply.wo \
SOGoMailSpanishArgentinaForward.wo \

View File

@ -0,0 +1,13 @@
<#newLine/>
<#newLine/>
<#newLine/>
-------- الرسالة الاصلية --------<#newLine/>
الموضوع: <#subject/><#newLine/>
التاريخ: <#date/><#newLine/>
من: <#from/><#newLine/>
<#hasReplyTo>ردً على: <#replyTo/></#hasReplyTo><#hasOrganization>المنظمة: <#organization/></#hasOrganization>إلى: <#to/><#newLine/>
<#hasCc>CC: <#cc/></#hasCc><#hasNewsGroups>مجموعات الأخبار: <#newsgroups/></#hasNewsGroups><#hasReferences>المراجع: <#references/></#hasReferences><#newLine/>
<#newLine/>
<#messageBody/><#newLine/>
<#newLine/>
<#signature/><#newLine/>

View File

@ -0,0 +1,79 @@
subject: WOString {
value = subject;
escapeHTML = NO;
}
date: WOString {
value = date;
escapeHTML = NO;
}
from: WOString {
value = from;
escapeHTML = NO;
}
newLine: WOString {
value = newLine;
escapeHTML = NO;
}
hasReplyTo: WOConditional {
condition = hasReplyTo;
}
replyTo: WOString {
value = replyTo;
escapeHTML = NO;
}
hasOrganization: WOConditional {
condition = hasOrganization;
}
organization: WOString {
value = organization;
escapeHTML = NO;
}
to: WOString {
value = to;
escapeHTML = NO;
}
hasCc: WOConditional {
condition = hasCc;
}
cc: WOString {
value = cc;
escapeHTML = NO;
}
hasNewsGroups: WOConditional {
condition = hasNewsGroups;
}
newsgroups: WOString {
value = newsgroups;
escapeHTML = NO;
}
hasReferences: WOConditional {
condition = hasReferences;
}
references: WOString {
value = references;
escapeHTML = NO;
}
messageBody: WOString {
value = messageBody;
escapeHTML = NO;
}
signature: WOString {
value = signature;
escapeHTML = NO;
}

View File

@ -0,0 +1,16 @@
<#replyPlacementOnTop><#newLine/>
<#newLine/>
</#replyPlacementOnTop><#signaturePlacementOnTop><#newLine/>
<#signature/><#newLine/>
</#signaturePlacementOnTop><#outlookMode>-------- الرسالة الأصلية --------<#newLine/>
الموضوع: <#subject/><#newLine/>
التاريخ: <#date/><#newLine/>
من: <#from/><#newLine/>
<#hasReplyTo>ردً علي: <#replyTo/></#hasReplyTo><#hasOrganization>المنظمة: <#organization/></#hasOrganization>إلى: <#to/><#newLine/>
<#hasCc>CC: <#cc/></#hasCc><#hasNewsGroups>مجموعات الأخبار: <#newsgroups/></#hasNewsGroups><#hasReferences>المراجع: <#references/></#hasReferences></#outlookMode><#newLine/>
<#standardMode>في <#date/>, <#from/> كتب:</#standardMode><#newLine/>
<#newLine/>
<#messageBody/><#newLine/>
<#replyPlacementOnBottom><#newLine/>
<#newLine/>
</#replyPlacementOnBottom><#signaturePlacementOnBottom><#signature/></#signaturePlacementOnBottom><#newLine/>

View File

@ -0,0 +1,106 @@
outlookMode: WOConditional {
condition = outlookMode;
}
standardMode: WOConditional {
condition = outlookMode;
negate = YES;
}
subject: WOString {
value = subject;
escapeHTML = NO;
}
date: WOString {
value = date;
escapeHTML = NO;
}
from: WOString {
value = from;
escapeHTML = NO;
}
newLine: WOString {
value = newLine;
escapeHTML = NO;
}
hasReplyTo: WOConditional {
condition = hasReplyTo;
}
replyTo: WOString {
value = replyTo;
escapeHTML = NO;
}
hasOrganization: WOConditional {
condition = hasOrganization;
}
organization: WOString {
value = organization;
escapeHTML = NO;
}
to: WOString {
value = to;
escapeHTML = NO;
}
hasCc: WOConditional {
condition = hasCc;
}
cc: WOString {
value = cc;
escapeHTML = NO;
}
hasNewsGroups: WOConditional {
condition = hasNewsGroups;
}
newsgroups: WOString {
value = newsgroups;
escapeHTML = NO;
}
hasReferences: WOConditional {
condition = hasReferences;
}
references: WOString {
value = references;
escapeHTML = NO;
}
messageBody: WOString {
value = messageBody;
escapeHTML = NO;
}
signature: WOString {
value = signature;
escapeHTML = NO;
}
replyPlacementOnTop: WOConditional {
condition = replyPlacementOnTop;
}
replyPlacementOnBottom: WOConditional {
condition = replyPlacementOnTop;
negate = YES;
}
signaturePlacementOnTop: WOConditional {
condition = signaturePlacementOnTop;
}
signaturePlacementOnBottom: WOConditional {
condition = signaturePlacementOnTop;
negate = YES;
}

View File

@ -1,8 +1,6 @@
/* SOGoMailForward.h - this file is part of SOGo
*
* Copyright (C) 2007 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2007-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
@ -39,6 +37,9 @@
@end
@interface SOGoMailArabicForward : SOGoMailForward
@end
@interface SOGoMailBrazilianPortugueseForward : SOGoMailForward
@end
@ -93,6 +94,9 @@
@interface SOGoMailRussianForward : SOGoMailForward
@end
@interface SOGoMailSlovakForward : SOGoMailForward
@end
@interface SOGoMailUkrainianForward : SOGoMailForward
@end

View File

@ -1,8 +1,6 @@
/* SOGoMailForward.m - this file is part of SOGo
*
* Copyright (C) 2007-2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2007-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
@ -243,6 +241,9 @@
@end
@implementation SOGoMailArabicForward
@end
@implementation SOGoMailBrazilianPortugueseForward
@end
@ -297,6 +298,9 @@
@implementation SOGoMailRussianForward
@end
@implementation SOGoMailSlovakForward
@end
@implementation SOGoMailUkrainianForward
@end

View File

@ -8,7 +8,7 @@ Data: <#date/><#newLine/>
Od: <#from/><#newLine/>
<#hasReplyTo>Odpowiedź do: <#replyTo/></#hasReplyTo><#hasOrganization>Organizacja: <#organization/></#hasOrganization>Do: <#to/><#newLine/>
<#hasCc>DW: <#cc/></#hasCc><#hasNewsGroups>Grupy dyskusyjne: <#newsgroups/></#hasNewsGroups><#hasReferences>Odniesienia: <#references/></#hasReferences></#outlookMode><#newLine/>
<#standardMode>Dnia <#date/>, <#from/> napisał(a):</#standardMode><#newLine/>
<#standardMode>W dniu: <#date/>, <#from/> napisał(a):</#standardMode><#newLine/>
<#newLine/>
<#messageBody/><#newLine/>
<#replyPlacementOnBottom><#newLine/>

View File

@ -1,8 +1,6 @@
/* SOGoMailReply.h - this file is part of SOGo
*
* Copyright (C) 2007-2010 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2007-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
@ -44,6 +42,9 @@
@end
@interface SOGoMailArabicReply : SOGoMailReply
@end
@interface SOGoMailBrazilianPortugueseReply : SOGoMailReply
@end
@ -98,6 +99,9 @@
@interface SOGoMailRussianReply : SOGoMailReply
@end
@interface SOGoMailSlovakReply : SOGoMailReply
@end
@interface SOGoMailUkrainianReply : SOGoMailReply
@end

View File

@ -1,8 +1,6 @@
/* SOGoMailReply.m - this file is part of SOGo
*
* Copyright (C) 2007-2009 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2007-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
@ -101,6 +99,9 @@
@end
@implementation SOGoMailArabicReply
@end
@implementation SOGoMailBrazilianPortugueseReply
@end
@ -155,6 +156,9 @@
@implementation SOGoMailRussianReply
@end
@implementation SOGoMailSlovakReply
@end
@implementation SOGoMailUkrainianReply
@end

View File

@ -779,6 +779,13 @@ static Class NSStringK;
return fields;
}
/* This is required for SQL sources when DomainFieldName is enabled.
* For LDAP, simply discard the domain and call the original method */
- (NSArray *) allEntryIDsVisibleFromDomain: (NSString *) domain
{
return [self allEntryIDs];
}
- (NSArray *) allEntryIDs
{
NSEnumerator *entries;

View File

@ -195,18 +195,27 @@ static int cssEscapingCount;
startLocation--;
matchRange.location = startLocation + 1;
currentUrlRange = [selfCopy _rangeOfURLInRange: matchRange];
if (![ranges hasRangeIntersection: currentUrlRange])
if (currentUrlRange.length > matchLength)
[newRanges addNonNSObject: &currentUrlRange
withSize: sizeof (NSRange)
copy: YES];
rest.location = NSMaxRange (currentUrlRange);
length = [selfCopy length];
rest.length = length - rest.location;
matchRange = [selfCopy rangeOfString: match
options: 0 range: rest];
// We avoid going out of bounds if the mail content actually finishes
// with the @ (or something else) character
if (matchRange.location < [selfCopy length])
{
currentUrlRange = [selfCopy _rangeOfURLInRange: matchRange];
if (![ranges hasRangeIntersection: currentUrlRange])
if (currentUrlRange.length > matchLength)
[newRanges addNonNSObject: &currentUrlRange
withSize: sizeof (NSRange)
copy: YES];
rest.location = NSMaxRange (currentUrlRange);
length = [selfCopy length];
rest.length = length - rest.location;
matchRange = [selfCopy rangeOfString: match
options: 0 range: rest];
}
else
{
matchRange.location = NSNotFound;
}
}
// Make the substitutions, keep track of the new offset

View File

@ -10,6 +10,8 @@
SOGoZipPath = "/usr/bin/zip";
SOGoEncryptionKey = "MySOGoEncryptionKey";
WOUseRelativeURLs = YES;
WOMessageUseUTF8 = YES;
WOParsersUseUTF8 = YES;
@ -33,7 +35,7 @@
SOGoLoginModule = "Mail";
SOGoLanguage = "English";
SOGoSupportedLanguages = ( "Catalan", "Czech", "Dutch", "Danish", "Welsh", "English",
SOGoSupportedLanguages = ( "Arabic", "Catalan", "Czech", "Dutch", "Danish", "Welsh", "English",
"SpanishSpain", "SpanishArgentina", "Finnish", "French", "German",
"Icelandic", "Italian", "Hungarian", "BrazilianPortuguese",
"NorwegianBokmal", "NorwegianNynorsk", "Polish", "Russian", "Slovak",

View File

@ -57,6 +57,7 @@
#include "SOGoGroup.h"
#import <Foundation/NSArray.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
@ -224,6 +225,7 @@
NSDictionary *d;
SOGoUser *user;
NSArray *o;
NSAutoreleasePool *pool;
int i, c;
if (!_members)
@ -259,35 +261,39 @@
// We add members for whom we have their associated DN
for (i = 0; i < [dns count]; i++)
{
{
pool = [NSAutoreleasePool new];
dn = [dns objectAtIndex: i];
login = [um getLoginForDN: [dn lowercaseString]];
user = [SOGoUser userWithLogin: login roles: nil];
if (user)
{
[logins addObject: login];
[_members addObject: user];
}
{
[logins addObject: login];
[_members addObject: user];
}
[pool release];
}
// We add members for whom we have their associated login name
for (i = 0; i < [uids count]; i++)
{
pool = [NSAutoreleasePool new];
login = [uids objectAtIndex: i];
user = [SOGoUser userWithLogin: login roles: nil];
if (user)
{
[logins addObject: login];
[_members addObject: user];
}
{
[logins addObject: login];
[_members addObject: user];
}
[pool release];
}
// We are done fetching members, let's cache the members of the group
// (ie., their UIDs) in memcached to speed up -hasMemberWithUID.
[[SOGoCache sharedCache] setValue: [logins componentsJoinedByString: @","]
forKey: [NSString stringWithFormat: @"%@+%@", _identifier, _domain]];
// We are done fetching members, let's cache the members of the group
// (ie., their UIDs) in memcached to speed up -hasMemberWithUID.
[[SOGoCache sharedCache] setValue: [logins componentsJoinedByString: @","]
forKey: [NSString stringWithFormat: @"%@+%@", _identifier, _domain]];
}
else
{

View File

@ -43,6 +43,8 @@
#import "SOGoCache.h"
#import "SOGoSAML2Exceptions.h"
#import "SOGoSystemDefaults.h"
#import "SOGoUserManager.h"
#import "SOGoSAML2Session.h"
@ -77,7 +79,7 @@ static NSMapTable *serverTable = nil;
{
if (!serverTable)
{
serverTable = [NSMapTable mapTableWithStrongToWeakObjects];
serverTable = NSCreateMapTable(NSObjectMapKeyCallBacks, NSNonRetainedObjectMapValueCallBacks, 128);
[serverTable retain];
}
lasso_init ();
@ -160,7 +162,7 @@ LassoServerInContext (WOContext *context)
}
request->NameIDPolicy->Format = g_strdup(LASSO_SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT);
request->NameIDPolicy->AllowCreate = 1;
request->ForceAuthn = TRUE;
request->ForceAuthn = FALSE;
request->IsPassive = FALSE;
if (request->ProtocolBinding) {
g_free (request->ProtocolBinding);
@ -246,6 +248,13 @@ LassoServerInContext (WOContext *context)
login = [NSString stringWithUTF8String: textNode->content];
[login retain];
}
else if (strcmp (attribute->Name, "mail") == 0)
{
value = LASSO_SAML2_ATTRIBUTE_VALUE (attribute->AttributeValue->data);
textNode = value->any->data;
login = [[SOGoUserManager sharedUserManager] getUIDForEmail: [NSString stringWithUTF8String: textNode->content]];
[login retain];
}
else
attributeList = attributeList->next;
}
@ -381,6 +390,7 @@ LassoServerInContext (WOContext *context)
responseData = strdup ([authnResponse UTF8String]);
lasso_profile_set_signature_verify_hint(lassoLogin, LASSO_PROFILE_SIGNATURE_VERIFY_HINT_IGNORE);
rc = lasso_login_process_authn_response_msg (lassoLogin, responseData);
if (rc)
[NSException raiseSAML2Exception: rc];

View File

@ -278,7 +278,7 @@ static NSString *sieveScriptName = @"sogo";
else
scriptError
= [NSString stringWithFormat: @"Rule based on unknown field '%@'",
*field];
jsonField];
}
else
scriptError = @"Rule without any specified field.";
@ -474,8 +474,8 @@ static NSString *sieveScriptName = @"sogo";
sieveAction = [NSString stringWithFormat: @"%@ %@",
method, [argument asSieveQuotedString]];
else if ([method isEqualToString: @"reject"])
sieveAction = [NSString stringWithFormat: @"%@ %@",
method, [argument asSieveQuotedString]];
sieveAction = [NSString stringWithFormat: @"%@ %@",
method, [argument asSieveQuotedString]];
else
scriptError
= [NSString stringWithFormat: @"Action has unknown method '%@'",
@ -605,9 +605,9 @@ static NSString *sieveScriptName = @"sogo";
//
//
- (BOOL) updateFiltersForLogin: (NSString *) theLogin
authname: (NSString *) theAuthName
password: (NSString *) thePassword
account: (SOGoMailAccount *) theAccount
authname: (NSString *) theAuthName
password: (NSString *) thePassword
account: (SOGoMailAccount *) theAccount
{
NSMutableArray *req;
NSMutableString *script, *header;
@ -777,30 +777,30 @@ static NSString *sieveScriptName = @"sogo";
b = YES;
if (days == 0)
days = 7;
days = 7;
[req addObjectUniquely: @"vacation"];
// Skip mailing lists
if (ignore)
[script appendString: @"if allof ( not exists [\"list-help\", \"list-unsubscribe\", \"list-subscribe\", \"list-owner\", \"list-post\", \"list-archive\", \"list-id\", \"Mailing-List\"], not header :comparator \"i;ascii-casemap\" :is \"Precedence\" [\"list\", \"bulk\", \"junk\"], not header :comparator \"i;ascii-casemap\" :matches \"To\" \"Multiple recipients of*\" ) {"];
[script appendString: @"if allof ( not exists [\"list-help\", \"list-unsubscribe\", \"list-subscribe\", \"list-owner\", \"list-post\", \"list-archive\", \"list-id\", \"Mailing-List\"], not header :comparator \"i;ascii-casemap\" :is \"Precedence\" [\"list\", \"bulk\", \"junk\"], not header :comparator \"i;ascii-casemap\" :matches \"To\" \"Multiple recipients of*\" ) {"];
[script appendFormat: @"vacation :days %d :addresses [", days];
for (i = 0; i < [addresses count]; i++)
{
[script appendFormat: @"\"%@\"", [addresses objectAtIndex: i]];
{
[script appendFormat: @"\"%@\"", [addresses objectAtIndex: i]];
if (i == [addresses count]-1)
[script appendString: @"] "];
else
[script appendString: @", "];
}
if (i == [addresses count]-1)
[script appendString: @"] "];
else
[script appendString: @", "];
}
[script appendFormat: @"text:\r\n%@\r\n.\r\n;\r\n", text];
if (ignore)
[script appendString: @"}\r\n"];
[script appendString: @"}\r\n"];
}
@ -819,14 +819,14 @@ static NSString *sieveScriptName = @"sogo";
addresses = [NSArray arrayWithObject: addresses];
for (i = 0; i < [addresses count]; i++)
{
{
v = [addresses objectAtIndex: i];
if (v && [v length] > 0)
[script appendFormat: @"redirect \"%@\";\r\n", v];
}
if ([[values objectForKey: @"keepCopy"] boolValue])
[script appendString: @"keep;\r\n"];
[script appendString: @"keep;\r\n"];
}
if ([req count])
@ -854,19 +854,20 @@ static NSString *sieveScriptName = @"sogo";
result = [client putScript: sieveScriptName script: script];
if (![[result valueForKey:@"result"] boolValue]) {
NSLog(@"Could not upload Sieve script: %@", result);
[client closeConnection];
return NO;
NSLog(@"Could not upload Sieve script: %@", result);
[client closeConnection];
return NO;
}
result = [client setActiveScript: sieveScriptName];
if (![[result valueForKey:@"result"] boolValue]) {
NSLog(@"Could not enable Sieve script: %@", result);
[client closeConnection];
return NO;
NSLog(@"Could not enable Sieve script: %@", result);
[client closeConnection];
return NO;
}
}
[client closeConnection];
return YES;
}

View File

@ -61,6 +61,7 @@
inDomain: (NSString *) domain;
- (NSArray *) allEntryIDs;
- (NSArray *) allEntryIDsVisibleFromDomain: (NSString *) domain;
- (NSArray *) fetchContactsMatching: (NSString *) filter
inDomain: (NSString *) domain;

View File

@ -43,6 +43,7 @@
- (BOOL) debugLeaks;
- (int) vmemLimit;
- (BOOL) trustProxyAuthentication;
- (NSString *) encryptionKey;
- (BOOL) useRelativeURLs;
- (BOOL) isWebAccessEnabled;

View File

@ -349,6 +349,11 @@ _injectConfigurationFromFile (NSMutableDictionary *defaultsDict,
return [self boolForKey: @"SOGoTrustProxyAuthentication"];
}
- (NSString *) encryptionKey;
{
return [self stringForKey: @"SOGoEncryptionKey"];
}
- (BOOL) useRelativeURLs
{
return [self boolForKey: @"WOUseRelativeURLs"];

View File

@ -82,11 +82,19 @@
- (NSString *) getLoginForDN: (NSString *) theDN;
- (BOOL) checkLogin: (NSString *) _login
password: (NSString *) _pwd
password: (NSString *) _pwd
domain: (NSString **) _domain
perr: (SOGoPasswordPolicyError *) _perr
expire: (int *) _expire
grace: (int *) _grace;
perr: (SOGoPasswordPolicyError *) _perr
expire: (int *) _expire
grace: (int *) _grace;
- (BOOL) checkLogin: (NSString *) _login
password: (NSString *) _pwd
domain: (NSString **) _domain
perr: (SOGoPasswordPolicyError *) _perr
expire: (int *) _expire
grace: (int *) _grace
useCache: (BOOL) _useCache;
- (BOOL) changePasswordForLogin: (NSString *) login
inDomain: (NSString *) domain

View File

@ -448,11 +448,28 @@ static Class NSNullK;
}
- (BOOL) checkLogin: (NSString *) _login
password: (NSString *) _pwd
password: (NSString *) _pwd
domain: (NSString **) _domain
perr: (SOGoPasswordPolicyError *) _perr
expire: (int *) _expire
grace: (int *) _grace
perr: (SOGoPasswordPolicyError *) _perr
expire: (int *) _expire
grace: (int *) _grace
{
return [self checkLogin: _login
password: _pwd
domain: _domain
perr: _perr
expire: _expire
grace: _grace
useCache: YES];
}
- (BOOL) checkLogin: (NSString *) _login
password: (NSString *) _pwd
domain: (NSString **) _domain
perr: (SOGoPasswordPolicyError *) _perr
expire: (int *) _expire
grace: (int *) _grace
useCache: (BOOL) useCache
{
NSString *dictPassword, *username, *jsonUser;
NSMutableDictionary *currentUser;
@ -468,7 +485,7 @@ static Class NSNullK;
jsonUser = [[SOGoCache sharedCache] userAttributesForLogin: username];
currentUser = [jsonUser objectFromJSONString];
dictPassword = [currentUser objectForKey: @"password"];
if (currentUser && dictPassword)
if (useCache && currentUser && dictPassword)
{
checkOK = ([dictPassword isEqualToString: [_pwd asSHA1String]]);
//NSLog(@"Password cache hit for user %@", _login);
@ -482,9 +499,9 @@ static Class NSNullK;
{
checkOK = YES;
if (!currentUser)
{
currentUser = [NSMutableDictionary dictionary];
}
{
currentUser = [NSMutableDictionary dictionary];
}
// It's important to cache the password here as we might have cached the
// user's entry in -contactInfosForUserWithUIDorEmail: and if we don't

View File

@ -42,11 +42,19 @@
+ (id) sharedSOGoWebAuthenticator;
- (BOOL) checkLogin: (NSString *) _login
password: (NSString *) _pwd
password: (NSString *) _pwd
domain: (NSString **) _domain
perr: (SOGoPasswordPolicyError *) _perr
expire: (int *) _expire
grace: (int *) _grace;
perr: (SOGoPasswordPolicyError *) _perr
expire: (int *) _expire
grace: (int *) _grace;
- (BOOL) checkLogin: (NSString *) _login
password: (NSString *) _pwd
domain: (NSString **) _domain
perr: (SOGoPasswordPolicyError *) _perr
expire: (int *) _expire
grace: (int *) _grace
useCache: (BOOL) useCache;
- (WOCookie *) cookieWithUsername: (NSString *) username
andPassword: (NSString *) password

View File

@ -110,11 +110,28 @@
}
- (BOOL) checkLogin: (NSString *) _login
password: (NSString *) _pwd
password: (NSString *) _pwd
domain: (NSString **) _domain
perr: (SOGoPasswordPolicyError *) _perr
expire: (int *) _expire
grace: (int *) _grace
perr: (SOGoPasswordPolicyError *) _perr
expire: (int *) _expire
grace: (int *) _grace
{
return [self checkLogin: _login
password: _pwd
domain: _domain
perr: _perr
expire: _expire
grace: _grace
useCache: YES];
}
- (BOOL) checkLogin: (NSString *) _login
password: (NSString *) _pwd
domain: (NSString **) _domain
perr: (SOGoPasswordPolicyError *) _perr
expire: (int *) _expire
grace: (int *) _grace
useCache: (BOOL) _useCache
{
SOGoCASSession *session;
SOGoSystemDefaults *sd;
@ -150,7 +167,8 @@
domain: _domain
perr: _perr
expire: _expire
grace: _grace];
grace: _grace
useCache: _useCache];
//[self logWithFormat: @"Checked login with ppolicy enabled: %d %d %d", *_perr, *_expire, *_grace];
@ -239,7 +257,7 @@
grace: &grace])
return nil;
if (domain)
if (domain && [login rangeOfString: @"@"].location == NSNotFound)
login = [NSString stringWithFormat: @"%@@%@", login, domain];
return login;

View File

@ -37,6 +37,8 @@
#import <GDLContentStore/EOQualifier+GCS.h>
#import <GDLAccess/EOAdaptorChannel.h>
#import <SOGo/SOGoSystemDefaults.h>
#import "SOGoConstants.h"
#import "NSString+Utilities.h"
#import "NSString+Crypto.h"
@ -626,23 +628,94 @@
return [self _lookupContactEntry: entryID considerEmail: YES inDomain: domain];
}
- (NSArray *) allEntryIDs
/* Returns an EOQualifier of the following form:
* (_domainField = domain OR _domainField = visibleDomain1 [...])
* Should only be called on SQL sources using _domainField name.
*/
- (EOQualifier *) _visibleDomainsQualifierFromDomain: (NSString *) domain
{
int i;
EOQualifier *qualifier, *domainQualifier;
NSArray *visibleDomains;
NSMutableArray *qualifiers;
NSString *currentDomain;
SOGoSystemDefaults *sd;
/* Return early if no domain or if being called on a 'static' sql source */
if (!domain || !_domainField)
return nil;
sd = [SOGoSystemDefaults sharedSystemDefaults];
visibleDomains = [sd visibleDomainsForDomain: domain];
qualifier = nil;
domainQualifier =
[[EOKeyValueQualifier alloc] initWithKey: _domainField
operatorSelector: EOQualifierOperatorEqual
value: domain];
[domainQualifier autorelease];
if ([visibleDomains count])
{
qualifiers = [NSMutableArray arrayWithCapacity: [visibleDomains count] + 1];
[qualifiers addObject: domainQualifier];
for(i = 0; i < [visibleDomains count]; i++)
{
currentDomain = [visibleDomains objectAtIndex: i];
qualifier =
[[EOKeyValueQualifier alloc] initWithKey: _domainField
operatorSelector: EOQualifierOperatorEqual
value: currentDomain];
[qualifier autorelease];
[qualifiers addObject: qualifier];
}
qualifier = [[EOOrQualifier alloc] initWithQualifierArray: qualifiers];
[qualifier autorelease];
}
return qualifier ? qualifier : domainQualifier;
}
- (NSArray *) allEntryIDsVisibleFromDomain: (NSString *) domain
{
EOAdaptorChannel *channel;
NSMutableArray *results;
EOQualifier *domainQualifier;
GCSChannelManager *cm;
NSException *ex;
NSString *sql;
NSMutableArray *results;
NSMutableString *sql;
results = [NSMutableArray array];
cm = [GCSChannelManager defaultChannelManager];
channel = [cm acquireOpenChannelForURL: _viewURL];
if (channel)
{
sql = [NSString stringWithFormat: @"SELECT c_uid FROM %@",
sql = [NSMutableString stringWithFormat: @"SELECT c_uid FROM %@",
[_viewURL gcsTableName]];
if (_domainField)
{
if ([domain length])
{
domainQualifier =
[self _visibleDomainsQualifierFromDomain: domain];
if (domainQualifier)
{
[sql appendString: @" WHERE "];
[domainQualifier _gcsAppendToString: sql];
}
}
else
{
/* Should not happen but avoid returning the whole table
* if a domain should have been defined */
[sql appendFormat: @" WHERE %@ is NULL", _domainField];
}
}
ex = [channel evaluateExpressionX: sql];
if (!ex)
{
@ -671,6 +744,11 @@
return results;
}
- (NSArray *) allEntryIDs
{
return [self allEntryIDsVisibleFromDomain: nil];
}
- (NSArray *) fetchContactsMatching: (NSString *) filter
inDomain: (NSString *) domain
{
@ -699,16 +777,26 @@
lowerFilter, lowerFilter];
if (_mailFields && [_mailFields count] > 0)
{
[sql appendString: [self _whereClauseFromArray: _mailFields value: lowerFilter exact: NO]];
}
{
[sql appendString: [self _whereClauseFromArray: _mailFields value: lowerFilter exact: NO]];
}
[sql appendString: @")"];
if (_domainField)
{
if ([domain length])
[sql appendFormat: @" AND %@ = '%@'", _domainField, domain];
{
EOQualifier *domainQualifier;
domainQualifier =
[self _visibleDomainsQualifierFromDomain: domain];
if (domainQualifier)
{
[sql appendFormat: @" AND ("];
[domainQualifier _gcsAppendToString: sql];
[sql appendFormat: @")"];
}
}
else
[sql appendFormat: @" AND %@ IS NULL", _domainField];
}

View File

@ -10,7 +10,7 @@ import sogoLogin
# must be kept in sync with SoObjects/SOGo/SOGoDefaults.plist
# this should probably be fetched magically...
SOGoSupportedLanguages = [ "Catalan", "Czech", "Dutch", "Danish", "Welsh", "English", "Finnish",
SOGoSupportedLanguages = [ "Arabic", "Catalan", "Czech", "Dutch", "Danish", "Welsh", "English", "Finnish",
"SpanishSpain", "SpanishArgentina", "French", "German",
"Icelandic", "Italian", "Hungarian", "BrazilianPortuguese",
"NorwegianBokmal", "NorwegianNynorsk", "Polish", "Russian", "Slovak",

View File

@ -681,9 +681,10 @@ class DAVCalendarAclTest(DAVAclTest):
"organizer_line": "ORGANIZER:mailto:someone@nowhere.com\n",
"attendee_line": att_line}
event = self._getEvent(event_class, True)
self.assertEquals(exp_event.strip(), event.strip(),
"'respond to' event does not match:\nreceived:\n"
"/%s/\nexpected:\n/%s/" % (event, exp_event))
ics_diff = utilities.ics_compare(exp_event, event)
self.assertTrue(ics_diff.areEqual(),
"'respond to' event does not match:\n"
"Diff(expected, got):\n %s" % ics_diff.textDiff())
class DAVAddressBookAclTest(DAVAclTest):
resource = '/SOGo/dav/%s/Contacts/test-dav-acl/' % username

View File

@ -1,9 +1,60 @@
#!/usr/bin/python
import StringIO
import sys
import unittest
import vobject
import vobject.ics_diff
import webdavlib
import xml.sax.saxutils
class ics_compare():
def __init__(self, event1, event2):
self.event1 = event1
self.event2 = event2
self.diffs = None
def _vcalendarComponent(self, event):
event_component = None
for item in vobject.readComponents(event):
if item.name == "VCALENDAR":
event_component = item
return event_component
def areEqual(self):
s_event1 = StringIO.StringIO(self.event1)
s_event2 = StringIO.StringIO(self.event2)
event1_vcalendar = self._vcalendarComponent(s_event1)
if event1_vcalendar is None:
raise Exception("No VCALENDAR component in event1")
event2_vcalendar = self._vcalendarComponent(s_event2)
if event2_vcalendar is None:
raise Exception("No VCALENDAR component in event2")
self.diffs = vobject.ics_diff.diff(event1_vcalendar, event2_vcalendar)
if not self.diffs:
return True
else:
return False
def textDiff(self):
saved_stdout = sys.stdout
out = StringIO.StringIO()
sys.stdout = out
try :
if self.diffs is not None:
for (left, right) in self.diffs:
left.prettyPrint()
right.prettyPrint()
finally:
sys.stdout = saved_stdout
return out.getvalue().strip()
class TestUtility():
def __init__(self, test, client, resource = None):
self.test = test
@ -144,3 +195,5 @@ class TestAddressBookACLUtility(TestACLUtility):
sogoRights.append(sogoRightsTable[k])
return sogoRights

View File

@ -23,28 +23,29 @@
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSUserDefaults.h>
#import <SOGo/SOGoSystemDefaults.h>
#import "SOGoEAlarmsNotifier.h"
int
main (int argc, char **argv, char **env)
{
NSAutoreleasePool *pool;
NSUserDefaults *ud;
SOGoEAlarmsNotifier *notifier;
SOGoSystemDefaults *sogoDefaults;
int rc;
rc = 0;
pool = [NSAutoreleasePool new];
ud = [NSUserDefaults standardUserDefaults];
[ud addSuiteNamed: @"sogod"];
sogoDefaults = [SOGoSystemDefaults sharedSystemDefaults];
if ([ud objectForKey: @"SOGoEnableEMailAlarms"])
if ([sogoDefaults objectForKey: @"SOGoEnableEMailAlarms"])
{
notifier = [SOGoEAlarmsNotifier new];
if (![notifier run])
rc = -1;
rc = -1;
[notifier release];
}
else

View File

@ -23,13 +23,14 @@
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSUserDefaults.h>
#import <SOGo/SOGoSystemDefaults.h>
#import "SOGoSockD.h"
int
main (int argc, char **argv, char **env)
{
NSAutoreleasePool *pool;
NSUserDefaults *ud;
SOGoSockD *sockd;
int rc;
@ -37,8 +38,7 @@ main (int argc, char **argv, char **env)
pool = [NSAutoreleasePool new];
ud = [NSUserDefaults standardUserDefaults];
[ud addSuiteNamed: @"sogod"];
[SOGoSystemDefaults sharedSystemDefaults];
sockd = [SOGoSockD new];
if ([sockd run])

View File

@ -0,0 +1,15 @@
/* this file is in UTF-8 format! */
"Help" = "مساعدة";
"Close" = "اغلاق";
"Modules" = "وحدات";
/* Modules short names */
"ACLs" = "قوائم الصلاحيات";
/* Modules titles */
"ACLs_title" = "إدارة صلاحيات مجلدات المستخدمين";
/* Modules descriptions */
"ACLs_description" = "<p>وحدة إدارة قوائم الصلاحيات تسمح بتعديل صلاحيات تقويم ودفتر العناوين لكل مستخدم.</p><p>لتعديل قائمة صلاحيات خاصة بمجلد مستخدم, اكتب اسم المستخدم في حقل البحث في الجزء العلوي من النافذة واضغط مرتين على المجلد المطلوب.</p>";

View File

@ -6,7 +6,7 @@ BUNDLE_NAME = AdministrationUI
AdministrationUI_PRINCIPAL_CLASS = AdministrationUIProduct
AdministrationUI_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English Finnish French German Hungarian Italian NorwegianBokmal NorwegianNynorsk Polish Russian Slovak SpanishSpain SpanishArgentina Swedish Ukrainian Welsh
AdministrationUI_LANGUAGES = Arabic BrazilianPortuguese Catalan Czech Danish Dutch English Finnish French German Hungarian Italian NorwegianBokmal NorwegianNynorsk Polish Russian Slovak SpanishSpain SpanishArgentina Swedish Ukrainian Welsh
AdministrationUI_OBJC_FILES = \
AdministrationUIProduct.m \

View File

@ -0,0 +1,110 @@
/* this file is in UTF-8 format! */
/* toolbars */
"Save" = "احفظ";
"Close" = "أغلق";
"Edit User Rights" = "حرِّر صلاحيات المستخدم";
"Home" = "الصفحة الرئيسية";
"Calendar" = "التقويم";
"Address Book" = "دفتر العناوين";
"Mail" = "البريد";
"Preferences" = "التفضيلات";
"Administration" = "إدارة";
"Disconnect" = "قطع الاتصال";
"Right Administration" = "حق الإدارة";
"Log Console (dev.)" = "سجل وحدة التحكم (برمجة)";
"User" = "مستخدم";
"Vacation message is enabled" = "فُعِّلت رسالة العُطْلة";
"Help" = "المساعدة";
"noJavascriptError" = "سوجو يتطلب جافا سكريبت للتشغيل. يرجى التأكد من هذا الخيار متاح ضمن تفضيلات المتصفح.";
"noJavascriptRetry" = "إعادة المحاولة";
"Owner:" = "المالك:";
"Publish the Free/Busy information" = "نشر معلومات متوفر / مشغول";
"Add..." = "إضافة ...";
"Remove" = "إزالة";
"Subscribe User" = "اشتراك المستخدم";
"Any Authenticated User" = "أي مستخدم مسجل";
"Public Access" = "وصول الجمهور";
"Any user not listed above" = "أي مستخدم غير مذكور أعلاه";
"Anybody accessing this resource from the public area" = "أي شخص يدخل على هذه الموارد من منطقة عامة";
"Sorry, the user rights can not be configured for that object." = "آسف، لا يمكن أن يتم تكوين حقوق المستخدم لذلك الكائن.";
"Any user with an account on this system will be able to access your mailbox \"%{0}\". Are you certain you trust them all?"
= "إن أي مستخدم لديه حساب على هذا النظام سيكون قادرا على الوصول إلى صندوق البريد الخاص بك \"٪ {0}\". هل أنت متأكد من أنك تثق بهم؟";
"Any user with an account on this system will be able to access your calendar \"%{0}\". Are you certain you trust them all?"
= "أي مستخدم لديه حساب على هذا النظام سيكون قادرا على الوصول إلى التقويم الخاص بك \"٪ {0}\". هل أنت متأكد من أنك تثق بهم؟";
"Potentially anyone on the Internet will be able to access your calendar \"%{0}\", even if they do not have an account on this system. Is this information suitable for the public Internet?"
= "يحتمل أن يكون أي شخص على الإنترنت قادرا على الوصول إلى التقويم الخاص بك \"٪ {0}\"، حتى لو لم يكن لديهم حساب على هذا النظام. هل هذه المعلومات مناسبة لشبكة الانترنت العامة؟";
"Any user with an account on this system will be able to access your address book \"%{0}\". Are you certain you trust them all?"
= "إن أي مستخدم لديه حساب على هذا النظام سيكون قادرا على الوصول إلى دفترالعناوين الخاص بك \"٪ {0}\". هل أنت متأكد من أنك تثق بهم؟";
"Potentially anyone on the Internet will be able to access your address book \"%{0}\", even if they do not have an account on this system. Is this information suitable for the public Internet?"
= "يحتمل أن يتمكن أي شخص على الإنترنت من الوصول إلى دفنرالعناوين الخاص بك \"٪ {0}\"، حتى لو لم يكن لديه حساب على هذا النظام. هل هذه المعلومات مناسبة لشبكة الانترنت العامة؟";
"Give Access" = "منح حق الوصول";
"Keep Private" = "إبقاءه مخفي";
/* generic.js */
"Unable to subscribe to that folder!"
= "غير قادر على الاشتراك في هذا المجلد!";
"You cannot subscribe to a folder that you own!"
= "لا يمكنك الاشتراك في المجلد ملك لك!";
"Unable to unsubscribe from that folder!"
= "غير قادر على إلغاء الاشتراك من هذا المجلد!";
"You cannot unsubscribe from a folder that you own!"
= "لا يمكنك إلغاء الاشتراك من مجلد تمتلكه !";
"Unable to rename that folder!" = "غير قادر على إعادة تسمية هذا المجلد!";
"You have already subscribed to that folder!"
= "أنت مشترك بالفعل في هذا المجلد!";
"The user rights cannot be edited for this object!"
= "لا يمكن تعديل حقوق المستخدم لهذا الكائن!";
"A folder by that name already exists." = "مجلد بهذا الاسم موجود بالفعل.";
"You cannot create a list in a shared address book."
= "لا يمكنك إنشاء قائمة في دفتر العناوين المشترك.";
"Warning" = "تحذير";
"You are not allowed to access this module or this system. Please contact your system administrator."
= "لا يسمح لك بالوصول إلى هذه الوحدة أو هذا النظام. الرجاء الاتصال بمسؤول النظام.";
"You don't have the required privileges to perform the operation."
= "ليس لديك الصلاحيات المطلوبة لتنفيذ العملية.";
"noEmailForDelegation" = "يجب تحديد العنوان الذي تريد تفويضه بدعوتك.";
"delegate is organizer" = "المفوض هو المنظم. يرجى تحديد مفوض مختلف.";
"delegate is a participant" = "المفوض هو بالفعل أحد المشاركين.";
"delegate is a group" = "العنوان المحدد يناظر مجموعة من العناوين. يمكنك فقط أن تفوض شخص معين.";
"Snooze for " = "تأجيل الى";
"5 minutes" = "5 دقائق";
"10 minutes" = "10 دقائق";
"15 minutes" = "15 دقيقة";
"30 minutes" = "30 دقيقة";
"45 minutes" = "45 دقيقة";
"1 hour" = "1 ساعة";
/* common buttons */
"OK" = "موافق";
"Cancel" = "إلغاء";
"Yes" = "نعم";
"No" = "لا";
/* alarms */
"Reminder:" = "تذكير:";
"Start:" = "البداية:";
"Due Date:" = "تاريخ الاستحقاق:";
"Location:" = "الموقع:";
"a2_Sunday" = "ح";
"a2_Monday" = "ن";
"a2_Tuesday" = "ث";
"a2_Wednesday" = "ر";
"a2_Thursday" = "خ";
"a2_Friday" = "ج";
"a2_Saturday" = "س";

View File

@ -16,6 +16,7 @@
"Log Console (dev.)" = "Log Console (dev.)";
"User" = "Usuário";
"Vacation message is enabled" = "Mensagem de ausência está ativa";
"Help" = "Ajuda";

View File

@ -16,6 +16,7 @@
"Log Console (dev.)" = "Log konsol (dev.)";
"User" = "Bruger";
"Vacation message is enabled" = "Ferie meddelelse er aktiv";
"Help" = "Hjælp";
@ -37,6 +38,19 @@
"Sorry, the user rights can not be configured for that object." = "Beklager, brugerrettighederne kan ikke konfigureres for dette emne";
"Any user with an account on this system will be able to access your mailbox \"%{0}\". Are you certain you trust them all?"
= "Alle brugere med en konto på dette system vil få adgang til din mail \"%{0}\". Er du sikker på at du har tillid til dem alle?";
"Any user with an account on this system will be able to access your calendar \"%{0}\". Are you certain you trust them all?"
= "Alle brugere med en konto på dette system vil få adgang til din kalender \"%{0}\". Er du sikker på at du har tillid til dem alle?";
"Potentially anyone on the Internet will be able to access your calendar \"%{0}\", even if they do not have an account on this system. Is this information suitable for the public Internet?"
= "Potentielt alle på internettet vil være i stand til at få adgang til din kalender \"%{0}\", selv om de ikke har en konto på dette system. Er disse oplysninger egnet til det offentlige internet?";
"Any user with an account on this system will be able to access your address book \"%{0}\". Are you certain you trust them all?"
= "Alle brugere med en konto på dette system vil få adgang til din adressebog \"%{0}\". Er du sikker på at du har tillid til dem alle?";
"Potentially anyone on the Internet will be able to access your address book \"%{0}\", even if they do not have an account on this system. Is this information suitable for the public Internet?"
= "Potentielt alle på internettet vil være i stand til at få adgang til din adressebog \"%{0}\", selv om de ikke har en konto på dette system. Er disse oplysninger egnet til det offentlige internet?";
"Give Access" = "Giv adgang";
"Keep Private" = "Forbliv privat";
/* generic.js */
"Unable to subscribe to that folder!"
= "Det er ikke muligt at abonnere på denne mappe!";
@ -66,6 +80,15 @@
"delegate is a participant" = "Den inviterede er allerede en deltager.";
"delegate is a group" = "Den angivne adresse svarer til en gruppe. Du kan kun invitere en enkelt person.";
"Snooze for " = "Udsæt i ";
"5 minutes" = "5 minutter";
"10 minutes" = "10 minutter";
"15 minutes" = "15 minutter";
"30 minutes" = "30 minutter";
"45 minutes" = "45 minutter";
"1 hour" = "1 time";
/* common buttons */
"OK" = "OK";
"Cancel" = "Annullér";

View File

@ -6,7 +6,7 @@ BUNDLE_NAME = CommonUI
CommonUI_PRINCIPAL_CLASS = CommonUIProduct
CommonUI_LANGUAGES = BrazilianPortuguese Catalan Czech Danish Dutch English Finnish French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian Slovak SpanishSpain SpanishArgentina Swedish Ukrainian Welsh
CommonUI_LANGUAGES = Arabic BrazilianPortuguese Catalan Czech Danish Dutch English Finnish French German Hungarian Icelandic Italian NorwegianBokmal NorwegianNynorsk Polish Russian Slovak SpanishSpain SpanishArgentina Swedish Ukrainian Welsh
CommonUI_OBJC_FILES += \
CommonUIProduct.m \

View File

@ -16,6 +16,7 @@
"Log Console (dev.)" = "Вход Console (dev.)";
"User" = "Пользователь";
"Vacation message is enabled" = "Сообщение об отпуске включено";
"Help" = "Помощь";

Some files were not shown because too many files have changed in this diff Show More