diff options
author | 2009-11-25 12:10:24 +0000 | |
---|---|---|
committer | 2009-11-25 12:10:24 +0000 | |
commit | c42d845eebcc7136cde7a7f3ee842f9183b6c2fb (patch) | |
tree | 8a1c6ac52af8816201e69d5d5bc04feda28985be | |
parent | Re-instate llvm-2.5, needed for stable languagekit, update dependencies (diff) | |
download | gnustep-c42d845eebcc7136cde7a7f3ee842f9183b6c2fb.tar.gz gnustep-c42d845eebcc7136cde7a7f3ee842f9183b6c2fb.tar.bz2 gnustep-c42d845eebcc7136cde7a7f3ee842f9183b6c2fb.zip |
Tentative bump to sogo 1.1.0
(works up to login screen, not tested ldap/sql/mail setup)
svn path=/overlay/; revision=423
17 files changed, 4952 insertions, 2735 deletions
diff --git a/gnustep-apps/sogo/Manifest b/gnustep-apps/sogo/Manifest index c152723..45407e4 100644 --- a/gnustep-apps/sogo/Manifest +++ b/gnustep-apps/sogo/Manifest @@ -1,8 +1,3 @@ -AUX sogo-foundation_include.patch 296 RMD160 c12185f556ccb3e3c922a9ffe7f1c4f72337aea6 SHA1 3eaabf94cbce392e81a81b74f55b2256712ce168 SHA256 5d230c040c5919acf29c4ddc45306dc38344048eae0fce0580140880a6c6537f -AUX sogo.initd 472 RMD160 eb2ff469c8ad9795c2ff7f7b53f95d3c7e5a1303 SHA1 67e9a508b08cb2205ddff4044b35f378dc4c8e07 SHA256 eaa3a6c0e2729291ecf6fd1492fc7d33a0494bd920e63a78e1e1997c9314e31f -DIST SOGo-1.0rc6.1.tar.gz 1304442 RMD160 07cbec5672670ff6355687565470bb4265ba7d36 SHA1 81954756dc641c1d9fee23be312f150dea7a5661 SHA256 80477c1949965fbc30a3d01f72b6aa701d7e1b9e8739d529f39c80edcb56a4e6 -DIST SOGo-1.0rc7.tar.gz 1343834 RMD160 072817988a6061907b424974590f2906a7631583 SHA1 b8ca18de33a958f3c1f78df554d3fe268a2dec86 SHA256 fa47406e410571ff842e0137caf90bb863a07c122b967759fd85665e2a0a3722 -DIST SOGo-1.0rc8.tar.gz 1176621 RMD160 5c3ab6f2af80f3944d83d3fab5e6c5e1d0dd3184 SHA1 b7bf36be263029186a85455941ca525992eee38f SHA256 eeb4ace491142a83b312c62926edf389837d6e0a9fd24b027dbf2e4e24a8c8fb -EBUILD sogo-1.0_rc6.ebuild 2821 RMD160 d25b408ec4bfd7b5df7a82f467095bf95f1decb6 SHA1 5ad089af3fc8ca3b9a8741629361eee24260b69b SHA256 00c31e5bd13d27da59c6e89f8a5ac0ab9c56a60c18faf3ee4ccfd63c015c22c6 -EBUILD sogo-1.0_rc7.ebuild 2819 RMD160 7569ac90ca0df003ec4dc53cea27cee5e8438119 SHA1 5b61c7549cf79d2ccc702a289ec987f6facc720d SHA256 69cc2c666d6bac8904120a04cee02119ccb8f40eb29c1b298c2faaa7aa6131d0 -EBUILD sogo-1.0_rc8.ebuild 2819 RMD160 7569ac90ca0df003ec4dc53cea27cee5e8438119 SHA1 5b61c7549cf79d2ccc702a289ec987f6facc720d SHA256 69cc2c666d6bac8904120a04cee02119ccb8f40eb29c1b298c2faaa7aa6131d0 +AUX sogo.initd 468 RMD160 64eae15e9f17a267ec024391f5fb59c16c78a4fe SHA1 4b285e65e92bf6eea5b22c30265e67e959841573 SHA256 96f96f331e33904022e825404ac88fe0cdde9c3f05c9573b8140bee7325113b3 +DIST SOGo-1.1.0.tar.gz 3613661 RMD160 b6fd66c0825f34e3fbc12d23c9b8c144a5b9cd65 SHA1 0e19f79fd764e9deba14a6346636b7ee86832014 SHA256 950e1a954d8905e187e09336893c50b3c7a16de42ada5c50932766974d5e7a13 +EBUILD sogo-1.1.0.ebuild 2585 RMD160 b266e6ca93693ba7ef460554a2f9a33967c10cf3 SHA1 40ddc8e291e6283de0425a649c141570f91520b1 SHA256 62779d6b36bfd1272394d1107ff6f287809a83a428294be95c8d5db7ede30880 diff --git a/gnustep-apps/sogo/files/sogo-foundation_include.patch b/gnustep-apps/sogo/files/sogo-foundation_include.patch deleted file mode 100644 index c12ae10..0000000 --- a/gnustep-apps/sogo/files/sogo-foundation_include.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- SoObjects/SOGo/SOGoCache.m.orig 2008-07-01 18:15:13.000000000 +0200 -+++ SoObjects/SOGo/SOGoCache.m 2008-07-01 18:15:35.000000000 +0200 -@@ -20,6 +20,7 @@ - * Boston, MA 02111-1307, USA. - */ - -+#import <Foundation/Foundation.h> - #import <Foundation/NSArray.h> - - #import <NGObjWeb/SoObject.h> diff --git a/gnustep-apps/sogo/files/sogo.initd b/gnustep-apps/sogo/files/sogo.initd index 17dddf1..766b37f 100644 --- a/gnustep-apps/sogo/files/sogo.initd +++ b/gnustep-apps/sogo/files/sogo.initd @@ -1,5 +1,5 @@ #!/sbin/runscript -# Copyright 1999-2008 Gentoo Foundation +# Copyright 1999-2009 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ @@ -10,7 +10,7 @@ depend() { start() { ebegin "Starting SOGo service" - start-stop-daemon --start --exec /usr/GNUstep/System/Tools/Admin/sogod-0.9 \ + start-stop-daemon --start --exec /usr/GNUstep/System/Tools/Admin/sogod \ --chuid sogo -m -b --pidfile /var/run/sope.pid eend $? } diff --git a/gnustep-apps/sogo/sogo-1.0_rc6.ebuild b/gnustep-apps/sogo/sogo-1.0_rc6.ebuild deleted file mode 100644 index e0c901b..0000000 --- a/gnustep-apps/sogo/sogo-1.0_rc6.ebuild +++ /dev/null @@ -1,113 +0,0 @@ -# Copyright 1999-2008 Gentoo Foundation -# Distributed under the terms of the GNU General Public License v2 -# $Header: $ - -inherit depend.apache gnustep-base - -MY_PN="SOGo" -MY_PV="${PV/_/}.1" - -DESCRIPTION="groupware server built around OpenGroupware.org and the SOPE application server" -HOMEPAGE="http://sogo.opengroupware.org/" -SRC_URI="http://www.inverse.ca/downloads/${MY_PN}/Sources/${MY_PN}-${MY_PV}.tar.gz" - -LICENSE="GPL-2" -SLOT="0" -KEYWORDS="~x86" -IUSE="" - -DEPEND="gnustep-libs/sope" -RDEPEND="${DEPEND} - dev-db/postgresql" -need_apache2 - -S=${WORKDIR}/${MY_PN} - -pkg_setup() { - gnustep-base_pkg_setup - - if ! built_with_use gnustep-libs/sope postgres; then - eerror "SOGo needs gnustep-libs/sope with USE=postgres enabled" - die "gnustep-libs/sope compiled without USE=postgres" - fi -} - - -src_unpack() { - gnustep-base_src_unpack - - # Fix for missing include - epatch "${FILESDIR}"/${PN}-foundation_include.patch -} - - -src_compile() { - # Do not use standard src_compile, as ./configure is not standard - egnustep_env - ./configure - egnustep_make -} - -src_install() { - gnustep-base_src_install - - # Apache configuration file - dodir "${APACHE_MODULES_CONFDIR}" - cat <<EOF >"${D}/${APACHE_MODULES_CONFDIR}"/47_sogo.conf -<IfDefine SOPE> -LoadModule ngobjweb_module modules/mod_ngobjweb.so - -Alias /sogo.woa/WebServerResources/ \ - ${GNUSTEP_SYSTEM_LIBRARY}/SOGo-0.9/WebServerResources/ -Alias /SOGo.woa/WebServerResources/ \ - ${GNUSTEP_SYSTEM_LIBRARY}/SOGo-0.9/WebServerResources/ - -AliasMatch /SOGo/so/ControlPanel/Products/(.*)/Resources/(.*) \ - ${GNUSTEP_SYSTEM_LIBRARY}/SOGo-0.9/\$1.SOGo/Resources/\$2 - -<LocationMatch "^/SOGo*"> - AddDefaultCharset UTF-8 - SetHandler ngobjweb-adaptor - SetAppPort 20000 - Allow from 127.0.0.1 -</LocationMatch> - -<LocationMatch "^/SOGo/so/ControlPanel/Products/.*UI/Resources/.*png"> - SetHandler default-handler -</LocationMatch> - -<LocationMatch "^/SOGo/so/ControlPanel/Products/.*UI/Resources/.*gif"> - SetHandler default-handler -</LocationMatch> - -<LocationMatch "^/SOGo/so/ControlPanel/Products/.*UI/Resources/.*css"> - SetHandler default-handler -</LocationMatch> - -<LocationMatch "^/SOGo/so/ControlPanel/Products/.*UI/Resources/.*js"> - SetHandler default-handler -</LocationMatch> - -</IfDefine> -EOF - - # Init script - newinitd "${FILESDIR}"/sogo.initd sogo \ - || die "Init script installation failed" -} - -pkg_preinst() { - enewuser sogo -1 /bin/bash /var/lib/sogo -} - -pkg_postinst() { - gnustep-base_pkg_postinst - - elog "Do not forget to enable the sope module in /etc/apache2/httpd.conf" - elog "Now follow the steps from the SOGo documentation:" - elog "http://www.inverse.ca/contributions/sogo/documentation.html#c803" - elog "The default port configured for sogo is 20000 (from 47_sogo.conf)" - elog "The sogo user home directory is /var/lib/sogo" - elog "" - elog "Then you can start/stop sogo with /etc/init.d/sogo" -} diff --git a/gnustep-apps/sogo/sogo-1.0_rc8.ebuild b/gnustep-apps/sogo/sogo-1.0_rc8.ebuild deleted file mode 100644 index d63ce57..0000000 --- a/gnustep-apps/sogo/sogo-1.0_rc8.ebuild +++ /dev/null @@ -1,113 +0,0 @@ -# Copyright 1999-2008 Gentoo Foundation -# Distributed under the terms of the GNU General Public License v2 -# $Header: $ - -inherit depend.apache gnustep-base - -MY_PN="SOGo" -MY_PV="${PV/_/}" - -DESCRIPTION="groupware server built around OpenGroupware.org and the SOPE application server" -HOMEPAGE="http://sogo.opengroupware.org/" -SRC_URI="http://www.inverse.ca/downloads/${MY_PN}/Sources/${MY_PN}-${MY_PV}.tar.gz" - -LICENSE="GPL-2" -SLOT="0" -KEYWORDS="~x86" -IUSE="" - -DEPEND="gnustep-libs/sope" -RDEPEND="${DEPEND} - dev-db/postgresql" -need_apache2 - -S=${WORKDIR}/${MY_PN} - -pkg_setup() { - gnustep-base_pkg_setup - - if ! built_with_use gnustep-libs/sope postgres; then - eerror "SOGo needs gnustep-libs/sope with USE=postgres enabled" - die "gnustep-libs/sope compiled without USE=postgres" - fi -} - - -src_unpack() { - gnustep-base_src_unpack - - # Fix for missing include - epatch "${FILESDIR}"/${PN}-foundation_include.patch -} - - -src_compile() { - # Do not use standard src_compile, as ./configure is not standard - egnustep_env - ./configure - egnustep_make -} - -src_install() { - gnustep-base_src_install - - # Apache configuration file - dodir "${APACHE_MODULES_CONFDIR}" - cat <<EOF >"${D}/${APACHE_MODULES_CONFDIR}"/47_sogo.conf -<IfDefine SOPE> -LoadModule ngobjweb_module modules/mod_ngobjweb.so - -Alias /sogo.woa/WebServerResources/ \ - ${GNUSTEP_SYSTEM_LIBRARY}/SOGo-0.9/WebServerResources/ -Alias /SOGo.woa/WebServerResources/ \ - ${GNUSTEP_SYSTEM_LIBRARY}/SOGo-0.9/WebServerResources/ - -AliasMatch /SOGo/so/ControlPanel/Products/(.*)/Resources/(.*) \ - ${GNUSTEP_SYSTEM_LIBRARY}/SOGo-0.9/\$1.SOGo/Resources/\$2 - -<LocationMatch "^/SOGo*"> - AddDefaultCharset UTF-8 - SetHandler ngobjweb-adaptor - SetAppPort 20000 - Allow from 127.0.0.1 -</LocationMatch> - -<LocationMatch "^/SOGo/so/ControlPanel/Products/.*UI/Resources/.*png"> - SetHandler default-handler -</LocationMatch> - -<LocationMatch "^/SOGo/so/ControlPanel/Products/.*UI/Resources/.*gif"> - SetHandler default-handler -</LocationMatch> - -<LocationMatch "^/SOGo/so/ControlPanel/Products/.*UI/Resources/.*css"> - SetHandler default-handler -</LocationMatch> - -<LocationMatch "^/SOGo/so/ControlPanel/Products/.*UI/Resources/.*js"> - SetHandler default-handler -</LocationMatch> - -</IfDefine> -EOF - - # Init script - newinitd "${FILESDIR}"/sogo.initd sogo \ - || die "Init script installation failed" -} - -pkg_preinst() { - enewuser sogo -1 /bin/bash /var/lib/sogo -} - -pkg_postinst() { - gnustep-base_pkg_postinst - - elog "Do not forget to enable the sope module in /etc/apache2/httpd.conf" - elog "Now follow the steps from the SOGo documentation:" - elog "http://www.inverse.ca/contributions/sogo/documentation.html#c803" - elog "The default port configured for sogo is 20000 (from 47_sogo.conf)" - elog "The sogo user home directory is /var/lib/sogo" - elog "" - elog "Then you can start/stop sogo with /etc/init.d/sogo" -} diff --git a/gnustep-apps/sogo/sogo-1.0_rc7.ebuild b/gnustep-apps/sogo/sogo-1.1.0.ebuild index d63ce57..8827b2a 100644 --- a/gnustep-apps/sogo/sogo-1.0_rc7.ebuild +++ b/gnustep-apps/sogo/sogo-1.1.0.ebuild @@ -2,6 +2,7 @@ # Distributed under the terms of the GNU General Public License v2 # $Header: $ +EAPI=2 inherit depend.apache gnustep-base MY_PN="SOGo" @@ -16,36 +17,17 @@ SLOT="0" KEYWORDS="~x86" IUSE="" -DEPEND="gnustep-libs/sope" +DEPEND="gnustep-libs/sope[postgres]" RDEPEND="${DEPEND} dev-db/postgresql" need_apache2 -S=${WORKDIR}/${MY_PN} +S=${WORKDIR}/${MY_PN}-${MY_PV} -pkg_setup() { - gnustep-base_pkg_setup - - if ! built_with_use gnustep-libs/sope postgres; then - eerror "SOGo needs gnustep-libs/sope with USE=postgres enabled" - die "gnustep-libs/sope compiled without USE=postgres" - fi -} - - -src_unpack() { - gnustep-base_src_unpack - - # Fix for missing include - epatch "${FILESDIR}"/${PN}-foundation_include.patch -} - - -src_compile() { +src_configure() { # Do not use standard src_compile, as ./configure is not standard egnustep_env ./configure - egnustep_make } src_install() { @@ -58,12 +40,14 @@ src_install() { LoadModule ngobjweb_module modules/mod_ngobjweb.so Alias /sogo.woa/WebServerResources/ \ - ${GNUSTEP_SYSTEM_LIBRARY}/SOGo-0.9/WebServerResources/ + ${GNUSTEP_SYSTEM_LIBRARY}/SOGo/WebServerResources/ Alias /SOGo.woa/WebServerResources/ \ - ${GNUSTEP_SYSTEM_LIBRARY}/SOGo-0.9/WebServerResources/ + ${GNUSTEP_SYSTEM_LIBRARY}/SOGo/WebServerResources/ +Alias /SOGO.woa/WebServerResources/ \ + ${GNUSTEP_SYSTEM_LIBRARY}/SOGo/WebServerResources/ AliasMatch /SOGo/so/ControlPanel/Products/(.*)/Resources/(.*) \ - ${GNUSTEP_SYSTEM_LIBRARY}/SOGo-0.9/\$1.SOGo/Resources/\$2 + ${GNUSTEP_SYSTEM_LIBRARY}/SOGo/\$1.SOGo/Resources/\$2 <LocationMatch "^/SOGo*"> AddDefaultCharset UTF-8 @@ -104,7 +88,7 @@ pkg_postinst() { gnustep-base_pkg_postinst elog "Do not forget to enable the sope module in /etc/apache2/httpd.conf" - elog "Now follow the steps from the SOGo documentation:" + elog "Now follow the steps from the SOGo documentation, Configuration section:" elog "http://www.inverse.ca/contributions/sogo/documentation.html#c803" elog "The default port configured for sogo is 20000 (from 47_sogo.conf)" elog "The sogo user home directory is /var/lib/sogo" diff --git a/gnustep-libs/sope/Manifest b/gnustep-libs/sope/Manifest index 7a0e974..f6831dc 100644 --- a/gnustep-libs/sope/Manifest +++ b/gnustep-libs/sope/Manifest @@ -1,9 +1,5 @@ AUX sope-gsmake2.diff 101334 RMD160 727b743a40a4a4b794581a327a9c9370726f212a SHA1 d4749540fb043ef1679b9395689ed5d9ce12c8ea SHA256 1bdc3501f276c08b27cbc15812eb6a26bbe32d5ce0e25bbfb2cdfe39a852cbf6 -AUX sope-mime-nosort.diff 2556 RMD160 00369bafdf0464337796122bbc22b677c50541f5 SHA1 e10455ebd45de88e245f89c5103d41a854186db9 SHA256 6ddb2874c0cf3989abc976bc1e535d4a9af9c97667619de1ac8ea99e772021c7 -AUX sope-nsexception.patch 1139 RMD160 08268926bb3a54408f493637afe196be3788429b SHA1 3c59fbf9977d7fa58eb8e134c22b2b3f8fe3f333 SHA256 caa817651c0490b5d4ec105ee2aead667b6ded1cf53eddd44baf5cac272f8067 -AUX sope-patchset-r1621.diff 72909 RMD160 82fc9162f5892aa907355e860d59f7a4b6ffec91 SHA1 70bf987c82fe3943b2b53522d099e8157326969d SHA256 eb86e3ca689beb188d832021bcd854cbcbdee2d36618ee060ec08db9e75920e2 +AUX sope-patchset-r1660.diff 151778 RMD160 42cb686013f0276c42faea14d119a3586ba2ca27 SHA1 c784b9015fc66fc97fce3d17ad92452443899808 SHA256 58d710671bd825667e8524a13370d07cfa09616e44d93e7f6e942e31cf3e52a2 AUX sope-use_system_root.patch 548 RMD160 add8b03f06b20ae96676b4efe17af08e024eae4c SHA1 86d50d562f5a94d3ffbd408fd59cbec288c17eb6 SHA256 6ac0f18cd2b39ae40b490f0e61952f6c7eccdc7939a4c7f844d2a3967abf2e64 -DIST sope-trunk-r1621-200805211100.tar.gz 4223699 RMD160 9b09c70577e32fb94daced41853a1c30c1d3ed8c SHA1 1d152ff065146cb10e4cfd80523ddb21bddc52d2 SHA256 fc6516599e3c292b2c08989bb274d6ccadb036b8bd1fe550f33774f3b7ed9ada DIST sope-trunk-r1660-200906161500.tar.gz 4262397 RMD160 8f4c6236a9214462e371b4119d0cbbb1f8810a86 SHA1 d5c3da0325a23454878b8d782818324808809793 SHA256 479e8ab86a058c8e0e0ddcf636745be77a0b676a888318da19a8852875c35658 -EBUILD sope-4.7_pre20080521.ebuild 1561 RMD160 0c9d4706ca41730ecbaea725422bef3001191de2 SHA1 7f8bbe0528fb1cec2f60e649edc889bb86c04fc2 SHA256 9ca5a8977c0d6d3afff7d6a2e010e94369d8b19b4d08bfca96f2804a89f2bd7e -EBUILD sope-4.7_pre20090616.ebuild 1555 RMD160 18ed224a0e5494003b692b73c478c37bad2de07e SHA1 ed13b376d03a063f629a3c2b28e32a3c2b3f50b1 SHA256 e94f341cb9692f9b525a452351c84a59f287c82f1ffa1e70fdb07ba8168e5b64 +EBUILD sope-4.7_pre20090616.ebuild 1646 RMD160 2662c4cb12188ba290380de78b9d306cb1d0b4d1 SHA1 08b66edb159143a9c2bbd0e85f5c04a27ff7b30e SHA256 742cb4d1cada7b660f82d9d391df760677151f4d0b4ba5c94ff5dae22e8976d4 diff --git a/gnustep-libs/sope/files/sope-mime-nosort.diff b/gnustep-libs/sope/files/sope-mime-nosort.diff deleted file mode 100644 index 1ea4bf5..0000000 --- a/gnustep-libs/sope/files/sope-mime-nosort.diff +++ /dev/null @@ -1,69 +0,0 @@ -Index: sope-mime/NGImap4/NGImap4Client.m -=================================================================== ---- sope-mime/NGImap4/NGImap4Client.m (révision 1620) -+++ sope-mime/NGImap4/NGImap4Client.m (copie de travail) -@@ -1054,17 +1054,18 @@ - - if (![_encoding isNotNull]) _encoding = @"UTF-8"; - if (![_qualString isNotNull]) _qualString = @" ALL"; -+ -+ sortStr = @"FETCH 1:* UID"; -+// sortStr = [NSMutableString stringWithCapacity:128]; - -- sortStr = [NSMutableString stringWithCapacity:128]; -+// [sortStr appendString:@"UID SORT ("]; -+// if (_sort != nil) [sortStr appendString:_sort]; -+// [sortStr appendString:@") "]; - -- [sortStr appendString:@"UID SORT ("]; -- if (_sort != nil) [sortStr appendString:_sort]; -- [sortStr appendString:@") "]; -+// [sortStr appendString:_encoding]; /* eg 'UTF-8' */ - -- [sortStr appendString:_encoding]; /* eg 'UTF-8' */ -- - /* Note: this is _space sensitive_! to many spaces lead to error! */ -- [sortStr appendString:_qualString]; /* eg ' ALL' or ' TEXT "abc"' */ -+// [sortStr appendString:_qualString]; /* eg ' ALL' or ' TEXT "abc"' */ - - return [self->normer normalizeSortResponse:[self processCommand:sortStr]]; - } -Index: sope-mime/NGImap4/NGImap4Connection.m -=================================================================== ---- sope-mime/NGImap4/NGImap4Connection.m (révision 1620) -+++ sope-mime/NGImap4/NGImap4Connection.m (copie de travail) -@@ -456,7 +456,7 @@ - return nil; - } - -- uids = [result valueForKey:@"sort"]; -+ uids = [result valueForKey:@"fetch"]; - if (![uids isNotNull]) { - [self errorWithFormat:@"got no UIDs for URL: %@: %@", _url, result]; - return nil; -Index: sope-mime/NGImap4/NGImap4ResponseNormalizer.m -=================================================================== ---- sope-mime/NGImap4/NGImap4ResponseNormalizer.m (révision 1620) -+++ sope-mime/NGImap4/NGImap4ResponseNormalizer.m (copie de travail) -@@ -148,12 +148,18 @@ - /* filter for sort response (search : NSArray (msn)) */ - id obj; - NSMutableDictionary *result; -+ NSMutableArray *uids; -+ NSEnumerator *fetchEnum; - - result = [self normalizeResponse:_map]; -+ uids = [NSMutableArray array]; -+ -+ fetchEnum = [_map objectEnumeratorForKey:@"fetch"]; -+ while ((obj = [fetchEnum nextObject])) -+ [uids addObject: [obj objectForKey: @"uid"]]; - -- if ((obj = [[_map objectEnumeratorForKey:@"sort"] nextObject]) != nil) -- [result setObject:obj forKey:@"sort"]; -- -+ [result setObject: uids forKey:@"fetch"]; -+ - return result; - } - diff --git a/gnustep-libs/sope/files/sope-nsexception.patch b/gnustep-libs/sope/files/sope-nsexception.patch deleted file mode 100644 index 88ec27f..0000000 --- a/gnustep-libs/sope/files/sope-nsexception.patch +++ /dev/null @@ -1,35 +0,0 @@ ---- sope-mime/NGImap4/NGImap4Client.m.orig Tue Dec 4 11:00:36 2007 -+++ sope-mime/NGImap4/NGImap4Client.m Tue Jan 15 07:16:07 2008 -@@ -53,18 +53,6 @@ - - @end /* NGImap4Client(ConnectionRegistration); */ - --#if GNUSTEP_BASE_LIBRARY --/* FIXME: TODO: move someplace better (hh: NGExtensions...) */ --@implementation NSException(setUserInfo) -- --- (id)setUserInfo:(NSDictionary *)_userInfo { -- ASSIGN(self->_e_info, _userInfo); -- return self; --} -- --@end /* NSException(setUserInfo) */ --#endif -- - @interface NGImap4Client(Private) - - - (NSString *)_folder2ImapFolder:(NSString *)_folder; -@@ -967,9 +955,10 @@ static NSArray *Imap4SystemFlags = nil; - descr = @"Could not process qualifier for imap search "; - descr = [descr stringByAppendingString:reason]; - -- exception = [[NGImap4SearchException alloc] initWithFormat:@"%@", descr]; - ui = [NSDictionary dictionaryWithObject:_q forKey:@"qualifier"]; -- [exception setUserInfo:ui]; -+ exception = [[NSException alloc] initWithName:@"NGImap4SearchException" -+ reason:descr userInfo:ui]; -+ - [self->context setLastException:exception]; - [exception release]; - } - diff --git a/gnustep-libs/sope/files/sope-patchset-r1621.diff b/gnustep-libs/sope/files/sope-patchset-r1621.diff deleted file mode 100644 index 5f5c23d..0000000 --- a/gnustep-libs/sope/files/sope-patchset-r1621.diff +++ /dev/null @@ -1,2270 +0,0 @@ -Index: sope-gdl1/PostgreSQL/PostgreSQL72Channel.m -=================================================================== ---- sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (révision 1621) -+++ sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (copie de travail) -@@ -713,6 +713,39 @@ - return ms; - } - -+/* GCSEOAdaptorChannel protocol */ -+static NSString *sqlFolderFormat = (@"CREATE TABLE %@ (\n" \ -+ @" c_name VARCHAR (256) NOT NULL PRIMARY KEY,\n" -+ @" c_content VARCHAR (100000) NOT NULL,\n" -+ @" c_creationdate INT4 NOT NULL,\n" -+ @" c_lastmodified INT4 NOT NULL,\n" -+ @" c_version INT4 NOT NULL,\n" -+ @" c_deleted INT4 NULL\n" -+ @")"); -+static NSString *sqlFolderACLFormat = (@"CREATE TABLE %@ (\n" \ -+ @" c_uid VARCHAR (256) NOT NULL,\n" -+ @" c_object VARCHAR (256) NOT NULL,\n" -+ @" c_role VARCHAR (80) NOT NULL\n" -+ @")"); -+ -+- (NSException *) createGCSFolderTableWithName: (NSString *) tableName -+{ -+ NSString *sql; -+ -+ sql = [NSString stringWithFormat: sqlFolderFormat, tableName]; -+ -+ return [self evaluateExpressionX: sql]; -+} -+ -+- (NSException *) createGCSFolderACLTableWithName: (NSString *) tableName -+{ -+ NSString *sql; -+ -+ sql = [NSString stringWithFormat: sqlFolderACLFormat, tableName]; -+ -+ return [self evaluateExpressionX: sql]; -+} -+ - @end /* PostgreSQL72Channel */ - - @implementation PostgreSQL72Channel(PrimaryKeyGeneration) -Index: sope-gdl1/Oracle8/OracleAdaptorChannel.m -=================================================================== ---- sope-gdl1/Oracle8/OracleAdaptorChannel.m (révision 1621) -+++ sope-gdl1/Oracle8/OracleAdaptorChannel.m (copie de travail) -@@ -30,6 +30,7 @@ - - #import <NGExtensions/NSObject+Logs.h> - -+static BOOL debugOn = NO; - // - // - // -@@ -41,10 +42,19 @@ - - @implementation OracleAdaptorChannel (Private) - --- (void) _cleanup -++ (void) initialize - { -+ NSUserDefaults *ud; -+ -+ ud = [NSUserDefaults standardUserDefaults]; -+ debugOn = [ud boolForKey: @"OracleAdaptorDebug"]; -+} -+ -+- (void) _cleanup -+{ - column_info *info; - int c; -+ sword result; - - [_resultSetProperties removeAllObjects]; - -@@ -58,11 +68,29 @@ - // so we just free the value instead. - if (info->value) - { -- if (OCIDescriptorFree((dvoid *)info->value, (ub4)OCI_DTYPE_LOB) != OCI_SUCCESS) -+ if (info->type == SQLT_CLOB -+ || info->type == SQLT_BLOB -+ || info->type == SQLT_BFILEE -+ || info->type == SQLT_CFILEE) -+ { -+ result = OCIDescriptorFree((dvoid *)info->value, (ub4) OCI_DTYPE_LOB); -+ if (result != OCI_SUCCESS) -+ { -+ NSLog (@"value was not a LOB descriptor"); -+ abort(); -+ } -+ } -+ else - free(info->value); - info->value = NULL; - } -- free(info); -+ else -+ { -+ NSLog (@"trying to free an already freed value!"); -+ abort(); -+ } -+ free(info); -+ - [_row_buffer removeObjectAtIndex: c]; - } - -@@ -231,6 +259,9 @@ - - [self _cleanup]; - -+ if (debugOn) -+ [self logWithFormat: @"expression: %@", theExpression]; -+ - if (!theExpression || ![theExpression length]) - { - [NSException raise: @"OracleInvalidExpressionException" -@@ -302,7 +333,9 @@ - // We read the maximum width of a column - info->max_width = 0; - status = OCIAttrGet((dvoid*)param, (ub4)OCI_DTYPE_PARAM, (dvoid*)&(info->max_width), (ub4 *)0, (ub4)OCI_ATTR_DATA_SIZE, (OCIError *)_oci_err); -- -+ -+ if (debugOn) -+ NSLog(@"name: %s, type: %d", cname, info->type); - attribute = [EOAttribute attributeWithOracleType: info->type name: cname length: clen width: info->max_width]; - [_resultSetProperties addObject: attribute]; - -@@ -609,7 +642,7 @@ - - /* GCSEOAdaptorChannel protocol */ - static NSString *sqlFolderFormat = (@"CREATE TABLE %@ (\n" \ -- @" c_name VARCHAR2 (256) NOT NULL,\n" -+ @" c_name VARCHAR2 (256) NOT NULL PRIMARY KEY,\n" - @" c_content CLOB NOT NULL,\n" - @" c_creationdate INTEGER NOT NULL,\n" - @" c_lastmodified INTEGER NOT NULL,\n" -Index: sope-gdl1/Oracle8/OracleAdaptorChannelController.m -=================================================================== ---- sope-gdl1/Oracle8/OracleAdaptorChannelController.m (révision 1621) -+++ sope-gdl1/Oracle8/OracleAdaptorChannelController.m (copie de travail) -@@ -31,6 +31,8 @@ - #import <Foundation/Foundation.h> - #import <GDLAccess/EOSQLExpression.h> - -+static BOOL debugOn = NO; -+ - // - // - // -@@ -48,6 +50,14 @@ - // - @implementation OracleAdaptorChannelController - -++ (void) initialize -+{ -+ NSUserDefaults *ud; -+ -+ ud = [NSUserDefaults standardUserDefaults]; -+ debugOn = [ud boolForKey: @"OracleAdaptorDebug"]; -+} -+ - - (EODelegateResponse) adaptorChannel: (id) theChannel - willInsertRow: (NSMutableDictionary *) theRow - forEntity: (EOEntity *) theEntity -@@ -56,7 +66,8 @@ - NSArray *keys; - int i, c; - -- NSLog(@"willInsertRow: %@ %@", [theRow description], [theEntity description]); -+ if (debugOn) -+ NSLog(@"willInsertRow: %@ %@", [theRow description], [theEntity description]); - - s = AUTORELEASE([[NSMutableString alloc] init]); - -@@ -101,7 +112,8 @@ - NSArray *keys; - int i, c; - -- NSLog(@"willUpdatetRow: %@ %@", [theRow description], [theQualifier description]); -+ if (debugOn) -+ NSLog(@"willUpdateRow: %@ %@", [theRow description], [theQualifier description]); - - s = AUTORELEASE([[NSMutableString alloc] init]); - -Index: sope-mime/NGImap4/NGImap4Connection.m -=================================================================== ---- sope-mime/NGImap4/NGImap4Connection.m (révision 1621) -+++ sope-mime/NGImap4/NGImap4Connection.m (copie de travail) -@@ -381,7 +381,7 @@ - - if (debugCache) [self logWithFormat:@" no folders cached yet .."]; - -- result = [[self client] list:(onlyFetchInbox ? @"INBOX" : @"*") -+ result = [[self client] list:(onlyFetchInbox ? @"INBOX" : @"") - pattern:@"*"]; - if (![[result valueForKey:@"result"] boolValue]) { - [self errorWithFormat:@"Could not list mailbox hierarchy!"]; -Index: sope-mime/NGImap4/NGImap4ResponseNormalizer.m -=================================================================== ---- sope-mime/NGImap4/NGImap4ResponseNormalizer.m (révision 1621) -+++ sope-mime/NGImap4/NGImap4ResponseNormalizer.m (copie de travail) -@@ -648,14 +648,13 @@ - enumerator = [_flags objectEnumerator]; - cnt = 0; - while ((obj = [enumerator nextObject])) { -- if (![obj isNotEmpty]) -- continue; -- -- if (![[obj substringToIndex:1] isEqualToString:@"\\"]) -- continue; -- -- objs[cnt] = [obj substringFromIndex:1]; -- cnt++; -+ if ([obj isNotEmpty]) { -+ if ([obj hasPrefix:@"\\"]) -+ objs[cnt] = [obj substringFromIndex:1]; -+ else -+ objs[cnt] = obj; -+ cnt++; -+ } - } - result = [NSArray arrayWithObjects:objs count:cnt]; - if (objs) free(objs); -Index: sope-mime/NGImap4/NGImap4ResponseParser.m -=================================================================== ---- sope-mime/NGImap4/NGImap4ResponseParser.m (révision 1621) -+++ sope-mime/NGImap4/NGImap4ResponseParser.m (copie de travail) -@@ -84,6 +84,8 @@ - static NSDictionary *_parseMultipartBody(NGImap4ResponseParser *self, - BOOL isBodyStructure); - -+static NSArray *_parseLanguages(); -+ - static NSString *_parseBodyString(NGImap4ResponseParser *self, - BOOL _convertString); - static NSString *_parseBodyDecodeString(NGImap4ResponseParser *self, -@@ -111,6 +113,7 @@ - static NSNumber *_parseUnsigned(NGImap4ResponseParser *self); - static NSString *_parseUntil(NGImap4ResponseParser *self, char _c); - static NSString *_parseUntil2(NGImap4ResponseParser *self, char _c1, char _c2); -+static BOOL _endsWithCQuote(NSString *_string); - - static __inline__ NSException *_consumeIfMatch - (NGImap4ResponseParser *self, unsigned char _m); -@@ -649,12 +652,35 @@ - } - - - (NSString *)_parseQuotedString { -+ NSMutableString *quotedString; -+ NSString *tmpString; -+ BOOL stop; -+ - /* parse a quoted string, eg '"' */ - if (_la(self, 0) == '"') { - _consume(self, 1); -- return _parseUntil(self, '"'); -+ quotedString = [NSMutableString string]; -+ stop = NO; -+ while (!stop) { -+ tmpString = _parseUntil(self, '"'); -+ [quotedString appendString: tmpString]; -+ if(_endsWithCQuote(tmpString)) { -+ [quotedString deleteSuffix: @"\\"]; -+ [quotedString appendString: @"\""]; -+ } -+ else { -+ stop = YES; -+ } -+ } - } -- return nil; -+ else { -+ quotedString = nil; -+ } -+ -+ [quotedString replaceString:@"?=\t=?" -+ withString:@"?==?"]; -+ -+ return quotedString; - } - - (void)_consumeOptionalSpace { - if (_la(self, 0) == ' ') _consume(self, 1); -@@ -1185,7 +1211,7 @@ - route = [self _parseQuotedStringOrNIL]; [self _consumeOptionalSpace]; - mailbox = [self _parseQuotedStringOrNIL]; [self _consumeOptionalSpace]; - host = [self _parseQuotedStringOrNIL]; [self _consumeOptionalSpace]; -- -+ - if (_la(self, 0) != ')') { - [self logWithFormat:@"WARNING: IMAP4 envelope " - @"address not properly closed (c0=%c,c1=%c): %@", -@@ -1197,6 +1223,7 @@ - address = [[NGImap4EnvelopeAddress alloc] initWithPersonalName:pname - sourceRoute:route mailbox:mailbox - host:host]; -+ - return address; - } - -@@ -1594,8 +1621,11 @@ - if (_decode) - data = [data decodeQuotedPrintableValueOfMIMEHeaderField:nil]; - -- return [[[StrClass alloc] initWithData:data encoding:encoding] -- autorelease]; -+ if ([data isKindOfClass: [NSString class]]) -+ return (NSString *) data; -+ else -+ return [[[StrClass alloc] initWithData:data encoding:encoding] -+ autorelease]; - } - else { - str = _parseUntil2(self, ' ', ')'); -@@ -1620,13 +1650,35 @@ - return str; - } - -- - static NSString *_parseBodyString(NGImap4ResponseParser *self, - BOOL _convertString) - { - return _parseBodyDecodeString(self, _convertString, NO /* no decode */); - } - -+static NSArray *_parseLanguages(NGImap4ResponseParser *self) { -+ NSMutableArray *languages; -+ NSString *language; -+ -+ languages = [NSMutableArray array]; -+ if (_la(self, 0) == '(') { -+ while (_la(self, 0) != ')') { -+ _consume(self,1); -+ language = _parseBodyString(self, YES); -+ if ([language length]) -+ [languages addObject: language]; -+ } -+ _consume(self,1); -+ } -+ else { -+ language = _parseBodyString(self, YES); -+ if ([language length]) -+ [languages addObject: language]; -+ } -+ -+ return languages; -+} -+ - static NSDictionary *_parseBodyParameterList(NGImap4ResponseParser *self) - { - NSMutableDictionary *list; -@@ -1646,7 +1698,7 @@ - _consumeIfMatch(self, ' '); - value = _parseBodyDecodeString(self, YES, YES); - -- [list setObject:value forKey:[key lowercaseString]]; -+ if (value) [list setObject:value forKey:[key lowercaseString]]; - } - _consumeIfMatch(self, ')'); - } -@@ -1734,10 +1786,11 @@ - *encoding, *bodysize; - NSDictionary *parameterList; - NSMutableDictionary *dict; -+ NSArray *languages; - - type = [_parseBodyString(self, YES) lowercaseString]; - _consumeIfMatch(self, ' '); -- subtype = _parseBodyString(self, YES); -+ subtype = [_parseBodyString(self, YES) lowercaseString]; - _consumeIfMatch(self, ' '); - parameterList = _parseBodyParameterList(self); - _consumeIfMatch(self, ' '); -@@ -1762,7 +1815,8 @@ - _consumeIfMatch(self, ' '); - [dict setObject:_parseBodyString(self, YES) forKey:@"lines"]; - } -- else if ([type isEqualToString:@"message"]) { -+ else if ([type isEqualToString:@"message"] -+ && [subtype isEqualToString:@"rfc822"]) { - if (_la(self, 0) != ')') { - _consumeIfMatch(self, ' '); - _consumeIfMatch(self, '('); -@@ -1805,14 +1859,9 @@ - forKey: @"disposition"]; - if (_la(self, 0) != ')') { - _consume(self,1); -- if (_la(self, 0) == '(') { -- [dict setObject: _parseBodyParameterList(self) -- forKey: @"language"]; -- } -- else { -- [dict setObject: _parseBodyString(self, YES) -- forKey: @"language"]; -- } -+ languages = _parseLanguages(self); -+ if ([languages count]) -+ [dict setObject: languages forKey: @"languages"]; - if (_la(self, 0) != ')') { - _consume(self,1); - [dict setObject: _parseBodyString(self, YES) -@@ -1829,6 +1878,7 @@ - static NSDictionary *_parseMultipartBody(NGImap4ResponseParser *self, - BOOL isBodyStructure) { - NSMutableArray *parts; -+ NSArray *languages; - NSString *kind; - NSMutableDictionary *dict; - -@@ -1854,14 +1904,9 @@ - forKey: @"disposition"]; - if (_la(self, 0) != ')') { - _consume(self,1); -- if (_la(self, 0) == '(') { -- [dict setObject: _parseBodyParameterList(self) -- forKey: @"language"]; -- } -- else { -- [dict setObject: _parseBodyString(self, YES) -- forKey: @"language"]; -- } -+ languages = _parseLanguages(self); -+ if ([languages count]) -+ [dict setObject: languages forKey: @"languages"]; - if (_la(self, 0) != ')') { - _consume(self,1); - [dict setObject: _parseBodyString(self, YES) -@@ -2170,6 +2215,21 @@ - } - } - -+static BOOL _endsWithCQuote(NSString *_string){ -+ unsigned int quoteSlashes; -+ int pos; -+ -+ quoteSlashes = 0; -+ pos = [_string length] - 1; -+ while (pos > -1 -+ && [_string characterAtIndex: pos] == '\\') { -+ quoteSlashes++; -+ pos--; -+ } -+ -+ return ((quoteSlashes % 2) == 1); -+} -+ - - (NSException *)exceptionForFailedMatch:(unsigned char)_match - got:(unsigned char)_avail - { -Index: sope-mime/NGMail/NGSmtpClient.m -=================================================================== ---- sope-mime/NGMail/NGSmtpClient.m (révision 1621) -+++ sope-mime/NGMail/NGSmtpClient.m (copie de travail) -@@ -24,6 +24,82 @@ - #include "NGSmtpReplyCodes.h" - #include "common.h" - -+// -+// Useful extension that comes from Pantomime which is also -+// released under the LGPL. -+// -+@interface NSMutableData (DataCleanupExtension) -+ -+- (NSRange) rangeOfCString: (const char *) theCString; -+- (NSRange) rangeOfCString: (const char *) theCString -+ options: (unsigned int) theOptions -+ range: (NSRange) theRange; -+@end -+ -+@implementation NSMutableData (DataCleanupExtension) -+ -+- (NSRange) rangeOfCString: (const char *) theCString -+{ -+ return [self rangeOfCString: theCString -+ options: 0 -+ range: NSMakeRange(0,[self length])]; -+} -+ -+-(NSRange) rangeOfCString: (const char *) theCString -+ options: (unsigned int) theOptions -+ range: (NSRange) theRange -+{ -+ const char *b, *bytes; -+ int i, len, slen; -+ -+ if (!theCString) -+ { -+ return NSMakeRange(NSNotFound,0); -+ } -+ -+ bytes = [self bytes]; -+ len = [self length]; -+ slen = strlen(theCString); -+ -+ b = bytes; -+ -+ if (len > theRange.location + theRange.length) -+ { -+ len = theRange.location + theRange.length; -+ } -+ -+ if (theOptions == NSCaseInsensitiveSearch) -+ { -+ i = theRange.location; -+ b += i; -+ -+ for (; i <= len-slen; i++, b++) -+ { -+ if (!strncasecmp(theCString,b,slen)) -+ { -+ return NSMakeRange(i,slen); -+ } -+ } -+ } -+ else -+ { -+ i = theRange.location; -+ b += i; -+ -+ for (; i <= len-slen; i++, b++) -+ { -+ if (!memcmp(theCString,b,slen)) -+ { -+ return NSMakeRange(i,slen); -+ } -+ } -+ } -+ -+ return NSMakeRange(NSNotFound,0); -+} -+ -+@end -+ - @interface NGSmtpClient(PrivateMethods) - - (void)_fetchExtensionInfo; - @end -@@ -429,7 +505,9 @@ - - - (BOOL)sendData:(NSData *)_data { - NGSmtpResponse *reply = nil; -- -+ NSMutableData *cleaned_data; -+ NSRange r1, r2; -+ - [self requireState:NGSmtpState_TRANSACTION]; - - reply = [self sendCommand:@"DATA"]; -@@ -441,11 +519,54 @@ - } - [self->text flush]; - -+ cleaned_data = [NSMutableData dataWithData: _data]; -+ -+ // -+ // According to RFC 2821 section 4.5.2, we must check for the character -+ // sequence "<CRLF>.<CRLF>"; any occurrence have its period duplicated -+ // to avoid data transparency. -+ // -+ // The following code was copied from Pantomime (and also the one -+ // that strips Bcc: headers from the mail's content) -+ // -+ r1 = [cleaned_data rangeOfCString: "\r\n."]; -+ -+ while (r1.location != NSNotFound) -+ { -+ [cleaned_data replaceBytesInRange: r1 withBytes: "\r\n.." length: 4]; -+ -+ r1 = [cleaned_data rangeOfCString: "\r\n." -+ options: 0 -+ range: NSMakeRange(NSMaxRange(r1)+1, [cleaned_data length]-NSMaxRange(r1)-1)]; -+ } -+ -+ // -+ // We now look for the Bcc: header. If it is present, we remove it. -+ // Some servers, like qmail, do not remove it automatically. -+ // -+ r1 = [cleaned_data rangeOfCString: "\r\n\r\n"]; -+ r1 = [cleaned_data rangeOfCString: "\r\nBcc: " -+ options: 0 -+ range: NSMakeRange(0,r1.location-1)]; -+ -+ if (r1.location != NSNotFound) -+ { -+ // We search for the first \r\n AFTER the Bcc: header and -+ // replace the whole thing with \r\n. -+ r2 = [cleaned_data rangeOfCString: "\r\n" -+ options: 0 -+ range: NSMakeRange(NSMaxRange(r1)+1,[cleaned_data length]-NSMaxRange(r1)-1)]; -+ [cleaned_data replaceBytesInRange: NSMakeRange(r1.location, NSMaxRange(r2)-r1.location) -+ withBytes: "\r\n" -+ length: 2]; -+ } -+ -+ - if (self->isDebuggingEnabled) -- [NGTextErr writeFormat:@"C: data(%i bytes) ..\n", [_data bytes]]; -+ [NGTextErr writeFormat:@"C: data(%i bytes) ..\n", [cleaned_data length]]; - -- [self->connection safeWriteBytes:[_data bytes] count:[_data length]]; -- [self->connection safeWriteBytes:".\r\n" count:3]; -+ [self->connection safeWriteBytes:[cleaned_data bytes] count:[cleaned_data length]]; -+ [self->connection safeWriteBytes:"\r\n.\r\n" count:5]; - [self->connection flush]; - - reply = [self receiveReply]; -Index: sope-mime/NGMail/NGMailAddressParser.h -=================================================================== ---- sope-mime/NGMail/NGMailAddressParser.h (révision 1621) -+++ sope-mime/NGMail/NGMailAddressParser.h (copie de travail) -@@ -24,7 +24,9 @@ - - #import <Foundation/NSObject.h> - --@class NSData, NSString, NSArray; -+#import <Foundation/NSString.h> -+ -+@class NSData, NSArray; - @class NGMailAddressList; - - /* -@@ -34,16 +36,16 @@ - @interface NGMailAddressParser : NSObject - { - @private -- unsigned char *data; -- int dataPos; -- int errorPos; -- int maxLength; -+ unichar *data; -+ int dataPos; -+ int errorPos; -+ int maxLength; - } - - + (id)mailAddressParserWithString:(NSString *)_string; - + (id)mailAddressParserWithData:(NSData *)_data; --+ (id)mailAddressParserWithCString:(char *)_cString; --- (id)initWithCString:(const unsigned char *)_cstr length:(int unsigned)_len; -++ (id)mailAddressParserWithCString:(const char *)_cString; -+- (id)initWithString:(NSString *)_str; - - /* parsing */ - -Index: sope-mime/NGMail/NGMimeMessageGenerator.m -=================================================================== ---- sope-mime/NGMail/NGMimeMessageGenerator.m (révision 1621) -+++ sope-mime/NGMail/NGMimeMessageGenerator.m (copie de travail) -@@ -86,37 +86,40 @@ - char *des = NULL; - unsigned int cnt; - BOOL doEnc; -- NSString *str; -+// NSString *str; - - // TODO: this s***s big time! -+// NSLog (@"class: '%@'", NSStringFromClass ([_data class])); -+// #if APPLE_Foundation_LIBRARY || NeXT_Foundation_LIBRARY -+// str = [[NSString alloc] initWithData:_data -+// encoding:NSISOLatin1StringEncoding]; -+// str = [str autorelease]; -+ -+// #else -+// str = [[NSString alloc] initWithData:_data -+// encoding:NSISOLatin9StringEncoding]; -+// #endif -+// bytes = [str cString]; -+// length = [str cStringLength]; - --#if APPLE_Foundation_LIBRARY || NeXT_Foundation_LIBRARY -- str = [[NSString alloc] initWithData:_data -- encoding:NSISOLatin1StringEncoding]; --#else -- str = [[NSString alloc] initWithData:_data -- encoding:NSISOLatin9StringEncoding]; --#endif -- str = [str autorelease]; -- -- bytes = [str cString]; -- length = [str cStringLength]; -- -+ bytes = [_data bytes]; -+ length = [_data length]; -+ - /* check whether we need to encode */ -- -- for (cnt = 0, doEnc = NO; cnt < length; cnt++) { -- if ((unsigned char)bytes[cnt] > 127) { -+ cnt = 0; -+ doEnc = NO; -+ while (!doEnc && cnt < length) -+ if ((unsigned char)bytes[cnt] > 127) - doEnc = YES; -- break; -- } -- } -- -+ else -+ cnt++; -+ - if (!doEnc) - return _data; - - /* encode quoted printable */ - { -- char iso[] = "=?iso-8859-15?q?"; -+ char iso[] = "=?utf-8?q?"; - unsigned isoLen = 16; - char isoEnd[] = "?="; - unsigned isoEndLen = 2; -Index: sope-mime/NGMail/NGMailAddressParser.m -=================================================================== ---- sope-mime/NGMail/NGMailAddressParser.m (révision 1621) -+++ sope-mime/NGMail/NGMailAddressParser.m (copie de travail) -@@ -52,9 +52,9 @@ - StrClass = [NSString class]; - } - --static inline NSString *mkStrObj(const unsigned char *s, unsigned int l) { -+static inline NSString *mkStrObj(const unichar *s, unsigned int l) { - // TODO: unicode -- return [(NSString *)[StrClass alloc] initWithCString:(char *)s length:l]; -+ return [(NSString *)[StrClass alloc] initWithCharacters:s length:l]; - } - - static inline id parseWhiteSpaces(NGMailAddressParser *self, BOOL _guessMode) { -@@ -84,7 +84,7 @@ - int keepPos = self->dataPos; // keep reference for backtracking - id returnValue = nil; - BOOL isAtom = YES; -- unsigned char text[self->maxLength + 2]; // token text -+ unichar text[self->maxLength + 2]; // token text - int length = 0; // token text length - BOOL done = NO; - -@@ -162,7 +162,7 @@ - int keepPos = self->dataPos; // keep reference for backtracking - id returnValue = nil; - BOOL isQText = YES; -- unsigned char text[self->maxLength + 4]; // token text -+ unichar text[self->maxLength + 4]; // token text - int length = 0; // token text length - BOOL done = YES; - -@@ -215,7 +215,7 @@ - int keepPos = self->dataPos; // keep reference for backtracking - id returnValue = nil; - BOOL isDText = YES; -- unsigned char text[self->maxLength]; // token text -+ unichar text[self->maxLength]; // token text - int length = 0; // token text length - BOOL done = YES; - -@@ -320,42 +320,47 @@ - /* constructors */ - - + (id)mailAddressParserWithData:(NSData *)_data { -- return [[(NGMailAddressParser *)[self alloc] -- initWithCString:[_data bytes] -- length:[_data length]] autorelease]; -+ NSString *uniString; -+ -+ uniString = [NSString stringWithCharacters:(unichar *)[_data bytes] -+ length:([_data length] / sizeof(unichar))]; -+ -+ return [(NGMailAddressParser *)self mailAddressParserWithString:uniString]; - } -+ - + (id)mailAddressParserWithCString:(char *)_cString { -- return [[(NGMailAddressParser *)[self alloc] -- initWithCString:(unsigned char *)_cString -- length:strlen(_cString)] autorelease]; -+ NSString *nsCString; -+ -+ nsCString = [NSString stringWithCString:_cString]; -+ -+ return [(NGMailAddressParser *)self mailAddressParserWithString:nsCString]; - } --- (id)initWithCString:(const unsigned char *)_cstr length:(int unsigned)_len { -+ -++ (id)mailAddressParserWithString:(NSString *)_string { -+ return [[(NGMailAddressParser *)[self alloc] initWithString:_string] -+ autorelease]; -+} -+ -+- (id)initWithString:(NSString *)_str { - if ((self = [super init])) { - // TODO: remember some string encoding? -- self->data = (unsigned char *)_cstr; -- self->maxLength = _len; -+ self->maxLength = [_str length]; -+ self->data = malloc(self->maxLength*sizeof(unichar)); -+ [_str getCharacters:self->data]; - self->dataPos = 0; - self->errorPos = -1; - } - return self; - } - --- (id)initWithString:(NSString *)_str { -- // TODO: unicode -- return [self initWithCString:(unsigned char *)[_str cString] -- length:[_str cStringLength]]; --} -- - - (id)init { -- return [self initWithCString:NULL length:0]; -+ return [self initWithString:nil]; - } - --+ (id)mailAddressParserWithString:(NSString *)_string { -- return [[(NGMailAddressParser *)[self alloc] initWithString:_string] -- autorelease]; --} -- - - (void)dealloc { -+ if (self->data != NULL) { -+ free(self->data); -+ } - self->data = NULL; - self->maxLength = 0; - self->dataPos = 0; -Index: sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m -=================================================================== ---- sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m (révision 1621) -+++ sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m (copie de travail) -@@ -19,88 +19,45 @@ - 02111-1307, USA. - */ - -+#ifdef HAVE_STRNDUP -+#define _GNU_SOURCE 1 -+#endif -+ -+#include <string.h> -+ - #include "NGMimeHeaderFieldParser.h" - #include "NGMimeHeaderFields.h" - #include "NGMimeUtilities.h" - #include "common.h" --#include <string.h> - -+#ifndef HAVE_STRNDUP -+char *strndup(const char *str, size_t len) -+{ -+ char *dup = (char *)malloc(len+1); -+ if (dup) { -+ strncpy(dup,str,len); -+ dup[len]= '\0'; -+ } -+ return dup; -+} -+#endif -+ - @implementation NGMimeRFC822DateHeaderFieldParser - --static Class CalDateClass = Nil; --static NSTimeZone *gmt = nil; --static NSTimeZone *gmt01 = nil; --static NSTimeZone *gmt02 = nil; --static NSTimeZone *gmt03 = nil; --static NSTimeZone *gmt04 = nil; --static NSTimeZone *gmt05 = nil; --static NSTimeZone *gmt06 = nil; --static NSTimeZone *gmt07 = nil; --static NSTimeZone *gmt08 = nil; --static NSTimeZone *gmt09 = nil; --static NSTimeZone *gmt10 = nil; --static NSTimeZone *gmt11 = nil; --static NSTimeZone *gmt12 = nil; --static NSTimeZone *gmt0530 = nil; --static NSTimeZone *gmtM01 = nil; --static NSTimeZone *gmtM02 = nil; --static NSTimeZone *gmtM03 = nil; --static NSTimeZone *gmtM04 = nil; --static NSTimeZone *gmtM05 = nil; --static NSTimeZone *gmtM06 = nil; --static NSTimeZone *gmtM07 = nil; --static NSTimeZone *gmtM08 = nil; --static NSTimeZone *gmtM09 = nil; --static NSTimeZone *gmtM10 = nil; --static NSTimeZone *gmtM11 = nil; --static NSTimeZone *gmtM12 = nil; --static NSTimeZone *gmtM13 = nil; --static NSTimeZone *gmtM14 = nil; --static NSTimeZone *met = nil; -+static NSTimeZone *gmt = nil; -+static NSTimeZone *met = nil; - - + (int)version { - return 2; - } -+ - + (void)initialize { - static BOOL didInit = NO; -- Class TzClass; - if (didInit) return; - didInit = YES; - -- CalDateClass = [NSCalendarDate class]; -- -- /* timezones which were actually used in a maillist mailbox */ -- TzClass = [NSTimeZone class]; -- gmt = [[TzClass timeZoneWithName:@"GMT"] retain]; -- met = [[TzClass timeZoneWithName:@"MET"] retain]; -- gmt01 = [[TzClass timeZoneForSecondsFromGMT: 1 * (60 * 60)] retain]; -- gmt02 = [[TzClass timeZoneForSecondsFromGMT: 2 * (60 * 60)] retain]; -- gmt03 = [[TzClass timeZoneForSecondsFromGMT: 3 * (60 * 60)] retain]; -- gmt04 = [[TzClass timeZoneForSecondsFromGMT: 4 * (60 * 60)] retain]; -- gmt05 = [[TzClass timeZoneForSecondsFromGMT: 5 * (60 * 60)] retain]; -- gmt06 = [[TzClass timeZoneForSecondsFromGMT: 6 * (60 * 60)] retain]; -- gmt07 = [[TzClass timeZoneForSecondsFromGMT: 7 * (60 * 60)] retain]; -- gmt08 = [[TzClass timeZoneForSecondsFromGMT: 8 * (60 * 60)] retain]; -- gmt09 = [[TzClass timeZoneForSecondsFromGMT: 9 * (60 * 60)] retain]; -- gmt10 = [[TzClass timeZoneForSecondsFromGMT: 10 * (60 * 60)] retain]; -- gmt11 = [[TzClass timeZoneForSecondsFromGMT: 11 * (60 * 60)] retain]; -- gmt12 = [[TzClass timeZoneForSecondsFromGMT: 12 * (60 * 60)] retain]; -- gmtM01 = [[TzClass timeZoneForSecondsFromGMT: -1 * (60 * 60)] retain]; -- gmtM02 = [[TzClass timeZoneForSecondsFromGMT: -2 * (60 * 60)] retain]; -- gmtM03 = [[TzClass timeZoneForSecondsFromGMT: -3 * (60 * 60)] retain]; -- gmtM04 = [[TzClass timeZoneForSecondsFromGMT: -4 * (60 * 60)] retain]; -- gmtM05 = [[TzClass timeZoneForSecondsFromGMT: -5 * (60 * 60)] retain]; -- gmtM06 = [[TzClass timeZoneForSecondsFromGMT: -6 * (60 * 60)] retain]; -- gmtM07 = [[TzClass timeZoneForSecondsFromGMT: -7 * (60 * 60)] retain]; -- gmtM08 = [[TzClass timeZoneForSecondsFromGMT: -8 * (60 * 60)] retain]; -- gmtM09 = [[TzClass timeZoneForSecondsFromGMT: -9 * (60 * 60)] retain]; -- gmtM10 = [[TzClass timeZoneForSecondsFromGMT:-10 * (60 * 60)] retain]; -- gmtM11 = [[TzClass timeZoneForSecondsFromGMT:-11 * (60 * 60)] retain]; -- gmtM12 = [[TzClass timeZoneForSecondsFromGMT:-12 * (60 * 60)] retain]; -- gmtM13 = [[TzClass timeZoneForSecondsFromGMT:-13 * (60 * 60)] retain]; -- gmtM14 = [[TzClass timeZoneForSecondsFromGMT:-14 * (60 * 60)] retain]; -- -- gmt0530 = [[TzClass timeZoneForSecondsFromGMT:5 * (60*60) + (30*60)] retain]; -+ gmt = [[NSTimeZone timeZoneWithName:@"GMT"] retain]; -+ met = [[NSTimeZone timeZoneWithName:@"MET"] retain]; - } - - /* -@@ -147,162 +104,110 @@ - } - } - --static NSTimeZone *parseTimeZone(unsigned char *s, unsigned int len) { -+static int offsetFromTZAbbreviation(const char **p) { -+ NSString *abbreviation; -+ NSTimeZone *offsetTZ; -+ unsigned int length; -+ -+ length = 0; -+ while (isalpha(*(*p+length))) -+ length++; -+ abbreviation = [[NSString alloc] initWithBytes: *p -+ length: length - 1 -+ encoding: NSASCIIStringEncoding]; -+ offsetTZ = [NSTimeZone timeZoneWithAbbreviation: abbreviation]; -+ [abbreviation release]; -+ *p += length; -+ -+ return [offsetTZ secondsFromGMT]; -+} -+ -+static inline char *digitsString(const char *string) { -+ const char *p; -+ unsigned int len; -+ -+ p = string; -+ while (!isdigit(*p)) -+ p++; -+ len = 0; -+ while (isdigit(*(p + len))) -+ len++; -+ -+ return strndup(p, len); -+} -+ -+static NSTimeZone *parseTimeZone(const char *s, unsigned int len) { - /* - WARNING: failed to parse RFC822 timezone: '+0530' \ - (value='Tue, 13 Jul 2004 21:39:28 +0530') - TODO: this is because libFoundation doesn't accept 'GMT+0530' as input. - */ -- char *p = (char *)s; -+ char *newString, *digits; -+ const char *p; - NSTimeZone *tz; -- NSString *ts; -- -- if (len == 0) -- return nil; -- -- if (*s == '+' || *s == '-') { -- if (len == 3) { -- if (p[1] == '0' && p[2] == '0') // '+00' or '-00' -- return gmt; -- if (*s == '+') { -- if (p[1] == '0' && p[2] == '1') // '+01' -- return gmt01; -- if (p[1] == '0' && p[2] == '2') // '+02' -- return gmt02; -- } -- } -- else if (len == 5) { -- if (p[3] == '0' && p[4] == '0' && p[1] == '0') { // '?0x00' -- if (p[2] == '0') // '+0000' -- return gmt; -- -- if (*s == '+') { -- if (p[2] == '1') return gmt01; // '+0100' -- if (p[2] == '2') return gmt02; // '+0200' -- if (p[2] == '3') return gmt03; // '+0300' -- if (p[2] == '4') return gmt04; // '+0400' -- if (p[2] == '5') return gmt05; // '+0500' -- if (p[2] == '6') return gmt06; // '+0600' -- if (p[2] == '7') return gmt07; // '+0700' -- if (p[2] == '8') return gmt08; // '+0800' -- if (p[2] == '9') return gmt09; // '+0900' -- } -- else if (*s == '-') { -- if (p[2] == '1') return gmtM01; // '-0100' -- if (p[2] == '2') return gmtM02; // '-0200' -- if (p[2] == '3') return gmtM03; // '-0300' -- if (p[2] == '4') return gmtM04; // '-0400' -- if (p[2] == '5') return gmtM05; // '-0500' -- if (p[2] == '6') return gmtM06; // '-0600' -- if (p[2] == '7') return gmtM07; // '-0700' -- if (p[2] == '8') return gmtM08; // '-0800' -- if (p[2] == '9') return gmtM09; // '-0900' -- } -- } -- else if (p[3] == '0' && p[4] == '0' && p[1] == '1') { // "?1x00" -- if (*s == '+') { -- if (p[2] == '0') return gmt10; // '+1000' -- if (p[2] == '1') return gmt11; // '+1100' -- if (p[2] == '2') return gmt12; // '+1200' -- } -- else if (*s == '-') { -- if (p[2] == '0') return gmtM10; // '-1000' -- if (p[2] == '1') return gmtM11; // '-1100' -- if (p[2] == '2') return gmtM12; // '-1200' -- if (p[2] == '3') return gmtM13; // '-1300' -- if (p[2] == '4') return gmtM14; // '-1400' -- } -- } -- -- /* special case for GMT+0530 */ -- if (strncmp((char *)s, "+0530", 5) == 0) -- return gmt0530; -- } -- else if (len == 7) { -- /* -- "MultiMail" submits timezones like this: -- "Tue, 9 Mar 2004 9:43:00 -05-500", -- don't know what the "-500" trailer is supposed to mean? Apparently -- Thunderbird just uses the "-05", so do we. -- */ -- -- if (isdigit(p[1]) && isdigit(p[2]) && (p[3] == '-'||p[3] == '+')) { -- unsigned char tmp[8]; -- -- strncpy((char *)tmp, p, 3); -- tmp[3] = '0'; -- tmp[4] = '0'; -- tmp[5] = '\0'; -- return parseTimeZone(tmp, 5); -- } -- } -+ unsigned int hours, minutes, seconds, remaining; -+ int sign; -+ -+ sign = 1; -+ hours = 0; -+ minutes = 0; -+ seconds = 0; -+ -+ newString = strndup(s, len); -+ p = newString; -+ -+ if (isalpha(*p)) -+ seconds = offsetFromTZAbbreviation(&p); -+ while (isspace(*p)) -+ p++; -+ while (*p == '+' || *p == '-') { -+ if (*p == '-') -+ sign = -sign; -+ p++; - } -- else if (*s == '0') { -- if (len == 2) { // '00' -- if (p[1] == '0') return gmt; -- if (p[1] == '1') return gmt01; -- if (p[1] == '2') return gmt02; -- } -- else if (len == 4) { -- if (p[2] == '0' && p[3] == '0') { // '0x00' -- if (p[1] == '0') return gmt; -- if (p[1] == '1') return gmt01; -- if (p[1] == '2') return gmt02; -- } -- } -+ digits = digitsString(p); -+ p = digits; -+ remaining = strlen(p); -+ switch(remaining) { -+ case 6: /* hhmmss */ -+ seconds += (10 * (*(p + remaining - 2) - 48) -+ + *(p + remaining - 1) - 48); -+ case 4: /* hhmm */ -+ hours += 10 * (*p - 48); -+ p++; -+ case 3: /* hmm */ -+ hours += (*p - 48); -+ p++; -+ minutes += 10 * (*p - 48) + *(p + 1) - 48; -+ break; -+ case 2: /* hh */ -+ hours += 10 * (*p - 48) + *(p + 1) - 48; -+ break; -+ default: -+ NSLog (@"parseTimeZone: cannot parse time notation '%s'", newString); - } -- else if (len == 3) { -- if (strcasecmp((char *)s, "GMT") == 0) return gmt; -- if (strcasecmp((char *)s, "UTC") == 0) return gmt; -- if (strcasecmp((char *)s, "MET") == 0) return met; -- if (strcasecmp((char *)s, "CET") == 0) return met; -- } -- -- if (isalpha(*s)) { -- ts = [[NSString alloc] initWithCString:(char *)s length:len]; -- } -- else { -- char buf[len + 5]; -- -- buf[0] = 'G'; buf[1] = 'M'; buf[2] = 'T'; -- if (*s == '+' || *s == '-') { -- strcpy(&(buf[3]), (char *)s); -- } -- else { -- buf[3] = '+'; -- strcpy(&(buf[4]), (char *)s); -- } -- ts = [[NSString alloc] initWithCString:buf]; -- } --#if 1 -- NSLog(@"%s: RFC822 TZ Parser: expensive: '%@'", __PRETTY_FUNCTION__, ts); --#endif -- tz = [NSTimeZone timeZoneWithAbbreviation:ts]; -- [ts release]; -+ free(digits); -+ -+ seconds += sign * (3600 * hours + 60 * minutes); -+ tz = [NSTimeZone timeZoneForSecondsFromGMT: seconds]; -+ free(newString); -+ - return tz; - } - - - (id)parseValue:(id)_data ofHeaderField:(NSString *)_field { - // TODO: use UNICODE - NSCalendarDate *date = nil; -- unsigned char buf[256]; -- unsigned char *bytes = buf, *pe; -+ unsigned char *bytes, *pe; - unsigned length = 0; - NSTimeZone *tz = nil; - char dayOfMonth, monthOfYear, hour, minute, second; - short year; - BOOL flag; -- -- if ((length = [_data cStringLength]) > 254) { -- [self logWithFormat: -- @"header field value to large for date parsing: '%@'(%i)", -- _data, length]; -- length = 254; -- } -- -- [_data getCString:(char *)buf maxLength:length]; -- buf[length] = '\0'; -- -+ -+ length = [_data lengthOfBytesUsingEncoding: NSASCIIStringEncoding]; -+ bytes = [_data cStringUsingEncoding: NSASCIIStringEncoding]; -+ - /* remove leading chars (skip to first digit, the day of the month) */ - while (length > 0 && (!isdigit(*bytes))) { - bytes++; -@@ -312,7 +217,7 @@ - if (length == 0) { - NSLog(@"WARNING(%s): empty value for header field %@ ..", - __PRETTY_FUNCTION__, _field); -- return [CalDateClass date]; -+ return [NSCalendarDate date]; - } - - // TODO: should be a category on NSCalendarDate -@@ -435,7 +340,7 @@ - for (pe = bytes; isalnum(*pe) || *pe == '-' || *pe == '+'; pe++) - ; - *pe = '\0'; -- if ((tz = parseTimeZone(bytes, (pe - bytes))) == nil) { -+ if ((tz = parseTimeZone((const char *) bytes, (pe - bytes))) == nil) { - [self logWithFormat: - @"WARNING: failed to parse RFC822 timezone: '%s' (value='%@')", - bytes, _data]; -@@ -444,9 +349,9 @@ - - /* construct and return */ - finished: -- date = [CalDateClass dateWithYear:year month:monthOfYear day:dayOfMonth -- hour:hour minute:minute second:second -- timeZone:tz]; -+ date = [NSCalendarDate dateWithYear:year month:monthOfYear day:dayOfMonth -+ hour:hour minute:minute second:second -+ timeZone:tz]; - if (date == nil) goto failed; - - #if 0 -Index: sope-mime/NGMime/NGMimeHeaderFieldGeneratorSet.m -=================================================================== ---- sope-mime/NGMime/NGMimeHeaderFieldGeneratorSet.m (révision 1621) -+++ sope-mime/NGMime/NGMimeHeaderFieldGeneratorSet.m (copie de travail) -@@ -77,6 +77,7 @@ - [rfc822Set setGenerator:gen forField:@"bcc"]; - [rfc822Set setGenerator:gen forField:Fields->from]; - [rfc822Set setGenerator:gen forField:@"reply-to"]; -+ [rfc822Set setGenerator:gen forField:@"in-reply-to"]; - [rfc822Set setGenerator:gen forField:@"Disposition-Notification-To"]; - } - -Index: sope-mime/NGMime/NGMimeBodyPart.m -=================================================================== ---- sope-mime/NGMime/NGMimeBodyPart.m (révision 1621) -+++ sope-mime/NGMime/NGMimeBodyPart.m (copie de travail) -@@ -31,18 +31,6 @@ - return 2; - } - --static NGMimeType *defaultType = nil; -- --+ (void)initialize { -- static BOOL isInitialized = NO; -- if (!isInitialized) { -- isInitialized = YES; -- -- defaultType = -- [[NGMimeType mimeType:@"text/plain; charset=us-ascii"] retain]; -- } --} -- - + (id)bodyPartWithHeader:(NGHashMap *)_header { - return [[[self alloc] initWithHeader:_header] autorelease]; - } -@@ -156,13 +144,12 @@ - if (!Fields) - Fields = (NGMimeHeaderNames *)[NGMimePartParser headerFieldNames]; - -- - type = [self->header objectForKey:Fields->contentType]; - - if (![type isKindOfClass:[NGMimeType class]]) - type = [NGMimeType mimeType:[type stringValue]]; - -- return (type != nil ? type : (id)defaultType); -+ return type; - } - - - (NSString *)contentId { -Index: sope-mime/NGMime/GNUmakefile.preamble -=================================================================== ---- sope-mime/NGMime/GNUmakefile.preamble (révision 1621) -+++ sope-mime/NGMime/GNUmakefile.preamble (copie de travail) -@@ -5,6 +5,11 @@ - -DLIBRARY_MINOR_VERSION=${MINOR_VERSION} \ - -DLIBRARY_SUBMINOR_VERSION=${SUBMINOR_VERSION} \ - -+ifeq ($(patsubstr GNU/%,glibc,$(shell uname -o)),glibc) -+ADDITIONAL_CPPFLAGS += \ -+ -DHAVE_STRNDUP -+endif -+ - NGMime_INCLUDE_DIRS += \ - -I.. -I../.. \ - -I../../sope-core/NGStreams/ \ -Index: sope-mime/NGMime/NGMimeBodyParser.m -=================================================================== ---- sope-mime/NGMime/NGMimeBodyParser.m (révision 1621) -+++ sope-mime/NGMime/NGMimeBodyParser.m (copie de travail) -@@ -67,7 +67,10 @@ - if (_data == nil) return nil; - - ctype = [_part contentType]; -- -+ if (!ctype -+ && [_d respondsToSelector: @selector(parser:contentTypeOfPart:)]) -+ ctype = [_d parser: self contentTypeOfPart: _part]; -+ - if (![ctype isKindOfClass:[NGMimeType class]]) - ctype = [NGMimeType mimeType:[ctype stringValue]]; - -Index: sope-mime/NGMime/NGMimePartParser.h -=================================================================== ---- sope-mime/NGMime/NGMimePartParser.h (révision 1621) -+++ sope-mime/NGMime/NGMimePartParser.h (copie de travail) -@@ -117,6 +117,7 @@ - BOOL parserParseRawBodyDataOfPart:1; - BOOL parserBodyParserForPart:1; - BOOL parserDecodeBodyOfPart:1; -+ BOOL parserContentTypeOfPart:1; - } delegateRespondsTo; - - -@@ -275,6 +276,9 @@ - - (id<NGMimeBodyParser>)parser:(NGMimePartParser *)_parser - bodyParserForPart:(id<NGMimePart>)_part; - -+- (NGMimeType *)parser:(id)_parser -+ contentTypeOfPart:(id<NGMimePart>)_part; -+ - @end /* NSObject(NGMimePartParserDelegate) */ - - @interface NSObject(NGMimePartParser) -Index: sope-mime/NGMime/NGMimePartParser.m -=================================================================== ---- sope-mime/NGMime/NGMimePartParser.m (révision 1621) -+++ sope-mime/NGMime/NGMimePartParser.m (copie de travail) -@@ -227,7 +227,7 @@ - } - - + (NSStringEncoding)defaultHeaderFieldEncoding { -- return NSISOLatin1StringEncoding; -+ return NSUTF8StringEncoding; - } - - - (id)valueOfHeaderField:(NSString *)_name data:(id)_data { -@@ -1091,7 +1091,10 @@ - id<NGMimeBodyParser> bodyParser = nil; - - ctype = [_p contentType]; -- -+ if (!ctype -+ && self->delegateRespondsTo.parserContentTypeOfPart) -+ ctype = [self->delegate parser: self contentTypeOfPart: _p]; -+ - contentType = ([ctype isKindOfClass:[NGMimeType class]]) - ? ctype - : [NGMimeType mimeType:[ctype stringValue]]; -Index: sope-mime/NGMime/NGMimeAddressHeaderFieldGenerator.m -=================================================================== ---- sope-mime/NGMime/NGMimeAddressHeaderFieldGenerator.m (révision 1621) -+++ sope-mime/NGMime/NGMimeAddressHeaderFieldGenerator.m (copie de travail) -@@ -130,8 +130,13 @@ - - if (doEnc) { - /* FIXME - better use UTF8 encoding! */ -+#if NeXT_Foundation_LIBRARY - unsigned char iso[] = "=?iso-8859-15?q?"; - unsigned isoLen = 16; -+#else -+ unsigned char iso[] = "=?utf-8?q?"; -+ unsigned isoLen = 10; -+#endif - unsigned char isoEnd[] = "?="; - unsigned isoEndLen = 2; - unsigned desLen; -@@ -141,10 +146,10 @@ - { - NSData *data; - --#if APPLE_Foundation_LIBRARY || NeXT_Foundation_LIBRARY -+#if NeXT_Foundation_LIBRARY - data = [tmp dataUsingEncoding:NSISOLatin1StringEncoding]; - #else -- data = [tmp dataUsingEncoding:NSISOLatin9StringEncoding]; -+ data = [tmp dataUsingEncoding:NSUTF8StringEncoding]; - #endif - - bufLen = [data length]; -Index: sope-mime/NGMime/NGMimeContentDispositionHeaderFieldGenerator.m -=================================================================== ---- sope-mime/NGMime/NGMimeContentDispositionHeaderFieldGenerator.m (révision 1621) -+++ sope-mime/NGMime/NGMimeContentDispositionHeaderFieldGenerator.m (copie de travail) -@@ -49,80 +49,70 @@ - - // TODO: move the stuff below to some NSString or NSData category? - -- data = [NSMutableData dataWithCapacity:64]; -+ data = [NSMutableData dataWithCapacity: 64]; - tmp = [field type]; - [data appendBytes:[tmp cString] length:[tmp length]]; - tmp = [field filename]; - if (tmp != nil) { - [data appendBytes:"; " length:2]; - [data appendBytes:"filename=\"" length:10]; -- { -- unsigned char *ctmp; -- int cnt, len; -- BOOL doEnc; -- -- // TODO: unicode? -- len = [tmp cStringLength]; -- ctmp = malloc(len + 3); -- [tmp getCString:(char *)ctmp]; ctmp[len] = '\0'; -- cnt = 0; -- doEnc = NO; -- while (cnt < len) { -- if ((unsigned char)ctmp[cnt] > 127) { -- doEnc = YES; -- break; -- } -- cnt++; -+ -+ NSData *d; -+ unsigned char* bytes; -+ unsigned length; -+ int cnt; -+ BOOL doEnc; -+ -+ //d = [tmp dataUsingEncoding: NSUTF8StringEncoding]; -+ //bytes = [d bytes]; -+ //length = [d length]; -+ bytes = [tmp cStringUsingEncoding: NSUTF8StringEncoding]; -+ length = strlen(bytes); -+ -+ cnt = 0; -+ doEnc = NO; -+ while (cnt < length) { -+ if ((unsigned char)bytes[cnt] > 127) { -+ doEnc = YES; -+ break; - } -- if (doEnc) { -- char iso[] = "=?iso-8859-15?q?"; -- unsigned isoLen = 16; -- char isoEnd[] = "?="; -- unsigned isoEndLen = 2; -- unsigned desLen; -- char *des; -- -- if (ctmp) free(ctmp); -- { -- NSData *data; -+ cnt++; -+ } - --#if APPLE_Foundation_LIBRARY || NeXT_Foundation_LIBRARY -- data = [tmp dataUsingEncoding:NSISOLatin1StringEncoding]; --#else -- data = [tmp dataUsingEncoding:NSISOLatin9StringEncoding]; --#endif -- -- len = [data length]; -- ctmp = malloc(len+1); -- [data getBytes:ctmp]; ctmp[len] = '\0'; -- } -- -- desLen = len * 3 + 20; -- des = calloc(desLen + 10, sizeof(char)); -- -- memcpy(des, ctmp, cnt); -- memcpy(des + cnt, iso, isoLen); -- desLen = -- NGEncodeQuotedPrintableMime((unsigned char *)ctmp + cnt, len - cnt, -- (unsigned char *)des + cnt + isoLen, -- desLen - cnt - isoLen); -- if ((int)desLen != -1) { -- memcpy(des + cnt + isoLen + desLen, isoEnd, isoEndLen); -- [data appendBytes:des length:(cnt + isoLen + desLen + isoEndLen)]; -- } -- else { -+ if (doEnc) -+ { -+ char iso[] = "=?utf-8?q?"; -+ unsigned isoLen = 10; -+ char isoEnd[] = "?="; -+ unsigned isoEndLen = 2; -+ int desLen; -+ char *des; -+ -+ desLen = length * 3 + 20; -+ -+ des = calloc(desLen + 2, sizeof(char)); -+ -+ memcpy(des, iso, isoLen); -+ desLen = NGEncodeQuotedPrintableMime((unsigned char *)bytes, length, -+ (unsigned char *)(des + isoLen), -+ desLen - isoLen); -+ if (desLen != -1) { -+ memcpy(des + isoLen + desLen, isoEnd, isoEndLen); -+ [data appendBytes:des length:(isoLen + desLen + isoEndLen)]; -+ } -+ else { - [self logWithFormat:@"WARNING(%s:%i): An error occour during " - @"quoted-printable decoding", - __PRETTY_FUNCTION__, __LINE__]; -- } -- if (des) free(des); -+ if (des != NULL) free(des); -+ } - } -- else { -- [data appendBytes:ctmp length:len]; -+ else -+ { -+ [data appendBytes:[tmp cString] length:[tmp length]]; - } -- } -- // [data appendBytes:[tmp cString] length:[tmp length]]; -- [data appendBytes:"\"" length:1]; -+ -+ [data appendBytes:"\"" length:1]; - } - return data; - } -Index: sope-core/NGExtensions/NGExtensions/NSString+Ext.h -=================================================================== ---- sope-core/NGExtensions/NGExtensions/NSString+Ext.h (révision 1621) -+++ sope-core/NGExtensions/NGExtensions/NSString+Ext.h (copie de travail) -@@ -30,6 +30,7 @@ - - @interface NSString(GSAdditions) - -+#if !GNUSTEP - - (NSString *)stringWithoutPrefix:(NSString *)_prefix; - - (NSString *)stringWithoutSuffix:(NSString *)_suffix; - -@@ -39,6 +40,7 @@ - - (NSString *)stringByTrimmingLeadSpaces; - - (NSString *)stringByTrimmingTailSpaces; - - (NSString *)stringByTrimmingSpaces; -+#endif /* !GNUSTEP */ - - /* the following are not available in gstep-base 1.6 ? */ - - (NSString *)stringByTrimmingLeadWhiteSpaces; -@@ -47,6 +49,8 @@ - - @end /* NSString(GSAdditions) */ - -+#if !GNUSTEP -+ - @interface NSMutableString(GNUstepCompatibility) - - - (void)trimLeadSpaces; -@@ -55,6 +59,8 @@ - - @end /* NSMutableString(GNUstepCompatibility) */ - -+#endif /* !GNUSTEP */ -+ - #endif - - /* specific to libFoundation */ -Index: sope-core/NGExtensions/FdExt.subproj/NSString+Ext.m -=================================================================== ---- sope-core/NGExtensions/FdExt.subproj/NSString+Ext.m (révision 1621) -+++ sope-core/NGExtensions/FdExt.subproj/NSString+Ext.m (copie de travail) -@@ -39,18 +39,6 @@ - : (NSString *)[[self copy] autorelease]; - } - --- (NSString *)stringByReplacingString:(NSString *)_orignal -- withString:(NSString *)_replacement --{ -- /* very slow solution .. */ -- -- if ([self rangeOfString:_orignal].length == 0) -- return [[self copy] autorelease]; -- -- return [[self componentsSeparatedByString:_orignal] -- componentsJoinedByString:_replacement]; --} -- - - (NSString *)stringByTrimmingLeadWhiteSpaces - { - // should check 'whitespaceAndNewlineCharacterSet' .. -@@ -96,6 +84,25 @@ - return [[self copy] autorelease]; - } - -+- (NSString *)stringByTrimmingWhiteSpaces -+{ -+ return [[self stringByTrimmingTailWhiteSpaces] -+ stringByTrimmingLeadWhiteSpaces]; -+} -+ -+#ifndef GNUSTEP -+- (NSString *)stringByReplacingString:(NSString *)_orignal -+ withString:(NSString *)_replacement -+{ -+ /* very slow solution .. */ -+ -+ if ([self rangeOfString:_orignal].length == 0) -+ return [[self copy] autorelease]; -+ -+ return [[self componentsSeparatedByString:_orignal] -+ componentsJoinedByString:_replacement]; -+} -+ - - (NSString *)stringByTrimmingLeadSpaces - { - unsigned len; -@@ -117,6 +124,7 @@ - else - return [[self copy] autorelease]; - } -+ - - (NSString *)stringByTrimmingTailSpaces - { - unsigned len; -@@ -139,19 +147,17 @@ - return [[self copy] autorelease]; - } - --- (NSString *)stringByTrimmingWhiteSpaces --{ -- return [[self stringByTrimmingTailWhiteSpaces] -- stringByTrimmingLeadWhiteSpaces]; --} - - (NSString *)stringByTrimmingSpaces - { - return [[self stringByTrimmingTailSpaces] - stringByTrimmingLeadSpaces]; - } -+#endif - - @end /* NSString(GSAdditions) */ - -+#if !GNUSTEP -+ - @implementation NSMutableString(GNUstepCompatibility) - - - (void)trimLeadSpaces -@@ -169,6 +175,8 @@ - - @end /* NSMutableString(GNUstepCompatibility) */ - -+#endif /* !GNUSTEP */ -+ - @implementation NSString(lfNSURLUtilities) - - - (BOOL)isAbsoluteURL -Index: sope-core/NGExtensions/FdExt.subproj/NSString+Encoding.m -=================================================================== ---- sope-core/NGExtensions/FdExt.subproj/NSString+Encoding.m (révision 1621) -+++ sope-core/NGExtensions/FdExt.subproj/NSString+Encoding.m (copie de travail) -@@ -140,8 +140,12 @@ - - - #ifdef __linux__ -+#if __BYTE_ORDER == __LITTLE_ENDIAN - static NSString *unicharEncoding = @"UCS-2LE"; - #else -+static NSString *unicharEncoding = @"UCS-2BE"; -+#endif /* __BYTE_ORDER */ -+#else - static NSString *unicharEncoding = @"UCS-2-INTERNAL"; - #endif - static int IconvLogEnabled = -1; -@@ -149,21 +153,12 @@ - static void checkDefaults(void) { - NSUserDefaults *ud; - -- if (IconvLogEnabled != -1) -- return; -- ud = [NSUserDefaults standardUserDefaults]; -- IconvLogEnabled = [ud boolForKey:@"IconvLogEnabled"]?1:0; -+ if (IconvLogEnabled == -1) { -+ ud = [NSUserDefaults standardUserDefaults]; -+ IconvLogEnabled = [ud boolForKey:@"IconvLogEnabled"]?1:0; - --#ifdef __linux__ -- if (NSHostByteOrder() == NS_BigEndian) { -- NSLog(@"Note: using UCS-2 big endian on Linux."); -- unicharEncoding = @"UCS-2BE"; -+ NSLog(@"Note: using '%@' on Linux.", unicharEncoding); - } -- else { -- NSLog(@"Note: using UCS-2 little endian on Linux."); -- unicharEncoding = @"UCS-2LE"; -- } --#endif - } - - static char *iconv_wrapper(id self, char *_src, unsigned _srcLen, -Index: sope-core/NGExtensions/EOExt.subproj/EOGlobalID+Ext.m -=================================================================== ---- sope-core/NGExtensions/EOExt.subproj/EOGlobalID+Ext.m (révision 1621) -+++ sope-core/NGExtensions/EOExt.subproj/EOGlobalID+Ext.m (copie de travail) -@@ -19,6 +19,7 @@ - 02111-1307, USA. - */ - -+#import <Foundation/NSString.h> - #import <EOControl/EOGlobalID.h> - #import <Foundation/NSString.h> - -Index: sope-xml/libxmlSAXDriver/libxmlHTMLSAXDriver.h -=================================================================== ---- sope-xml/libxmlSAXDriver/libxmlHTMLSAXDriver.h (révision 1621) -+++ sope-xml/libxmlSAXDriver/libxmlHTMLSAXDriver.h (copie de travail) -@@ -19,6 +19,8 @@ - 02111-1307, USA. - */ - -+#include <libxml/encoding.h> -+ - #include <SaxObjC/SaxXMLReader.h> - #include <SaxObjC/SaxLexicalHandler.h> - #include <SaxObjC/SaxDeclHandler.h> -@@ -34,7 +36,7 @@ - - @interface libxmlHTMLSAXDriver : NSObject < SaxXMLReader > - { -- id<NSObject,SaxContentHandler> contentHandler; -+ NSObject<SaxContentHandler> *contentHandler; - id<NSObject,SaxDTDHandler> dtdHandler; - id<NSObject,SaxErrorHandler> errorHandler; - id<NSObject,SaxEntityResolver> entityResolver; -Index: sope-xml/libxmlSAXDriver/libxmlHTMLSAXDriver.m -=================================================================== ---- sope-xml/libxmlSAXDriver/libxmlHTMLSAXDriver.m (révision 1621) -+++ sope-xml/libxmlSAXDriver/libxmlHTMLSAXDriver.m (copie de travail) -@@ -30,6 +30,12 @@ - #include <libxml/HTMLparser.h> - #include <libxml/HTMLtree.h> - -+@interface NSObject (contentHandlerExtensions) <SaxContentHandler> -+ -+- (xmlCharEncoding) contentEncoding; -+ -+@end -+ - @interface libxmlHTMLSAXDriver(PrivateMethods) - - - (void)tearDownParser; -@@ -194,10 +200,10 @@ - return self->entityResolver; - } - --- (void)setContentHandler:(id<NSObject,SaxContentHandler>)_handler { -+- (void)setContentHandler:(NSObject <NSObject,SaxContentHandler> *)_handler { - ASSIGN(self->contentHandler, _handler); - } --- (id<NSObject,SaxContentHandler>)contentHandler { -+- (NSObject <NSObject,SaxContentHandler> *)contentHandler { - return self->contentHandler; - } - -@@ -205,6 +211,7 @@ - - - (void)setupParserWithDocumentPath:(NSString *)_path { - xmlSAXHandler sax; -+ xmlCharEncoding charEncoding; - - if (self->ctxt != NULL) { - NSLog(@"WARNING(%s): HTML parser context already setup !", -@@ -223,14 +230,18 @@ - __PRETTY_FUNCTION__, self, activeDriver); - } - activeDriver = self; -- -+ -+ if ([self->contentHandler respondsToSelector: @selector (contentEncoding)]) -+ charEncoding = [self->contentHandler contentEncoding]; -+ else -+ charEncoding = XML_CHAR_ENCODING_8859_1; -+ - self->ctxt = htmlCreatePushParserCtxt(&sax /* sax */, - NULL /*self*/ /* userdata */, - NULL /* chunk */, - 0 /* chunklen */, - [_path cString] /* filename */, -- XML_CHAR_ENCODING_8859_1 -- /* encoding */); -+ charEncoding /* encoding */); - self->doc = NULL; - } - - (void)tearDownParser { -Index: sope-xml/libxmlSAXDriver/libxmlSAXDriver.m -=================================================================== ---- sope-xml/libxmlSAXDriver/libxmlSAXDriver.m (révision 1621) -+++ sope-xml/libxmlSAXDriver/libxmlSAXDriver.m (copie de travail) -@@ -614,7 +614,7 @@ - xmlParseDocument(ctxt); - - if (!(((xmlParserCtxtPtr)self->ctxt)->wellFormed)) -- NSLog(@"%@: not well formed", _sysId); -+ NSLog(@"%@: not well formed 1", _sysId); - - if (((xmlParserCtxtPtr)self->ctxt)->input != NULL && [_sysId length] > 0) { - ((xmlParserInputPtr)((xmlParserCtxtPtr)self->ctxt)->input)->filename -@@ -737,7 +737,7 @@ - } - - if (!(((xmlParserCtxtPtr)self->ctxt)->wellFormed)) -- NSLog(@"%@: not well formed", _sysId); -+ NSLog(@"%@: not well formed 2", _sysId); - - ((xmlParserCtxtPtr)self->ctxt)->sax = NULL; - xmlFreeParserCtxt(self->ctxt); -Index: sope-appserver/mod_ngobjweb/config.c -=================================================================== ---- sope-appserver/mod_ngobjweb/config.c (révision 1621) -+++ sope-appserver/mod_ngobjweb/config.c (copie de travail) -@@ -21,7 +21,7 @@ - - #include "common.h" - --//#define LOG_CONFIG 1 -+#define LOG_CONFIG 0 - - static char *_makeString(char *buf, char *str, int max) { - if (buf == NULL) -Index: sope-appserver/mod_ngobjweb/NGBufferedDescriptor.c -=================================================================== ---- sope-appserver/mod_ngobjweb/NGBufferedDescriptor.c (révision 1621) -+++ sope-appserver/mod_ngobjweb/NGBufferedDescriptor.c (copie de travail) -@@ -23,6 +23,7 @@ - #include <unistd.h> - #include <string.h> - #include <stdio.h> -+#include "common.h" - #include "NGBufferedDescriptor.h" - - // returns the number of bytes which where read from the buffer -Index: sope-appserver/mod_ngobjweb/GNUmakefile -=================================================================== ---- sope-appserver/mod_ngobjweb/GNUmakefile (révision 1621) -+++ sope-appserver/mod_ngobjweb/GNUmakefile (copie de travail) -@@ -82,7 +82,7 @@ - - CFLAGS = -Wall -I. -fPIC \ - $(APXS_CFLAGS) $(APR_CFLAGS) \ -- $(APXS_INCLUDE_DIRS) $(APR_INCLUDE_DIRS) -+ $(APXS_INCLUDE_DIRS) $(APR_INCLUDE_DIRS) -O0 -ggdb - - LDFLAGS = $(APXS_LDFLAGS) $(APR_LDFLAGS) -shared -fPIC - LDLIBS = $(APXS_LIBS) $(APR_LIBS) -@@ -111,8 +111,7 @@ - apache-dir : - $(MKDIRS) $(GNUSTEP_INSTALLATION_DIR) - --install :: apache-dir all -- $(INSTALL_PROGRAM) $(product) $(GNUSTEP_INSTALLATION_DIR) -+install :: - - install-usr-libexec :: all - $(INSTALL_PROGRAM) $(product) /usr/libexec/httpd/ -Index: sope-appserver/NGObjWeb/GNUmakefile.postamble -=================================================================== ---- sope-appserver/NGObjWeb/GNUmakefile.postamble (révision 1621) -+++ sope-appserver/NGObjWeb/GNUmakefile.postamble (copie de travail) -@@ -23,14 +23,20 @@ - - # install makefiles - --after-install :: -- $(MKDIRS) $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/Additional/ -- $(INSTALL_DATA) ngobjweb.make $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/Additional/ngobjweb.make -+after-install :: $(DESTDIR)/$(GNUSTEP_MAKEFILES)/Additional/ngobjweb.make - - ifneq ($(GNUSTEP_MAKE_VERSION),1.3.0) --after-install :: -+after-install :: $(DESTDIR)/$(GNUSTEP_MAKEFILES)/woapp.make $(DESTDIR)/$(GNUSTEP_MAKEFILES)/wobundle.make -+endif -+ -+$(DESTDIR)/$(GNUSTEP_MAKEFILES)/Additional/ngobjweb.make: ngobjweb.make -+ $(MKDIRS) $(DESTDIR)/$(GNUSTEP_MAKEFILES)/Additional/ -+ $(INSTALL_DATA) ngobjweb.make $(DESTDIR)/$(GNUSTEP_MAKEFILES)/Additional/ngobjweb.make -+ -+$(DESTDIR)/$(GNUSTEP_MAKEFILES)/woapp.make: woapp-gs.make - $(INSTALL_DATA) woapp-gs.make \ -- $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/woapp.make -+ $(DESTDIR)/$(GNUSTEP_MAKEFILES)/woapp.make -+ -+$(DESTDIR)/$(GNUSTEP_MAKEFILES)/wobundle.make: wobundle-gs.make - $(INSTALL_DATA) wobundle-gs.make \ -- $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/wobundle.make --endif -+ $(DESTDIR)/$(GNUSTEP_MAKEFILES)/wobundle.make -Index: sope-appserver/NGObjWeb/WOContext.m -=================================================================== ---- sope-appserver/NGObjWeb/WOContext.m (révision 1621) -+++ sope-appserver/NGObjWeb/WOContext.m (copie de travail) -@@ -64,11 +64,13 @@ - static BOOL testNSURLs = NO; - static BOOL newCURLStyle = NO; - static NSString *WOApplicationSuffix = nil; -+static NSURL *redirectURL = nil; - - + (void)initialize { - static BOOL didInit = NO; - NSUserDefaults *ud; - NSString *cn; -+ NSString *url; - - if (didInit) return; - -@@ -91,6 +93,9 @@ - debugCursor = [ud boolForKey:@"WODebugCursor"] ? 1 : 0; - debugComponentAwake = [ud boolForKey:@"WODebugComponentAwake"]; - WOApplicationSuffix = [[ud stringForKey:@"WOApplicationSuffix"] copy]; -+ url = [ud stringForKey:@"WOApplicationRedirectURL"]; -+ if (url != nil) -+ redirectURL = [NSURL URLWithString: url]; - } - - + (id)contextWithRequest:(WORequest *)_r { -@@ -503,6 +508,11 @@ - return nil; - } - -+ if (redirectURL) { -+ // Use URL from user defaults (WOApplicationRedirectURL) -+ return redirectURL; -+ } -+ - if ((serverURL = [rq headerForKey:@"x-webobjects-server-url"]) == nil) { - if ((host = [rq headerForKey:@"host"])) - serverURL = [@"http://" stringByAppendingString:host]; -Index: sope-appserver/NGObjWeb/DAVPropMap.plist -=================================================================== ---- sope-appserver/NGObjWeb/DAVPropMap.plist (révision 1621) -+++ sope-appserver/NGObjWeb/DAVPropMap.plist (copie de travail) -@@ -24,13 +24,19 @@ - "{DAV:}status" = "davStatus"; - "{http://apache.org/dav/props/}executable" = "davIsExecutable"; - -+ /* RFC 3253 - Versioning Extensions to WebDAV (DeltaV) */ -+ "{DAV:}comment" = "davComment"; -+ "{DAV:}creator-displayname" = "davCreatorDisplayName"; -+ "{DAV:}supported-method-set" = "davSupportedMethodSet"; -+ "{DAV:}supported-live-property-set" = "davSupportedLivePropertySet"; -+ "{DAV:}supported-report-set" = "davSupportedReportSet"; -+ - /* used with Apple WebDAV */ - "{DAV:}quota" = davQuota; - "{DAV:}quotaused" = davQuotaUsed; - "{http://www.apple.com/webdav_fs/props/}appledoubleheader"=appleDoubleHeader; - - /* Novell NetDrive */ -- "{DAV:}owner" = davOwner; - "{DAV:}locktoken" = davLockToken; - "{DAV:}activelock" = davActiveLock; - // TODO: non-standard?, also used by WebDrive -@@ -120,12 +126,29 @@ - "{http://ucb.openoffice.org/dav/props/}IsRemoveable" = isOOoRemoveable; - "{http://ucb.openoffice.org/dav/props/}IsVolume" = isOOoVolume; - "{http://ucb.openoffice.org/dav/props/}TargetURL" = davOOoTargetURL; -- -+ - /* WebDAV ACL */ -+ "{DAV:}owner" = davOwner; -+ "{DAV:}group" = davGroup; -+ "{DAV:}supported-privilege-set" = davSupportedPrivilegeSet; -+ "{DAV:}principal-collection-set" = davPrincipalCollectionSet; -+ "{DAV:}acl" = davAcl; -+ "{DAV:}acl-restrictions" = davAclRestrictions; - "{DAV:}current-user-privilege-set" = davCurrentUserPrivilegeSet; -+ "{DAV:}inherited-acl-set" = davInheritedAclSet; -+ "{DAV:}principal-URL" = davPrincipalURL; -+ "{DAV:}alternate-URI-set" = davAlternateURISet; -+ "{DAV:}group-member-set" = davGroupMemberSet; -+ "{DAV:}group-membership" = davGroupMembership; - - /* CalDAV */ -+ "{urn:ietf:params:xml:ns:caldav}calendar-data" = davCalendarData; -+ "{urn:ietf:params:xml:ns:caldav}calendar-description" = davDescription; - "{urn:ietf:params:xml:ns:caldav}calendar-home-set" = davCalendarHomeSet; -+ "{urn:ietf:params:xml:ns:caldav}calendar-user-address-set" = -+ davCalendarUserAddressSet; -+ "{urn:ietf:params:xml:ns:caldav}schedule-inbox-URL" = davCalendarScheduleInboxURL; -+ "{urn:ietf:params:xml:ns:caldav}schedule-outbox-URL" = davCalendarScheduleOutboxURL; - "{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set" = - davCalendarComponentSet; - "{urn:ietf:params:xml:ns:caldav}supported-calendar-data" = -@@ -138,13 +161,13 @@ - "{urn:ietf:params:xml:ns:carddav}addressbook-description" = davDescription; - - /* Apple CalServer */ -- "{http://apple.com/ns/calendarserver/}dropbox-home-URL" = -- davDropboxHomeURL; -- "{http://apple.com/ns/calendarserver/}notifications-URL" = -- davNotificationsURL; -- "{com.apple.ical:}calendarcolor" = davCalendarColor; -+ "{http://calendarserver.org/ns/}dropbox-home-URL" = davDropboxHomeURL; -+ "{http://calendarserver.org/ns/}notifications-URL" = davNotificationsURL; - "{http://calendarserver.org/ns/}getctag" = davCollectionTag; - -+ /* Apple extensions */ -+ "{http://apple.com/ns/ical/}calendar-color" = davCalendarColor; -+ - /* GroupDAV */ - "{http://www.groupdav.org/}component-set" = gdavComponentSet; - "{http://groupdav.org/}component-set" = gdavComponentSet; -Index: sope-appserver/NGObjWeb/WebDAV/SaxDAVHandler.m -=================================================================== ---- sope-appserver/NGObjWeb/WebDAV/SaxDAVHandler.m (révision 1621) -+++ sope-appserver/NGObjWeb/WebDAV/SaxDAVHandler.m (copie de travail) -@@ -655,6 +655,7 @@ - if (self->responses == nil) - self->responses = [[NSMutableArray alloc] initWithCapacity:64]; - } -+ - break; - - case 'n': -Index: sope-appserver/NGObjWeb/WebDAV/SoObjectWebDAVDispatcher.m -=================================================================== ---- sope-appserver/NGObjWeb/WebDAV/SoObjectWebDAVDispatcher.m (révision 1621) -+++ sope-appserver/NGObjWeb/WebDAV/SoObjectWebDAVDispatcher.m (copie de travail) -@@ -1523,14 +1523,16 @@ - - (id)doREPORT:(WOContext *)_ctx { - id<DOMDocument> domDocument; - WORequest *rq; -- NSString *mname; -+ NSString *mname, *ctype; - id method, resultObject; - - rq = [_ctx request]; - - /* ensure XML */ - -- if (![[rq headerForKey:@"content-type"] hasPrefix:@"text/xml"]) { -+ ctype = [rq headerForKey:@"content-type"]; -+ if (!([ctype hasPrefix:@"text/xml"] -+ || [ctype hasPrefix:@"application/xml"])) { - return [self httpException:400 /* invalid request */ - reason:@"XML entity expected for WebDAV REPORT."]; - } -Index: sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.m -=================================================================== ---- sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.m (révision 1621) -+++ sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.m (copie de travail) -@@ -216,6 +216,12 @@ - assocCount++; - } - } -+ if (count > 0) { -+ if ((self->isAbsolute = OWGetProperty(_config, @"absolute"))) { -+ count--; -+ assocCount++; -+ } -+ } - - self->rest = _config; - -Index: sope-appserver/NGObjWeb/DynamicElements/_WOComplexHyperlink.m -=================================================================== ---- sope-appserver/NGObjWeb/DynamicElements/_WOComplexHyperlink.m (révision 1621) -+++ sope-appserver/NGObjWeb/DynamicElements/_WOComplexHyperlink.m (copie de travail) -@@ -41,6 +41,7 @@ - WOAssociation *string; - WOAssociation *target; - WOAssociation *disabled; -+ WOAssociation *isAbsolute; - WOElement *template; - - /* new in WO4: */ -@@ -360,6 +361,7 @@ - { - if ((self = [super initWithName:_name hyperlinkInfo:_info template:_t])) { - self->href = _info->href; -+ self->isAbsolute = _info->isAbsolute; - } - return self; - } -@@ -375,8 +377,11 @@ - // TODO: we need a binding to disable rewriting! - NSRange r; - -+ if ([[self->isAbsolute valueInContext:_ctx] boolValue] == YES) -+ return NO; -+ - r.length = [_s length]; -- -+ - /* do not rewrite pure fragment URLs */ - if (r.length > 0 && [_s characterAtIndex:0] == '#') - return NO; -Index: sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.h -=================================================================== ---- sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.h (révision 1621) -+++ sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.h (copie de travail) -@@ -41,7 +41,8 @@ - WOAssociation *pageName; - WOAssociation *actionClass; - WOAssociation *directActionName; -- -+ WOAssociation *isAbsolute; -+ - BOOL sidInUrl; - - /* 'ivar' associations */ -Index: sope-appserver/NGObjWeb/SoObjects/SoObject.m -=================================================================== ---- sope-appserver/NGObjWeb/SoObjects/SoObject.m (révision 1621) -+++ sope-appserver/NGObjWeb/SoObjects/SoObject.m (copie de travail) -@@ -39,22 +39,34 @@ - static int debugLookup = -1; - static int debugBaseURL = -1; - static int useRelativeURLs = -1; -+static int redirectInitted = -1; -+static NSURL *redirectURL = nil; -+ - static void _initialize(void) { -+ NSString *url; -+ NSUserDefaults *ud; -+ -+ ud = [NSUserDefaults standardUserDefaults]; -+ - if (debugLookup == -1) { -- debugLookup = [[NSUserDefaults standardUserDefaults] -- boolForKey:@"SoDebugKeyLookup"] ? 1 : 0; -+ debugLookup = [ud boolForKey:@"SoDebugKeyLookup"] ? 1 : 0; - NSLog(@"Note(SoObject): SoDebugKeyLookup is enabled!"); - } - if (debugBaseURL == -1) { -- debugBaseURL = [[NSUserDefaults standardUserDefaults] -- boolForKey:@"SoDebugBaseURL"] ? 1 : 0; -+ debugBaseURL = [ud boolForKey:@"SoDebugBaseURL"] ? 1 : 0; - NSLog(@"Note(SoObject): SoDebugBaseURL is enabled!"); - } - if (useRelativeURLs == -1) { -- useRelativeURLs = [[NSUserDefaults standardUserDefaults] -- boolForKey:@"WOUseRelativeURLs"] ?1:0; -+ useRelativeURLs = [ud boolForKey:@"WOUseRelativeURLs"] ?1:0; - NSLog(@"Note(SoObject): relative base URLs are enabled."); - } -+ if (redirectInitted == -1) { -+ url = [ud stringForKey:@"WOApplicationRedirectURL"]; -+ if ([url length]) { -+ redirectURL = [[NSURL alloc] initWithString: url]; -+ } -+ redirectInitted = 1; -+ } - } - - /* classes */ -@@ -318,56 +330,61 @@ - - rq = [_ctx request]; - ms = [[NSMutableString alloc] initWithCapacity:128]; -+ -+ if (redirectURL) { -+ [ms appendString: [redirectURL absoluteString]]; -+ } -+ else { -+ if (!useRelativeURLs) { -+ port = [[rq headerForKey:@"x-webobjects-server-port"] intValue]; - -- if (!useRelativeURLs) { -- port = [[rq headerForKey:@"x-webobjects-server-port"] intValue]; -- -- /* this is actually a bug in Apache */ -- if (port == 0) { -- static BOOL didWarn = NO; -- if (!didWarn) { -- [self warnWithFormat:@"(%s:%i): got an empty port from Apache!", -- __PRETTY_FUNCTION__, __LINE__]; -- didWarn = YES; -+ /* this is actually a bug in Apache */ -+ if (port == 0) { -+ static BOOL didWarn = NO; -+ if (!didWarn) { -+ [self warnWithFormat:@"(%s:%i): got an empty port from Apache!", -+ __PRETTY_FUNCTION__, __LINE__]; -+ didWarn = YES; -+ } -+ port = 80; - } -- port = 80; -- } - -- if ((tmp = [rq headerForKey:@"host"]) != nil) { -- /* check whether we have a host header with port */ -- if ([tmp rangeOfString:@":"].length == 0) -- tmp = nil; -- } -- if (tmp != nil) { /* we have a host header with port */ -- isHTTPS = -- [[rq headerForKey:@"x-webobjects-server-url"] hasPrefix:@"https"]; -- [ms appendString:isHTTPS ? @"https://" : @"http://"]; -- [ms appendString:tmp]; -- } -- else if ((tmp = [rq headerForKey:@"x-webobjects-server-url"]) != nil) { -- /* sometimes the URL is just wrong! (suggests port 80) */ -- if ([tmp hasSuffix:@":0"] && [tmp length] > 2) { // TODO: bad bad bad -- [self warnWithFormat:@"%s: got incorrect URL from Apache: '%@'", -- __PRETTY_FUNCTION__, tmp]; -- tmp = [tmp substringToIndex:([tmp length] - 2)]; -+ if ((tmp = [rq headerForKey:@"host"]) != nil) { -+ /* check whether we have a host header with port */ -+ if ([tmp rangeOfString:@":"].length == 0) -+ tmp = nil; - } -- else if ([tmp hasSuffix:@":443"] && [tmp hasPrefix:@"http://"]) { -- /* see OGo bug #1435, Debian Apache hack */ -- [self warnWithFormat:@"%s: got 'http' protocol but 443 port, " -- @"assuming Debian/Apache bug (OGo #1435): '%@'", -- __PRETTY_FUNCTION__, tmp]; -- tmp = [tmp substringWithRange:NSMakeRange(4, [tmp length] - 4 - 4)]; -- tmp = [@"https" stringByAppendingString:tmp]; -+ if (tmp != nil) { /* we have a host header with port */ -+ isHTTPS = -+ [[rq headerForKey:@"x-webobjects-server-url"] hasPrefix:@"https"]; -+ [ms appendString:isHTTPS ? @"https://" : @"http://"]; -+ [ms appendString:tmp]; - } -- [ms appendString:tmp]; -- } -- else { -- // TODO: isHTTPS always no in this case? -- [ms appendString:isHTTPS ? @"https://" : @"http://"]; -+ else if ((tmp = [rq headerForKey:@"x-webobjects-server-url"]) != nil) { -+ /* sometimes the URL is just wrong! (suggests port 80) */ -+ if ([tmp hasSuffix:@":0"] && [tmp length] > 2) { // TODO: bad bad bad -+ [self warnWithFormat:@"%s: got incorrect URL from Apache: '%@'", -+ __PRETTY_FUNCTION__, tmp]; -+ tmp = [tmp substringToIndex:([tmp length] - 2)]; -+ } -+ else if ([tmp hasSuffix:@":443"] && [tmp hasPrefix:@"http://"]) { -+ /* see OGo bug #1435, Debian Apache hack */ -+ [self warnWithFormat:@"%s: got 'http' protocol but 443 port, " -+ @"assuming Debian/Apache bug (OGo #1435): '%@'", -+ __PRETTY_FUNCTION__, tmp]; -+ tmp = [tmp substringWithRange:NSMakeRange(4, [tmp length] - 4 - 4)]; -+ tmp = [@"https" stringByAppendingString:tmp]; -+ } -+ [ms appendString:tmp]; -+ } -+ else { -+ // TODO: isHTTPS always no in this case? -+ [ms appendString:isHTTPS ? @"https://" : @"http://"]; - -- [ms appendString:[rq headerForKey:@"x-webobjects-server-name"]]; -- if ((isHTTPS ? (port != 443) : (port != 80)) && port != 0) -- [ms appendFormat:@":%i", port]; -+ [ms appendString:[rq headerForKey:@"x-webobjects-server-name"]]; -+ if ((isHTTPS ? (port != 443) : (port != 80)) && port != 0) -+ [ms appendFormat:@":%i", port]; -+ } - } - } - -Index: sope-appserver/NGObjWeb/WOHttpAdaptor/WOHttpTransaction.m -=================================================================== ---- sope-appserver/NGObjWeb/WOHttpAdaptor/WOHttpTransaction.m (révision 1621) -+++ sope-appserver/NGObjWeb/WOHttpAdaptor/WOHttpTransaction.m (copie de travail) -@@ -32,6 +32,7 @@ - #include <NGObjWeb/WOCookie.h> - #include <NGExtensions/NSData+gzip.h> - #include <NGHttp/NGHttp.h> -+#include <NGMime/NGMimeType.h> - #include "common.h" - - #include <string.h> -@@ -1042,6 +1043,12 @@ - - (void)parser:(NGMimePartParser *)_parser didParseHeader:(NGHashMap *)_header { - } - -+- (NGMimeType *)parser:(id)_parser -+ contentTypeOfPart:(id<NGMimePart>)_part -+{ -+ return [NGMimeType mimeType: @"text/plain; charset=utf-8"]; -+} -+ - @end /* WOHttpAdaptor */ - - @implementation WOCoreApplication(SimpleParserSelection) diff --git a/gnustep-libs/sope/files/sope-patchset-r1660.diff b/gnustep-libs/sope/files/sope-patchset-r1660.diff new file mode 100644 index 0000000..629a5b5 --- /dev/null +++ b/gnustep-libs/sope/files/sope-patchset-r1660.diff @@ -0,0 +1,4889 @@ +Index: sope-ldap/NGLdap/NGLdapEntry.m +=================================================================== +--- sope-ldap/NGLdap/NGLdapEntry.m (revision 1660) ++++ sope-ldap/NGLdap/NGLdapEntry.m (working copy) +@@ -105,14 +105,16 @@ + - (NGLdapAttribute *)attributeWithName:(NSString *)_name { + NSEnumerator *e; + NGLdapAttribute *a; +- ++ NSString *upperName; ++ + if (_name == nil) + return nil; + ++ upperName = [_name uppercaseString]; + e = [self->attributes objectEnumerator]; + + while ((a = [e nextObject])) { +- if ([[a attributeName] isEqualToString:_name]) ++ if ([[[a attributeName] uppercaseString] isEqualToString:upperName]) + return a; + } + return nil; +Index: sope-ldap/NGLdap/ChangeLog +=================================================================== +--- sope-ldap/NGLdap/ChangeLog (revision 1660) ++++ sope-ldap/NGLdap/ChangeLog (working copy) +@@ -1,3 +1,8 @@ ++2009-08-13 Wolfgang Sourdeau <wsourdeau@inverse.ca> ++ ++ * NGLdapEntry.m (-attributeWithName:): attribute names are now ++ accessed in a case-insensitive way. ++ + 2009-04-02 Wolfgang Sourdeau <wsourdeau@inverse.ca> + + * NGLdapConnection.m (useSSL,startTLS): new method enabling +Index: sope-gdl1/PostgreSQL/PostgreSQL72Channel.m +=================================================================== +--- sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (revision 1660) ++++ sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (working copy) +@@ -713,6 +713,39 @@ + return ms; + } + ++/* GCSEOAdaptorChannel protocol */ ++static NSString *sqlFolderFormat = (@"CREATE TABLE %@ (\n" \ ++ @" c_name VARCHAR (256) NOT NULL PRIMARY KEY,\n" ++ @" c_content VARCHAR (100000) NOT NULL,\n" ++ @" c_creationdate INT4 NOT NULL,\n" ++ @" c_lastmodified INT4 NOT NULL,\n" ++ @" c_version INT4 NOT NULL,\n" ++ @" c_deleted INT4 NULL\n" ++ @")"); ++static NSString *sqlFolderACLFormat = (@"CREATE TABLE %@ (\n" \ ++ @" c_uid VARCHAR (256) NOT NULL,\n" ++ @" c_object VARCHAR (256) NOT NULL,\n" ++ @" c_role VARCHAR (80) NOT NULL\n" ++ @")"); ++ ++- (NSException *) createGCSFolderTableWithName: (NSString *) tableName ++{ ++ NSString *sql; ++ ++ sql = [NSString stringWithFormat: sqlFolderFormat, tableName]; ++ ++ return [self evaluateExpressionX: sql]; ++} ++ ++- (NSException *) createGCSFolderACLTableWithName: (NSString *) tableName ++{ ++ NSString *sql; ++ ++ sql = [NSString stringWithFormat: sqlFolderACLFormat, tableName]; ++ ++ return [self evaluateExpressionX: sql]; ++} ++ + @end /* PostgreSQL72Channel */ + + @implementation PostgreSQL72Channel(PrimaryKeyGeneration) +Index: sope-gdl1/MySQL/MySQL4Channel.m +=================================================================== +--- sope-gdl1/MySQL/MySQL4Channel.m (revision 1660) ++++ sope-gdl1/MySQL/MySQL4Channel.m (working copy) +@@ -755,6 +755,39 @@ + return pkey; + } + ++/* GCSEOAdaptorChannel protocol */ ++static NSString *sqlFolderFormat = (@"CREATE TABLE %@ (\n" \ ++ @" c_name VARCHAR (256) NOT NULL PRIMARY KEY,\n" ++ @" c_content VARCHAR (100000) NOT NULL,\n" ++ @" c_creationdate INT NOT NULL,\n" ++ @" c_lastmodified INT NOT NULL,\n" ++ @" c_version INT NOT NULL,\n" ++ @" c_deleted INT NULL\n" ++ @")"); ++static NSString *sqlFolderACLFormat = (@"CREATE TABLE %@ (\n" \ ++ @" c_uid VARCHAR (256) NOT NULL,\n" ++ @" c_object VARCHAR (256) NOT NULL,\n" ++ @" c_role VARCHAR (80) NOT NULL\n" ++ @")"); ++ ++- (NSException *) createGCSFolderTableWithName: (NSString *) tableName ++{ ++ NSString *sql; ++ ++ sql = [NSString stringWithFormat: sqlFolderFormat, tableName]; ++ ++ return [self evaluateExpressionX: sql]; ++} ++ ++- (NSException *) createGCSFolderACLTableWithName: (NSString *) tableName ++{ ++ NSString *sql; ++ ++ sql = [NSString stringWithFormat: sqlFolderACLFormat, tableName]; ++ ++ return [self evaluateExpressionX: sql]; ++} ++ + @end /* MySQL4Channel */ + + void __link_MySQL4Channel() { +Index: sope-gdl1/Oracle8/OracleAdaptorChannel.m +=================================================================== +--- sope-gdl1/Oracle8/OracleAdaptorChannel.m (revision 1660) ++++ sope-gdl1/Oracle8/OracleAdaptorChannel.m (working copy) +@@ -1,7 +1,7 @@ + /* + ** OracleAdaptorChannel.m + ** +-** Copyright (c) 2007 Inverse groupe conseil inc. and Ludovic Marcotte ++** Copyright (c) 2007-2009 Inverse inc. and Ludovic Marcotte + ** + ** Author: Ludovic Marcotte <ludovic@inverse.ca> + ** +@@ -30,6 +30,11 @@ + + #import <NGExtensions/NSObject+Logs.h> + ++#include <unistd.h> ++ ++static BOOL debugOn = NO; ++static int maxTry = 3; ++static int maxSleep = 500; + // + // + // +@@ -41,10 +46,11 @@ + + @implementation OracleAdaptorChannel (Private) + +-- (void) _cleanup ++- (void) _cleanup + { + column_info *info; + int c; ++ sword result; + + [_resultSetProperties removeAllObjects]; + +@@ -58,11 +64,29 @@ + // so we just free the value instead. + if (info->value) + { +- if (OCIDescriptorFree((dvoid *)info->value, (ub4)OCI_DTYPE_LOB) != OCI_SUCCESS) ++ if (info->type == SQLT_CLOB ++ || info->type == SQLT_BLOB ++ || info->type == SQLT_BFILEE ++ || info->type == SQLT_CFILEE) ++ { ++ result = OCIDescriptorFree((dvoid *)info->value, (ub4) OCI_DTYPE_LOB); ++ if (result != OCI_SUCCESS) ++ { ++ NSLog (@"value was not a LOB descriptor"); ++ abort(); ++ } ++ } ++ else + free(info->value); + info->value = NULL; + } +- free(info); ++ else ++ { ++ NSLog (@"trying to free an already freed value!"); ++ abort(); ++ } ++ free(info); ++ + [_row_buffer removeObjectAtIndex: c]; + } + +@@ -78,8 +102,7 @@ + // + @implementation OracleAdaptorChannel + +-static void +-DBTerminate() ++static void DBTerminate() + { + if (OCITerminate(OCI_DEFAULT)) + NSLog(@"FAILED: OCITerminate()"); +@@ -89,6 +112,11 @@ + + + (void) initialize + { ++ NSUserDefaults *ud; ++ ++ ud = [NSUserDefaults standardUserDefaults]; ++ debugOn = [ud boolForKey: @"OracleAdaptorDebug"]; ++ + // We Initialize the OCI process environment. + if (OCIInitialize((ub4)OCI_DEFAULT, (dvoid *)0, + (dvoid * (*)(dvoid *, size_t)) 0, +@@ -156,14 +184,17 @@ + [super closeChannel]; + + // We logoff from the database. +- if (OCILogoff(_oci_ctx, _oci_err)) ++ if (!_oci_ctx || !_oci_err || OCILogoff(_oci_ctx, _oci_err)) + { + NSLog(@"FAILED: OCILogoff()"); + } + ++ if (_oci_ctx) ++ OCIHandleFree(_oci_ctx, OCI_HTYPE_SVCCTX); + +- OCIHandleFree(_oci_ctx, OCI_HTYPE_SVCCTX); +- OCIHandleFree(_oci_err, OCI_HTYPE_ERROR); ++ if (_oci_err) ++ OCIHandleFree(_oci_err, OCI_HTYPE_ERROR); ++ + // OCIHandleFree(_oci_env, OCI_HTYPE_ENV); + + _oci_ctx = (OCISvcCtx *)0; +@@ -177,7 +208,8 @@ + // + - (void) dealloc + { +- //NSLog(@"OracleAdaptorChannel: -dealloc"); ++ if (debugOn) ++ NSLog(@"OracleAdaptorChannel: -dealloc"); + + [self _cleanup]; + +@@ -222,7 +254,7 @@ + { + EOAttribute *attribute; + OCIParam *param; +- ++ int rCount; + column_info *info; + ub4 i, clen, count; + text *sql, *cname; +@@ -231,6 +263,9 @@ + + [self _cleanup]; + ++ if (debugOn) ++ [self logWithFormat: @"expression: %@", theExpression]; ++ + if (!theExpression || ![theExpression length]) + { + [NSException raise: @"OracleInvalidExpressionException" +@@ -244,7 +279,9 @@ + } + + sql = (text *)[theExpression UTF8String]; +- ++ ++ rCount = 0; ++ retry: + // We alloc our statement handle + if ((status = OCIHandleAlloc((dvoid *)_oci_env, (dvoid **)&_current_stm, (ub4)OCI_HTYPE_STMT, (CONST size_t) 0, (dvoid **) 0))) + { +@@ -264,13 +301,39 @@ + // We check if we're doing a SELECT and if so, we're fetching data! + OCIAttrGet(_current_stm, OCI_HTYPE_STMT, &type, 0, OCI_ATTR_STMT_TYPE, _oci_err); + self->isFetchInProgress = (type == OCI_STMT_SELECT ? YES : NO); +- ++ + // We execute our statement. Not that we _MUST_ set iter to 0 for non-SELECT statements. + if ((status = OCIStmtExecute(_oci_ctx, _current_stm, _oci_err, (self->isFetchInProgress ? (ub4)0 : (ub4)1), (ub4)0, (CONST OCISnapshot *)NULL, (OCISnapshot *)NULL, + ([(OracleAdaptorContext *)[self adaptorContext] autoCommit] ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT)))) + { ++ ub4 serverStatus; ++ + checkerr(_oci_err, status); + NSLog(@"Statement execute failed (OCI_ERROR): %@", theExpression); ++ ++ // We check to see if we lost connection and need to reconnect. ++ serverStatus = 0; ++ OCIAttrGet((dvoid *)_oci_env, OCI_HTYPE_SERVER, (dvoid *)&serverStatus, (ub4 *)0, OCI_ATTR_SERVER_STATUS, _oci_err); ++ ++ if (serverStatus == OCI_SERVER_NOT_CONNECTED) ++ { ++ // We cleanup our previous handles ++ [self cancelFetch]; ++ [self closeChannel]; ++ ++ // We try to reconnect a couple of times before giving up... ++ while (rCount < maxTry) ++ { ++ usleep(maxSleep); ++ rCount++; ++ ++ if ([self openChannel]) ++ { ++ NSLog(@"Connection re-established to Oracle - retrying to process the statement."); ++ goto retry; ++ } ++ } ++ } + return NO; + } + +@@ -302,7 +365,9 @@ + // We read the maximum width of a column + info->max_width = 0; + status = OCIAttrGet((dvoid*)param, (ub4)OCI_DTYPE_PARAM, (dvoid*)&(info->max_width), (ub4 *)0, (ub4)OCI_ATTR_DATA_SIZE, (OCIError *)_oci_err); +- ++ ++ if (debugOn) ++ NSLog(@"name: %s, type: %d", cname, info->type); + attribute = [EOAttribute attributeWithOracleType: info->type name: cname length: clen width: info->max_width]; + [_resultSetProperties addObject: attribute]; + +@@ -394,16 +459,17 @@ + return NO; + } + +- + if (OCIEnvInit((OCIEnv **)&_oci_env, (ub4)OCI_DEFAULT, (size_t)0, (dvoid **)0)) + { + NSLog(@"FAILED: OCIEnvInit()"); ++ [self closeChannel]; + return NO; + } + + if (OCIHandleAlloc((dvoid *)_oci_env, (dvoid *)&_oci_err, (ub4)OCI_HTYPE_ERROR, (size_t)0, (dvoid **)0)) + { + NSLog(@"FAILED: OCIHandleAlloc() on errhp"); ++ [self closeChannel]; + return NO; + } + +@@ -414,7 +480,10 @@ + // Under Oracle 10g, the third parameter of OCILogon() has the form: [//]host[:port][/service_name] + // See http://download-west.oracle.com/docs/cd/B12037_01/network.101/b10775/naming.htm#i498306 for + // all juicy details. +- database = [[NSString stringWithFormat:@"%@:%@", [o serverName], [o port]] UTF8String]; ++ if ([o serverName] && [o port]) ++ database = [[NSString stringWithFormat:@"%@:%@/%@", [o serverName], [o port], [o databaseName]] UTF8String]; ++ else ++ database = [[o databaseName] UTF8String]; + + // We logon to the database. + if (OCILogon(_oci_env, _oci_err, &_oci_ctx, (const OraText*)username, strlen(username), +@@ -422,6 +491,7 @@ + { + NSLog(@"FAILED: OCILogon(). username = %s password = %s" + @" database = %s", username, password, database); ++ [self closeChannel]; + return NO; + } + +@@ -438,6 +508,11 @@ + { + sword status; + ++ // We check if our connection is open prior to trying to fetch any data. OCIStmtFetch2() returns ++ // NO error code if the OCI environment is set up but the OCILogon() has failed. ++ if (![self isOpen]) ++ return nil; ++ + status = OCIStmtFetch2(_current_stm, _oci_err, (ub4)1, (ub4)OCI_FETCH_NEXT, (sb4)0, (ub4)OCI_DEFAULT); + + if (status == OCI_NO_DATA) +@@ -609,7 +684,7 @@ + + /* GCSEOAdaptorChannel protocol */ + static NSString *sqlFolderFormat = (@"CREATE TABLE %@ (\n" \ +- @" c_name VARCHAR2 (256) NOT NULL,\n" ++ @" c_name VARCHAR2 (256) NOT NULL PRIMARY KEY,\n" + @" c_content CLOB NOT NULL,\n" + @" c_creationdate INTEGER NOT NULL,\n" + @" c_lastmodified INTEGER NOT NULL,\n" +Index: sope-gdl1/Oracle8/OracleAdaptorChannelController.m +=================================================================== +--- sope-gdl1/Oracle8/OracleAdaptorChannelController.m (revision 1660) ++++ sope-gdl1/Oracle8/OracleAdaptorChannelController.m (working copy) +@@ -31,6 +31,8 @@ + #import <Foundation/Foundation.h> + #import <GDLAccess/EOSQLExpression.h> + ++static BOOL debugOn = NO; ++ + // + // + // +@@ -48,6 +50,14 @@ + // + @implementation OracleAdaptorChannelController + +++ (void) initialize ++{ ++ NSUserDefaults *ud; ++ ++ ud = [NSUserDefaults standardUserDefaults]; ++ debugOn = [ud boolForKey: @"OracleAdaptorDebug"]; ++} ++ + - (EODelegateResponse) adaptorChannel: (id) theChannel + willInsertRow: (NSMutableDictionary *) theRow + forEntity: (EOEntity *) theEntity +@@ -56,7 +66,8 @@ + NSArray *keys; + int i, c; + +- NSLog(@"willInsertRow: %@ %@", [theRow description], [theEntity description]); ++ if (debugOn) ++ NSLog(@"willInsertRow: %@ %@", [theRow description], [theEntity description]); + + s = AUTORELEASE([[NSMutableString alloc] init]); + +@@ -101,7 +112,8 @@ + NSArray *keys; + int i, c; + +- NSLog(@"willUpdatetRow: %@ %@", [theRow description], [theQualifier description]); ++ if (debugOn) ++ NSLog(@"willUpdateRow: %@ %@", [theRow description], [theQualifier description]); + + s = AUTORELEASE([[NSMutableString alloc] init]); + +Index: sope-mime/NGImap4/NGImap4Functions.m +=================================================================== +--- sope-mime/NGImap4/NGImap4Functions.m (revision 1660) ++++ sope-mime/NGImap4/NGImap4Functions.m (working copy) +@@ -367,3 +367,16 @@ + } + + @end /* NGImap4FolderHandler */ ++ ++NSString * ++SaneFolderName(NSString *folderName) ++{ ++ NSString *saneFName; ++ ++ saneFName = [[folderName stringByReplacingString: @"\\" ++ withString: @"\\\\"] ++ stringByReplacingString: @"\"" ++ withString: @"\\\""]; ++ ++ return saneFName; ++} +Index: sope-mime/NGImap4/NGImap4Client.h +=================================================================== +--- sope-mime/NGImap4/NGImap4Client.h (revision 1660) ++++ sope-mime/NGImap4/NGImap4Client.h (working copy) +@@ -62,6 +62,8 @@ + NGImap4ResponseNormalizer *normer; + NSMutableArray *responseReceiver; + ++ BOOL loggedIn; ++ + BOOL isLogin; + unsigned tagId; + +@@ -120,6 +122,7 @@ + - (NSDictionary *)list:(NSString *)_folder pattern:(NSString *)_pattern; + - (NSDictionary *)lsub:(NSString *)_folder pattern:(NSString *)_pattern; + - (NSDictionary *)select:(NSString *)_folder; ++- (NSDictionary *)unselect; + - (NSDictionary *)status:(NSString *)_folder flags:(NSArray *)_flags; + - (NSDictionary *)rename:(NSString *)_folder to:(NSString *)_newName; + - (NSDictionary *)delete:(NSString *)_folder; +@@ -138,7 +141,7 @@ + flags:(NSArray *)_flags; + - (NSDictionary *)storeFrom:(unsigned)_from to:(unsigned)_to + add:(NSNumber *)_add flags:(NSArray *)_flags; +-- (NSDictionary *)storeFlags:(NSArray *)_flags forMSNs:(id)_msns ++- (NSDictionary *)storeFlags:(NSArray *)_flags forUIDs:(id)_uids + addOrRemove:(BOOL)_flag; + + - (NSDictionary *)copyUid:(unsigned)_uid toFolder:(NSString *)_folder; +Index: sope-mime/NGImap4/NGImap4Client.m +=================================================================== +--- sope-mime/NGImap4/NGImap4Client.m (revision 1660) ++++ sope-mime/NGImap4/NGImap4Client.m (working copy) +@@ -24,6 +24,8 @@ + #include "NGImap4Client.h" + #include "NGImap4Context.h" + #include "NGImap4Support.h" ++#include "NGImap4Envelope.h" ++#include "NGImap4EnvelopeAddress.h" + #include "NGImap4Functions.h" + #include "NGImap4ResponseParser.h" + #include "NGImap4ResponseNormalizer.h" +@@ -53,17 +55,17 @@ + + @end /* NGImap4Client(ConnectionRegistration); */ + +-#if GNUSTEP_BASE_LIBRARY +-/* FIXME: TODO: move someplace better (hh: NGExtensions...) */ +-@implementation NSException(setUserInfo) ++// #if GNUSTEP_BASE_LIBRARY ++// /* FIXME: TODO: move someplace better (hh: NGExtensions...) */ ++// @implementation NSException(setUserInfo) + +-- (id)setUserInfo:(NSDictionary *)_userInfo { +- ASSIGN(self->_e_info, _userInfo); +- return self; +-} ++// - (id)setUserInfo:(NSDictionary *)_userInfo { ++// ASSIGN(self->_e_info, _userInfo); ++// return self; ++// } + +-@end /* NSException(setUserInfo) */ +-#endif ++// @end /* NSException(setUserInfo) */ ++// #endif + + @interface NGImap4Client(Private) + +@@ -84,6 +86,8 @@ + + - (NSDictionary *)login; + ++- (NSDictionary *) _sopeSORT: (id)_sortSpec qualifier:(EOQualifier *)_qual encoding:(NSString *)_encoding; ++ + @end + + /* +@@ -110,6 +114,8 @@ + static BOOL ImapDebugEnabled = NO; + static NSArray *Imap4SystemFlags = nil; + ++static NSMutableDictionary *capabilities; ++ + - (BOOL)useSSL { + return self->useSSL; + } +@@ -140,6 +146,8 @@ + + Imap4SystemFlags = [[NSArray alloc] initWithObjects: @"seen", @"answered", + @"deleted", @"draft", nil]; ++ ++ capabilities = [[NSMutableDictionary alloc] init]; + } + + /* constructors */ +@@ -195,11 +203,14 @@ + self->debug = ImapDebugEnabled; + self->responseReceiver = [[NSMutableArray alloc] initWithCapacity:128]; + self->normer = [[NGImap4ResponseNormalizer alloc] initWithClient:self]; ++ self->loggedIn = NO; ++ self->context = nil; + } + return self; + } + + - (void)dealloc { ++ if (self->loggedIn) [self logout]; + [self removeFromConnectionRegister]; + [self->normer release]; + [self->text release]; +@@ -457,8 +468,8 @@ + - (void)reconnect { + if ([self->context lastException] != nil) + return; +- +- [self closeConnection]; ++ ++ [self closeConnection]; + self->tagId = 0; + [self openConnection]; + +@@ -481,6 +492,7 @@ + */ + NGHashMap *map; + NSString *s, *log; ++ NSDictionary *response; + + if (self->isLogin ) + return nil; +@@ -499,7 +511,11 @@ + + self->isLogin = NO; + +- return [self->normer normalizeResponse:map]; ++ response = [self->normer normalizeResponse:map]; ++ ++ self->loggedIn = [[response valueForKey:@"result"] boolValue]; ++ ++ return response; + } + + - (NSDictionary *)logout { +@@ -508,6 +524,8 @@ + + map = [self processCommand:@"logout"]; + [self closeConnection]; ++ [self->selectedFolder release]; self->selectedFolder = nil; ++ self->loggedIn = NO; + + return [self->normer normalizeResponse:map]; + } +@@ -547,7 +565,7 @@ + if (!(_pattern = [self _folder2ImapFolder:_pattern])) + return nil; + +- s = [NSString stringWithFormat:@"list \"%@\" \"%@\"", _folder, _pattern]; ++ s = [NSString stringWithFormat:@"list \"%@\" \"%@\"", SaneFolderName(_folder), _pattern]; + map = [self processCommand:s]; + + if (self->delimiter == nil) { +@@ -563,9 +581,20 @@ + } + + - (NSDictionary *)capability { ++ NSDictionary *result; + id capres; +- capres = [self processCommand:@"capability"]; +- return [self->normer normalizeCapabilityRespone:capres]; ++ ++ result = [capabilities objectForKey: [self->address description]]; ++ ++ if (!result) ++ { ++ capres = [self processCommand:@"capability"]; ++ result = [self->normer normalizeCapabilityRespone:capres]; ++ ++ if (result) ++ [capabilities setObject: result forKey: [self->address description]]; ++ } ++ return result; + } + + - (NSDictionary *)lsub:(NSString *)_folder pattern:(NSString *)_pattern { +@@ -591,7 +620,7 @@ + return nil; + } + +- s = [NSString stringWithFormat:@"lsub \"%@\" \"%@\"", _folder, _pattern]; ++ s = [NSString stringWithFormat:@"lsub \"%@\" \"%@\"", SaneFolderName(_folder), _pattern]; + map = [self processCommand:s]; + + if (self->delimiter == nil) { +@@ -617,24 +646,25 @@ + 'flags' - array of strings (eg (answered,flagged,draft,seen); + 'RawResponse' - the raw IMAP4 response + */ +- NSString *s; +- id tmp; +- +- tmp = self->selectedFolder; // remember ptr to old folder name +- ++ NSString *s, *newFolder; ++ + if (![_folder isNotEmpty]) + return nil; + if ((_folder = [self _folder2ImapFolder:_folder]) == nil) + return nil; + +- self->selectedFolder = [_folder copy]; +- +- [tmp release]; tmp = nil; // release old folder name ++ newFolder = [NSString stringWithString: _folder]; ++ ASSIGN (self->selectedFolder, newFolder); + +- s = [NSString stringWithFormat:@"select \"%@\"", self->selectedFolder]; ++ s = [NSString stringWithFormat:@"select \"%@\"", SaneFolderName(self->selectedFolder)]; + return [self->normer normalizeSelectResponse:[self processCommand:s]]; + } + ++- (NSDictionary *)unselect { ++ [self->selectedFolder release]; self->selectedFolder = nil; ++ return [self->normer normalizeResponse:[self processCommand:@"unselect"]]; ++} ++ + - (NSDictionary *)status:(NSString *)_folder flags:(NSArray *)_flags { + NSString *cmd; + +@@ -646,7 +676,7 @@ + return nil; + + cmd = [NSString stringWithFormat:@"status \"%@\" (%@)", +- _folder, [_flags componentsJoinedByString:@" "]]; ++ SaneFolderName(_folder), [_flags componentsJoinedByString:@" "]]; + return [self->normer normalizeStatusResponse:[self processCommand:cmd]]; + } + +@@ -663,24 +693,28 @@ + if ((_newName = [self _folder2ImapFolder:_newName]) == nil) + return nil; + +- cmd = [NSString stringWithFormat:@"rename \"%@\" \"%@\"", _folder, _newName]; ++ cmd = [NSString stringWithFormat:@"rename \"%@\" \"%@\"", ++ SaneFolderName(_folder), SaneFolderName(_newName)]; + + return [self->normer normalizeResponse:[self processCommand:cmd]]; + } + + - (NSDictionary *)_performCommand:(NSString *)_op onFolder:(NSString *)_fname { + NSString *command; +- ++ + if ((_fname = [self _folder2ImapFolder:_fname]) == nil) + return nil; +- ++ + // eg: 'delete "blah"' +- command = [NSString stringWithFormat:@"%@ \"%@\"", _op, _fname]; +- ++ command = [NSString stringWithFormat:@"%@ \"%@\"", _op, SaneFolderName(_fname)]; ++ + return [self->normer normalizeResponse:[self processCommand:command]]; + } + + - (NSDictionary *)delete:(NSString *)_name { ++ if ([self->selectedFolder isEqualToString:_name]) { ++ [self unselect]; ++ } + return [self _performCommand:@"delete" onFolder:_name]; + } + - (NSDictionary *)create:(NSString *)_name { +@@ -820,23 +854,23 @@ + return [self->normer normalizeResponse:[self processCommand:cmd]]; + } + +-- (NSDictionary *)storeFlags:(NSArray *)_flags forMSNs:(id)_msns ++- (NSDictionary *)storeFlags:(NSArray *)_flags forUIDs:(id)_uids + addOrRemove:(BOOL)_flag + { + NSString *cmd; + NSString *flagstr; + NSString *seqstr; + +- if ([_msns isKindOfClass:[NSArray class]]) { ++ if ([_uids isKindOfClass:[NSArray class]]) { + // TODO: improve by using ranges, eg 1:5 instead of 1,2,3,4,5 +- _msns = [_msns valueForKey:@"stringValue"]; +- seqstr = [_msns componentsJoinedByString:@","]; ++ _uids = [_uids valueForKey:@"stringValue"]; ++ seqstr = [_uids componentsJoinedByString:@","]; + } + else +- seqstr = [_msns stringValue]; ++ seqstr = [_uids stringValue]; + + flagstr = [_flags2ImapFlags(self, _flags) componentsJoinedByString:@" "]; +- cmd = [NSString stringWithFormat:@"store %@ %cFLAGS (%@)", ++ cmd = [NSString stringWithFormat:@"UID STORE %@ %cFLAGS (%@)", + seqstr, _flag ? '+' : '-', flagstr]; + + return [self->normer normalizeResponse:[self processCommand:cmd]]; +@@ -967,11 +1001,12 @@ + descr = @"Could not process qualifier for imap search "; + descr = [descr stringByAppendingString:reason]; + +- exception = [[NGImap4SearchException alloc] initWithFormat:@"%@", descr]; + ui = [NSDictionary dictionaryWithObject:_q forKey:@"qualifier"]; +- [exception setUserInfo:ui]; ++ exception ++ = [NGImap4SearchException exceptionWithName: @"NGImap4SearchException" ++ reason: descr ++ userInfo: ui]; + [self->context setLastException:exception]; +- [exception release]; + } + + - (NSString *)_searchExprForQual:(EOQualifier *)_qualifier { +@@ -1093,7 +1128,18 @@ + Eg: UID SORT ( DATE REVERSE SUBJECT ) UTF-8 TODO + */ + NSString *tmp; ++ NSArray *capa; + ++ // We first check to see if our server supports IMAP SORT. If not ++ // we'll sort ourself the results. ++ capa = [[self capability] objectForKey: @"capability"]; ++ ++ if ([capa indexOfObject: @"sort"] == NSNotFound) ++ { ++ return [self _sopeSORT: _sortSpec qualifier: _qual encoding: _encoding]; ++ } ++ ++ + if ([_sortSpec isKindOfClass:[NSArray class]]) + tmp = [self _generateIMAP4SortOrderings:_sortSpec]; + else if ([_sortSpec isKindOfClass:[EOSortOrdering class]]) +@@ -1107,9 +1153,10 @@ + tmp = @"DATE"; + } + ++ + return [self primarySort:tmp +- qualifierString:[self _searchExprForQual:_qual] +- encoding:_encoding]; ++ qualifierString:[self _searchExprForQual:_qual] ++ encoding:_encoding]; + } + - (NSDictionary *)sort:(NSArray *)_sortOrderings + qualifier:(EOQualifier *)_qual +@@ -1130,7 +1177,7 @@ + return nil; + } + +- s = [@"search" stringByAppendingString:s]; ++ s = [@"UID SEARCH" stringByAppendingString:s]; + return [self->normer normalizeSearchResponse:[self processCommand:s]]; + } + +@@ -1142,7 +1189,7 @@ + if ((_folder = [self _folder2ImapFolder:_folder]) == nil) + return nil; + +- cmd = [NSString stringWithFormat:@"getacl \"%@\"", _folder]; ++ cmd = [NSString stringWithFormat:@"getacl \"%@\"", SaneFolderName(_folder)]; + return [self->normer normalizeGetACLResponse:[self processCommand:cmd]]; + } + +@@ -1155,7 +1202,7 @@ + return nil; + + cmd = [NSString stringWithFormat:@"setacl \"%@\" \"%@\" \"%@\"", +- _folder, _uid, _r]; ++ SaneFolderName(_folder), _uid, _r]; + return [self->normer normalizeResponse:[self processCommand:cmd]]; + } + +@@ -1166,7 +1213,7 @@ + return nil; + + cmd = [NSString stringWithFormat:@"deleteacl \"%@\" \"%@\"", +- _folder, _uid]; ++ SaneFolderName(_folder), _uid]; + return [self->normer normalizeResponse:[self processCommand:cmd]]; + } + +@@ -1177,7 +1224,7 @@ + return nil; + + cmd = [NSString stringWithFormat:@"listrights \"%@\" \"%@\"", +- _folder, _uid]; ++ SaneFolderName(_folder), _uid]; + return [self->normer normalizeListRightsResponse:[self processCommand:cmd]]; + } + +@@ -1187,12 +1234,94 @@ + if ((_folder = [self _folder2ImapFolder:_folder]) == nil) + return nil; + +- cmd = [NSString stringWithFormat:@"myrights \"%@\"", _folder]; ++ cmd = [NSString stringWithFormat:@"myrights \"%@\"", SaneFolderName(_folder)]; + return [self->normer normalizeMyRightsResponse:[self processCommand:cmd]]; + } + + /* Private Methods */ + ++- (NSDictionary *) _sopeSORT: (id)_sortSpec qualifier:(EOQualifier *)_qual encoding:(NSString *)_encoding { ++ NSMutableDictionary *result; ++ NSDictionary *d; ++ NSCalendarDate *envDate; ++ ++ result = [NSMutableDictionary dictionary]; ++ [result setObject: [NSNumber numberWithBool: NO] forKey: @"result"]; ++ ++ // _sortSpec: [REVERSE] {DATE,FROM,SUBJECT} ++ d = [self searchWithQualifier: _qual]; ++ ++ if ((d = [d objectForKey: @"RawResponse"])) { ++ NSMutableDictionary *dict; ++ NSArray *a, *s_a; ++ BOOL b; ++ int i; ++ ++ a = [d objectForKey: @"search"]; ++ if ([a isNotEmpty]) { ++ d = [self fetchUids: a ++ parts: [NSArray arrayWithObjects: @"ENVELOPE", ++ @"RFC822.SIZE", nil]]; ++ a = [d objectForKey: @"fetch"]; ++ ++ dict = [NSMutableDictionary dictionary]; ++ b = YES; ++ ++ for (i = 0; i < [a count]; i++) { ++ NGImap4Envelope *env; ++ id o, uid, s; ++ ++ o = [a objectAtIndex: i]; ++ env = [o objectForKey: @"envelope"]; ++ uid = [o objectForKey: @"uid"]; ++ ++ if ([_sortSpec rangeOfString: @"SUBJECT"].length) { ++ s = [env subject]; ++ if ([s isKindOfClass: [NSData class]]) ++ s = [[[NSString alloc] initWithData: s encoding: NSUTF8StringEncoding] autorelease]; ++ ++ [dict setObject: (s != nil ? s : (id)@"") forKey: uid]; ++ } ++ else if ([_sortSpec rangeOfString: @"FROM"].length) { ++ s = [[[env from] lastObject] email]; ++ [dict setObject: (s != nil ? s : (id)@"") forKey: uid]; ++ } ++ else if ([_sortSpec rangeOfString: @"SIZE"].length) { ++ s = [o objectForKey: @"size"]; ++ [dict setObject: (s != nil ? s : [NSNumber numberWithInt: 0]) ++ forKey: uid]; ++ b = NO; ++ } ++ else { ++ envDate = [env date]; ++ if (!envDate) ++ envDate = [NSCalendarDate date]; ++ [dict setObject: envDate forKey: uid]; ++ b = NO; ++ } ++ } ++ ++ if (b) ++ s_a = [dict keysSortedByValueUsingSelector: @selector(caseInsensitiveCompare:)]; ++ else ++ s_a = [dict keysSortedByValueUsingSelector: @selector(compare:)]; ++ ++ if ([_sortSpec rangeOfString: @"REVERSE"].length) { ++ s_a = [[s_a reverseObjectEnumerator] allObjects]; ++ } ++ ++ } ++ else { ++ s_a = [NSArray array]; ++ } ++ [result setObject: [NSNumber numberWithBool: YES] forKey: @"result"]; ++ [result setObject: s_a forKey: @"sort"]; ++ } ++ ++ return result; ++} ++ ++ + - (NSException *)_processCommandParserException:(NSException *)_exception { + [self logWithFormat:@"ERROR(%s): catched IMAP4 parser exception %@: %@", + __PRETTY_FUNCTION__, [_exception name], [_exception reason]]; +@@ -1412,21 +1541,24 @@ + return nil; + } + +- array = [_folder pathComponents]; ++// array = [_folder pathComponents]; ++ array = [_folder componentsSeparatedByString:@"/"]; + +- if ([array isNotEmpty]) { ++ if ([array count]) { + NSString *o; + + o = [array objectAtIndex:0]; +- if (([o isEqualToString:@"/"]) || ([o length] == 0)) ++ if ([o length] == 0) + array = [array subarrayWithRange:NSMakeRange(1, [array count] - 1)]; +- +- o = [array lastObject]; +- if (([o length] == 0) || ([o isEqualToString:@"/"])) +- array = [array subarrayWithRange:NSMakeRange(0, [array count] - 1)]; ++ ++ if ([array count]) { ++ o = [array lastObject]; ++ if ([o length] == 0) ++ array = [array subarrayWithRange:NSMakeRange(0, [array count] - 1)]; ++ } + } + return [[array componentsJoinedByString:self->delimiter] +- stringByEncodingImap4FolderName]; ++ stringByEncodingImap4FolderName]; + } + + - (NSString *)_imapFolder2Folder:(NSString *)_folder { +@@ -1442,10 +1574,16 @@ + return nil; + } + ++ if ([_folder hasPrefix: self->delimiter]) ++ _folder = [_folder substringFromIndex: 1]; ++ if ([_folder hasSuffix: self->delimiter]) ++ _folder = [_folder substringToIndex: [_folder length] - 2]; ++ + array = [array arrayByAddingObjectsFromArray: + [_folder componentsSeparatedByString:[self delimiter]]]; +- +- return [[NSString pathWithComponents:array] stringByDecodingImap4FolderName]; ++ ++ return [[array componentsJoinedByString: @"/"] ++ stringByDecodingImap4FolderName]; + } + + - (void)setContext:(NGImap4Context *)_ctx { +Index: sope-mime/NGImap4/NGSieveClient.m +=================================================================== +--- sope-mime/NGImap4/NGSieveClient.m (revision 1660) ++++ sope-mime/NGImap4/NGSieveClient.m (working copy) +@@ -294,8 +294,8 @@ + return con; + } + +- logLen = [self->login cStringLength]; +- bufLen = (logLen * 2) + [self->password cStringLength] +2; ++ logLen = [self->login lengthOfBytesUsingEncoding: NSUTF8StringEncoding]; ++ bufLen = (logLen * 2) + [self->password lengthOfBytesUsingEncoding: NSUTF8StringEncoding] +2; + + buf = calloc(bufLen + 2, sizeof(char)); + +@@ -306,8 +306,9 @@ + password + */ + sprintf(buf, "%s %s %s", +- [self->login cString], [self->login cString], +- [self->password cString]); ++ [self->login cStringUsingEncoding:NSUTF8StringEncoding], ++ [self->login cStringUsingEncoding:NSUTF8StringEncoding], ++ [self->password cStringUsingEncoding:NSUTF8StringEncoding]); + + buf[logLen] = '\0'; + buf[logLen * 2 + 1] = '\0'; +@@ -656,7 +657,7 @@ + fputc('\n', stderr); + } + else +- fprintf(stderr, "C: %s\n", [_txt cString]); ++ fprintf(stderr, "C: %s\n", [_txt cStringUsingEncoding:NSUTF8StringEncoding]); + } + + /* write */ +Index: sope-mime/NGImap4/NGImap4Connection.h +=================================================================== +--- sope-mime/NGImap4/NGImap4Connection.h (revision 1660) ++++ sope-mime/NGImap4/NGImap4Connection.h (working copy) +@@ -89,6 +89,9 @@ + + - (NSArray *)subfoldersForURL:(NSURL *)_url; + - (NSArray *)allFoldersForURL:(NSURL *)_url; ++- (NSArray *)allFoldersForURL:(NSURL *)_url ++ onlySubscribedFolders: (BOOL) subscribedFoldersOnly; ++- (BOOL)selectFolder:(id)_url; + + /* message operations */ + +Index: sope-mime/NGImap4/NGImap4Connection.m +=================================================================== +--- sope-mime/NGImap4/NGImap4Connection.m (revision 1660) ++++ sope-mime/NGImap4/NGImap4Connection.m (working copy) +@@ -22,6 +22,7 @@ + #include "NGImap4Connection.h" + #include "NGImap4MailboxInfo.h" + #include "NGImap4Client.h" ++#include "NGImap4Functions.h" + #include "imCommon.h" + + @implementation NGImap4Connection +@@ -66,7 +67,7 @@ + self->creationTime = [[NSDate alloc] init]; + + // TODO: retrieve from IMAP4 instead of using a default +- self->separator = imap4Separator; ++ self->separator = [imap4Separator copy]; + } + return self; + } +@@ -321,13 +322,15 @@ + return nil; + if ([folderName characterAtIndex:0] == '/') + folderName = [folderName substringFromIndex:1]; ++ if ([folderName hasSuffix: @"/"]) ++ folderName = [folderName substringToIndex:[folderName length] - 1]; + + if (_delfn) folderName = [folderName stringByDeletingLastPathComponent]; + + if ([[self imap4Separator] isEqualToString:@"/"]) + return folderName; + +- names = [folderName pathComponents]; ++ names = [folderName componentsSeparatedByString: @"/"]; + return [names componentsJoinedByString:[self imap4Separator]]; + } + - (NSString *)imap4FolderNameForURL:(NSURL *)_url { +@@ -373,7 +376,9 @@ + + /* folder operations */ + +-- (NSDictionary *)primaryFetchMailboxHierarchyForURL:(NSURL *)_url { ++- (NSDictionary *)primaryFetchMailboxHierarchyForURL:(NSURL *)_url ++ onlySubscribedFolders: (BOOL) subscribedFoldersOnly ++{ + NSDictionary *result; + + if ((result = [self cachedHierarchyResults]) != nil) +@@ -381,8 +386,12 @@ + + if (debugCache) [self logWithFormat:@" no folders cached yet .."]; + +- result = [[self client] list:(onlyFetchInbox ? @"INBOX" : @"*") +- pattern:@"*"]; ++ if (subscribedFoldersOnly) ++ result = [[self client] lsub:(onlyFetchInbox ? @"INBOX" : @"") ++ pattern:@"*"]; ++ else ++ result = [[self client] list:(onlyFetchInbox ? @"INBOX" : @"") ++ pattern:@"*"]; + if (![[result valueForKey:@"result"] boolValue]) { + [self errorWithFormat:@"Could not list mailbox hierarchy!"]; + return nil; +@@ -400,6 +409,11 @@ + return result; + } + ++- (NSDictionary *)primaryFetchMailboxHierarchyForURL:(NSURL *)_url ++{ ++ return [self primaryFetchMailboxHierarchyForURL: _url onlySubscribedFolders: NO]; ++} ++ + - (NSArray *)subfoldersForURL:(NSURL *)_url { + NSDictionary *result; + +@@ -413,10 +427,13 @@ + return [self extractSubfoldersForURL:_url fromResultSet:result]; + } + +-- (NSArray *)allFoldersForURL:(NSURL *)_url { ++- (NSArray *)allFoldersForURL:(NSURL *)_url ++ onlySubscribedFolders: (BOOL) subscribedFoldersOnly ++{ + NSDictionary *result; + +- if ((result = [self primaryFetchMailboxHierarchyForURL:_url]) == nil) ++ if ((result = [self primaryFetchMailboxHierarchyForURL:_url ++ onlySubscribedFolders: subscribedFoldersOnly]) == nil) + return nil; + if ([result isKindOfClass:[NSException class]]) { + [self errorWithFormat:@"failed to retrieve hierarchy: %@", result]; +@@ -426,6 +443,11 @@ + return [self extractFoldersFromResultSet:result]; + } + ++- (NSArray *)allFoldersForURL:(NSURL *)_url ++{ ++ return [self allFoldersForURL: _url onlySubscribedFolders: NO]; ++} ++ + /* message operations */ + + - (NSArray *)fetchUIDsInURL:(NSURL *)_url qualifier:(id)_qualifier +@@ -646,7 +668,7 @@ + + /* store flags */ + +- result = [[self client] storeFlags:_f forMSNs:result addOrRemove:YES]; ++ result = [[self client] storeFlags:_f forUIDs:result addOrRemove:YES]; + if (![[result valueForKey:@"result"] boolValue]) { + return [self errorForResult:result + text:@"Failed to change flags of IMAP4 message"]; +@@ -760,11 +782,11 @@ + // TODO: we should probably just fetch the whole hierarchy? + + folderName = [self imap4FolderNameForURL:_url]; +- result = [[self client] select:folderName]; +- if (![[result valueForKey:@"result"] boolValue]) +- return NO; +- +- return YES; ++ ++ result = [self->client status: folderName ++ flags: [NSArray arrayWithObject: @"UIDVALIDITY"]]; ++ ++ return ([[result valueForKey: @"result"] boolValue]); + } + + - (id)infoForMailboxAtURL:(NSURL *)_url { +@@ -789,7 +811,8 @@ + /* construct path */ + + newPath = [self imap4FolderNameForURL:_url]; +- newPath = [newPath stringByAppendingString:[self imap4Separator]]; ++ if ([newPath length]) ++ newPath = [newPath stringByAppendingString:[self imap4Separator]]; + newPath = [newPath stringByAppendingString:_mailbox]; + + /* create */ +Index: sope-mime/NGImap4/NGImap4ResponseNormalizer.m +=================================================================== +--- sope-mime/NGImap4/NGImap4ResponseNormalizer.m (revision 1660) ++++ sope-mime/NGImap4/NGImap4ResponseNormalizer.m (working copy) +@@ -76,22 +76,6 @@ + return self; + } + +-/* client callbacks */ +- +-- (void)closeConnection { +- [(id)self->client closeConnection]; +-} +- +-- (NSString *)delimiter { +- return [self->client delimiter]; +-} +- +-/* folder handling */ +- +-- (NSString *)_imapFolder2Folder:(NSString *)_folder { +- return [self->client _imapFolder2Folder:_folder]; +-} +- + /* primary */ + + - (NSMutableDictionary *)normalizeResponse:(NGHashMap *)_map { +@@ -117,7 +101,7 @@ + if ((obj = [_map objectForKey:@"bye"])) { + [result setObject:NoNumber forKey:@"result"]; + [result setObject:obj forKey:@"reason"]; +- [self closeConnection]; ++ [self->client closeConnection]; + return result; + } + +@@ -292,7 +276,7 @@ + /* + filter for fetch response + fetch : NSArray (fetch responses) +- 'header' - RFC822.HEADER ++ 'header' - RFC822.HEADER and BODY[HEADER.FIELDS (...)] + 'text' - RFC822.TEXT + 'size' - SIZE + 'flags' - FLAGS +@@ -336,7 +320,12 @@ + switch (c) { + case 'b': + /* Note: we check for _prefix_! eg body[1] is valid too */ +- if (klen > 3 && [key hasPrefix:@"body"]) { ++ if (klen > 17 && [key hasPrefix:@"body[header.fields"]) { ++ keys[count] = @"header"; ++ values[count] = objForKey(obj, @selector(objectForKey:), key); ++ count++; ++ } ++ else if (klen > 3 && [key hasPrefix:@"body"]) { + keys[count] = @"body"; + values[count] = objForKey(obj, @selector(objectForKey:), key); + count++; +@@ -516,7 +505,7 @@ + } + continue; + } +- [tmp setObject:qDesc forKey:[self _imapFolder2Folder:obj]]; ++ [tmp setObject:qDesc forKey:[self->client _imapFolder2Folder:obj]]; + } + [result setObject:tmp forKey:@"quotas"]; + return [[result copy] autorelease]; +@@ -615,7 +604,7 @@ + + while ((o = [enumerator nextObject])) { + [folder setObject:_imapFlags2Flags(self, [o objectForKey:@"flags"]) +- forKey:[self _imapFolder2Folder:[o objectForKey:@"folderName"]]]; ++ forKey:[self->client _imapFolder2Folder:[o objectForKey:@"folderName"]]]; + } + + { +@@ -648,14 +637,13 @@ + enumerator = [_flags objectEnumerator]; + cnt = 0; + while ((obj = [enumerator nextObject])) { +- if (![obj isNotEmpty]) +- continue; +- +- if (![[obj substringToIndex:1] isEqualToString:@"\\"]) +- continue; +- +- objs[cnt] = [obj substringFromIndex:1]; +- cnt++; ++ if ([obj isNotEmpty]) { ++ if ([obj hasPrefix:@"\\"]) ++ objs[cnt] = [obj substringFromIndex:1]; ++ else ++ objs[cnt] = obj; ++ cnt++; ++ } + } + result = [NSArray arrayWithObjects:objs count:cnt]; + if (objs) free(objs); +Index: sope-mime/NGImap4/EOQualifier+IMAPAdditions.m +=================================================================== +--- sope-mime/NGImap4/EOQualifier+IMAPAdditions.m (revision 1660) ++++ sope-mime/NGImap4/EOQualifier+IMAPAdditions.m (working copy) +@@ -53,13 +53,13 @@ + if (FlagKeyWords) return; + + ud = [NSUserDefaults standardUserDefaults]; +- FlagKeyWords = [[NSArray alloc] initWithObjects: @"answered", @"deleted", +- @"draft", @"flagged", @"new", @"old", @"recent", +- @"seen", @"unanswered", @"undeleted", @"undraft", +- @"unflagged", @"unseen", nil]; +- OtherKeyWords = [[NSArray alloc] initWithObjects: +- @"bcc", @"body", @"cc", @"from", @"subject", +- @"text", @"to", @"keyword", @"unkeyword", nil]; ++ FlagKeyWords = [[NSArray alloc] initWithObjects: @"ANSWERED", @"DELETED", ++ @"DRAFT", @"FLAGGED", @"NEW", @"OLD", @"RECENT", ++ @"SEEN", @"UNANSWERED", @"UNDELETED", @"UNDRAFT", ++ @"UNFLAGGED", @"UNSEEN", nil]; ++ OtherKeyWords = [[NSArray alloc] initWithObjects: @"ALL", @"BCC", @"BODY", ++ @"CC", @"FROM", @"SUBJECT", @"TEXT", @"TO", ++ @"KEYWORD", @"UID", @"UNKEYWORD", nil]; + + debugOn = [ud boolForKey:@"ImapDebugQualifierGeneration"]; + } +@@ -266,10 +266,10 @@ + + enumerator = [lvalue objectEnumerator]; + while ((lvalue = [enumerator nextObject]) != nil) { +- lvalue = [lvalue lowercaseString]; ++ lvalue = [lvalue uppercaseString]; + + if ([FlagKeyWords containsObject:lvalue]) { +- if (insertNot) [search appendString:@"not "]; ++ if (insertNot) [search appendString:@"NOT "]; + [search appendString:lvalue]; + } + else { +@@ -280,15 +280,31 @@ + return nil; + } + +-- (NSString *)imap4OperatorForDateComparisonSelector:(SEL)lselector { ++- (NSString *)imap4OperatorForDateKeyword:(NSString *)dkey ++andComparisonSelector:(SEL)lselector { ++ NSString *operatorPrefix, *dateOperator, *imap4Operator; ++ + if (sel_eq(lselector, EOQualifierOperatorEqual)) +- return @" senton "; +- if (sel_eq(lselector, EOQualifierOperatorGreaterThan)) +- return @" sentsince "; +- if (sel_eq(lselector, EOQualifierOperatorLessThan)) +- return @" sentbefore "; +- +- return nil; ++ dateOperator = @"ON"; ++ else if (sel_eq(lselector, EOQualifierOperatorGreaterThan)) ++ dateOperator = @"SINCE"; ++ else if (sel_eq(lselector, EOQualifierOperatorLessThan)) ++ dateOperator = @"BEFORE"; ++ else ++ dateOperator = nil; ++ ++ if (dateOperator) { ++ if ([dkey isEqualToString: @"DATE"]) ++ operatorPrefix = @"SENT"; ++ else ++ operatorPrefix = @""; ++ imap4Operator = [NSString stringWithFormat: @"%@%@ ", ++ operatorPrefix, dateOperator]; ++ } ++ else ++ imap4Operator = nil; ++ ++ return imap4Operator; + } + + - (NSException *)appendToImap4SearchString:(NSMutableString *)search +@@ -300,11 +316,11 @@ + id lvalue; + SEL lselector; + +- lkey = [[self key] lowercaseString]; ++ lkey = [[self key] uppercaseString]; + lvalue = [self value]; + lselector = [self selector]; + +- if ([lkey isEqualToString:@"flags"]) { ++ if ([lkey isEqualToString:@"FLAGS"]) { + /* NOTE: special "not" processing! */ + return [self appendFlagsCheckToImap4SearchString:search + insertNot:insertNot]; +@@ -312,9 +328,9 @@ + + /* not a flag */ + if (insertNot) +- [search appendString:@"not "]; ++ [search appendString:@"NOT "]; + +- if ([lkey isEqualToString:@"date"]) { ++ if ([lkey isEqualToString:@"DATE"] || [lkey isEqualToString:@"RECEIVE-DATE"]) { + NSString *s; + + if (![lvalue isKindOfClass:[NSCalendarDate class]]) { +@@ -322,35 +338,38 @@ + @"expected a NSDate as value"]; + } + +- if ((s = [self imap4OperatorForDateComparisonSelector:lselector]) == nil) ++ if ((s = [self imap4OperatorForDateKeyword:lkey ++ andComparisonSelector:lselector]) == nil) + return [self invalidImap4SearchQualifier:@"unexpected selector"]; + +- // TODO: operator created but NOT added? ++ [search appendString:s]; + + // TODO: much faster without descriptionWithCalendarFormat:?! +- s = [lvalue descriptionWithCalendarFormat:@"%d-%b-%Y"]; ++ s = [lvalue descriptionWithCalendarFormat:@"\"%d-%b-%Y\""]; + [search appendString:s]; + return nil; + } + +- if ([lkey isEqualToString:@"uid"]) { +- if (!sel_eq(lselector, EOQualifierOperatorEqual)) ++ if ([lkey isEqualToString:@"UID"]) { ++ if (!sel_eq(lselector, EOQualifierOperatorEqual)) { + return [self invalidImap4SearchQualifier:@"unexpected qualifier 2"]; ++ } + +- [search appendString:@"uid "]; ++ [search appendString:@"UID "]; + [search appendString:[lvalue stringValue]]; + return nil; + } + +- if ([lkey isEqualToString:@"size"]) { ++ if ([lkey isEqualToString:@"SIZE"]) { + if (sel_eq(lselector, EOQualifierOperatorGreaterThan)) +- [search appendString:@"larger "]; ++ [search appendString:@"LARGER "]; + else if (sel_eq(lselector, EOQualifierOperatorLessThan)) +- [search appendString:@"smaller "]; ++ [search appendString:@"SMALLER "]; + else + return [self invalidImap4SearchQualifier:@"unexpected qualifier 3"]; + + [search appendString:[lvalue stringValue]]; ++ + return nil; + } + +@@ -386,7 +405,7 @@ + if (!sel_eq(lselector, EOQualifierOperatorEqual)) + return [self invalidImap4SearchQualifier:@"unexpected qualifier 5"]; + +- [search appendString:@"header "]; ++ [search appendString:@"HEADER "]; + [search appendString:lkey]; + [search appendString:@" \""]; + [search appendString:[lvalue stringValue]]; +Index: sope-mime/NGImap4/NGImap4ResponseParser.m +=================================================================== +--- sope-mime/NGImap4/NGImap4ResponseParser.m (revision 1660) ++++ sope-mime/NGImap4/NGImap4ResponseParser.m (working copy) +@@ -31,6 +31,7 @@ + @interface NGImap4ResponseParser(ParsingPrivates) + - (BOOL)_parseNumberUntaggedResponse:(NGMutableHashMap *)result_; + - (NSDictionary *)_parseBodyContent; ++- (NSData *) _parseBodyHeaderFields; + + - (NSData *)_parseData; + +@@ -84,6 +85,8 @@ + static NSDictionary *_parseMultipartBody(NGImap4ResponseParser *self, + BOOL isBodyStructure); + ++static NSArray *_parseLanguages(); ++ + static NSString *_parseBodyString(NGImap4ResponseParser *self, + BOOL _convertString); + static NSString *_parseBodyDecodeString(NGImap4ResponseParser *self, +@@ -111,6 +114,7 @@ + static NSNumber *_parseUnsigned(NGImap4ResponseParser *self); + static NSString *_parseUntil(NGImap4ResponseParser *self, char _c); + static NSString *_parseUntil2(NGImap4ResponseParser *self, char _c1, char _c2); ++static BOOL _endsWithCQuote(NSString *_string); + + static __inline__ NSException *_consumeIfMatch + (NGImap4ResponseParser *self, unsigned char _m); +@@ -488,6 +492,50 @@ + return [self _parseDataIntoRAM:size]; + } + ++/* ++ Similair to _parseData but used to parse something like this : ++ ++ BODY[HEADER.FIELDS (X-PRIORITY)] {17} ++ X-Priority: 1 ++ ++ ) ++ ++ Headers are returned as data, as is. ++*/ ++- (NSData *) _parseBodyHeaderFields ++{ ++ NSData *result; ++ unsigned size; ++ NSNumber *sizeNum; ++ ++ /* we skip until we're ready to parse {length} */ ++ _parseUntil(self, '{'); ++ ++ result = nil; ++ ++ if ((sizeNum = _parseUnsigned(self)) == nil) { ++ NSException *e; ++ ++ e = [[NGImap4ParserException alloc] ++ initWithFormat:@"expect a number between {}"]; ++ [self setLastException:[e autorelease]]; ++ return nil; ++ } ++ _consumeIfMatch(self, '}'); ++ _consumeIfMatch(self, '\n'); ++ ++ if ((size = [sizeNum intValue]) == 0) { ++ [self logWithFormat:@"ERROR(%s): got content size '0'!", ++ __PRETTY_FUNCTION__]; ++ return nil; ++ } ++ ++ if (UseMemoryMappedData && (size > Imap4MMDataBoundary)) ++ return [self _parseDataToFile:size]; ++ ++ return [self _parseDataIntoRAM:size]; ++} ++ + static int _parseTaggedResponse(NGImap4ResponseParser *self, + NGMutableHashMap *result_) + { +@@ -648,13 +696,124 @@ + [result_ addObject:_parseUntil(self, '\n') forKey:@"description"]; + } + ++static inline void ++_purifyQuotedString(NSMutableString *quotedString) { ++ unichar *currentChar, *qString, *maxC, *startC; ++ unsigned int max, questionMarks; ++ BOOL possiblyQuoted, skipSpaces; ++ NSMutableString *newString; ++ ++ newString = [NSMutableString string]; ++ ++ max = [quotedString length]; ++ qString = malloc (sizeof (unichar) * max); ++ [quotedString getCharacters: qString]; ++ currentChar = qString; ++ startC = qString; ++ maxC = qString + max; ++ ++ possiblyQuoted = NO; ++ skipSpaces = NO; ++ ++ questionMarks = 0; ++ ++ while (currentChar < maxC) { ++ if (possiblyQuoted) { ++ if (questionMarks == 2) { ++ if ((*currentChar == 'Q' || *currentChar == 'q' ++ || *currentChar == 'B' || *currentChar == 'b') ++ && ((currentChar + 1) < maxC ++ && (*(currentChar + 1) == '?'))) { ++ currentChar++; ++ questionMarks = 3; ++ } ++ else { ++ possiblyQuoted = NO; ++ } ++ } ++ else if (questionMarks == 4) { ++ if (*currentChar == '=') { ++ skipSpaces = YES; ++ possiblyQuoted = NO; ++ currentChar++; ++ [newString appendString: [NSString stringWithCharacters: startC ++ length: (currentChar - startC)]]; ++ startC = currentChar; ++ } ++ else { ++ possiblyQuoted = NO; ++ } ++ } ++ else { ++ if (*currentChar == '?') { ++ questionMarks++; ++ } ++ else if (*currentChar == ' ' && questionMarks != 3) { ++ possiblyQuoted = NO; ++ } ++ } ++ } ++ else if (*currentChar == '=' ++ && ((currentChar + 1) < maxC ++ && (*(currentChar + 1) == '?'))) { ++ [newString appendString: [NSString stringWithCharacters: startC ++ length: (currentChar - startC)]]; ++ startC = currentChar; ++ possiblyQuoted = YES; ++ skipSpaces = NO; ++ currentChar++; ++ questionMarks = 1; ++ } ++ ++ currentChar++; ++ ++ if (skipSpaces) { ++ while (currentChar < maxC ++ && (*currentChar == ' ' ++ || *currentChar == '\t')) ++ currentChar++; ++ skipSpaces = NO; ++ startC = currentChar; ++ } ++ } ++ ++ if (startC < maxC) ++ [newString appendString: [NSString stringWithCharacters: startC ++ length: (currentChar - startC)]]; ++ ++ [quotedString setString: newString]; ++ free (qString); ++} ++ + - (NSString *)_parseQuotedString { ++ NSMutableString *quotedString; ++ NSString *tmpString; ++ BOOL stop; ++ + /* parse a quoted string, eg '"' */ + if (_la(self, 0) == '"') { + _consume(self, 1); +- return _parseUntil(self, '"'); ++ quotedString = [NSMutableString string]; ++ stop = NO; ++ while (!stop) { ++ tmpString = _parseUntil(self, '"'); ++ [quotedString appendString: tmpString]; ++ if(_endsWithCQuote(tmpString)) { ++ [quotedString deleteSuffix: @"\\"]; ++ [quotedString appendString: @"\""]; ++ } ++ else { ++ stop = YES; ++ } ++ } + } +- return nil; ++ else { ++ quotedString = nil; ++ } ++ ++ _purifyQuotedString(quotedString); ++ ++ return quotedString; + } + - (void)_consumeOptionalSpace { + if (_la(self, 0) == ' ') _consume(self, 1); +@@ -685,6 +844,10 @@ + name = [self _parseQuotedString]; + _parseUntil(self, '\n'); + } ++ else if (_la(self, 0) == '{') { ++ name = [self _parseQuotedStringOrNIL]; ++ _parseUntil(self, '\n'); ++ } + else + name = _parseUntil(self, '\n'); + +@@ -1030,10 +1193,15 @@ + _consume(self, 7); + + if (_la(self, 0) == '"') { +- _consume(self, 1); +- name = _parseUntil(self, '"'); ++ name = [self _parseQuotedString]; ++// _consume(self, 1); ++// name = _parseUntil(self, '"'); + _consumeIfMatch(self, ' '); + } ++ else if (_la(self, 0) == '{') { ++ name = [self _parseQuotedStringOrNIL]; ++ _consumeIfMatch(self, ' '); ++ } + else { + name = _parseUntil(self, ' '); + } +@@ -1090,6 +1258,8 @@ + return @""; + + s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; ++ if (s == nil) ++ s = [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding]; + if (s == nil) { + [self logWithFormat: + @"ERROR(%s): could not convert data (%d bytes) into string.", +@@ -1185,7 +1355,7 @@ + route = [self _parseQuotedStringOrNIL]; [self _consumeOptionalSpace]; + mailbox = [self _parseQuotedStringOrNIL]; [self _consumeOptionalSpace]; + host = [self _parseQuotedStringOrNIL]; [self _consumeOptionalSpace]; +- ++ + if (_la(self, 0) != ')') { + [self logWithFormat:@"WARNING: IMAP4 envelope " + @"address not properly closed (c0=%c,c1=%c): %@", +@@ -1197,6 +1367,7 @@ + address = [[NGImap4EnvelopeAddress alloc] initWithPersonalName:pname + sourceRoute:route mailbox:mailbox + host:host]; ++ + return address; + } + +@@ -1382,7 +1553,15 @@ + #if 0 + [self logWithFormat:@"PARSE KEY: %@", key]; + #endif +- if ([key hasPrefix:@"body["]) { ++ if ([key hasPrefix:@"body[header.fields"]) { ++ NSData *content; ++ ++ if ((content = [self _parseBodyHeaderFields]) != nil) ++ [fetch setObject:content forKey:key]; ++ else ++ [self logWithFormat:@"ERROR: got no body content for key: '%@'",key]; ++ } ++ else if ([key hasPrefix:@"body["]) { + NSDictionary *content; + + if ((content = [self _parseBodyContent]) != nil) +@@ -1594,8 +1773,11 @@ + if (_decode) + data = [data decodeQuotedPrintableValueOfMIMEHeaderField:nil]; + +- return [[[StrClass alloc] initWithData:data encoding:encoding] +- autorelease]; ++ if ([data isKindOfClass: [NSString class]]) ++ return (NSString *) data; ++ else ++ return [[[StrClass alloc] initWithData:data encoding:encoding] ++ autorelease]; + } + else { + str = _parseUntil2(self, ' ', ')'); +@@ -1620,13 +1802,35 @@ + return str; + } + +- + static NSString *_parseBodyString(NGImap4ResponseParser *self, + BOOL _convertString) + { + return _parseBodyDecodeString(self, _convertString, NO /* no decode */); + } + ++static NSArray *_parseLanguages(NGImap4ResponseParser *self) { ++ NSMutableArray *languages; ++ NSString *language; ++ ++ languages = [NSMutableArray array]; ++ if (_la(self, 0) == '(') { ++ while (_la(self, 0) != ')') { ++ _consume(self,1); ++ language = _parseBodyString(self, YES); ++ if ([language length]) ++ [languages addObject: language]; ++ } ++ _consume(self,1); ++ } ++ else { ++ language = _parseBodyString(self, YES); ++ if ([language length]) ++ [languages addObject: language]; ++ } ++ ++ return languages; ++} ++ + static NSDictionary *_parseBodyParameterList(NGImap4ResponseParser *self) + { + NSMutableDictionary *list; +@@ -1646,7 +1850,7 @@ + _consumeIfMatch(self, ' '); + value = _parseBodyDecodeString(self, YES, YES); + +- [list setObject:value forKey:[key lowercaseString]]; ++ if (value) [list setObject:value forKey:[key lowercaseString]]; + } + _consumeIfMatch(self, ')'); + } +@@ -1731,13 +1935,14 @@ + static NSDictionary *_parseSingleBody(NGImap4ResponseParser *self, + BOOL isBodyStructure) { + NSString *type, *subtype, *bodyId, *description, +- *encoding, *bodysize; ++ *result, *encoding, *bodysize; + NSDictionary *parameterList; + NSMutableDictionary *dict; ++ NSArray *languages; + + type = [_parseBodyString(self, YES) lowercaseString]; + _consumeIfMatch(self, ' '); +- subtype = _parseBodyString(self, YES); ++ subtype = [_parseBodyString(self, YES) lowercaseString]; + _consumeIfMatch(self, ' '); + parameterList = _parseBodyParameterList(self); + _consumeIfMatch(self, ' '); +@@ -1762,13 +1967,18 @@ + _consumeIfMatch(self, ' '); + [dict setObject:_parseBodyString(self, YES) forKey:@"lines"]; + } +- else if ([type isEqualToString:@"message"]) { ++ else if ([type isEqualToString:@"message"] ++ && [subtype isEqualToString:@"rfc822"]) { + if (_la(self, 0) != ')') { + _consumeIfMatch(self, ' '); + _consumeIfMatch(self, '('); +- [dict setObject:_parseBodyString(self, YES) forKey:@"date"]; ++ result = _parseBodyString(self, YES); ++ if (result == nil) result = @""; ++ [dict setObject:result forKey:@"date"]; + _consumeIfMatch(self, ' '); +- [dict setObject:_parseBodyString(self, YES) forKey:@"subject"]; ++ result = _parseBodyString(self, YES); ++ if (result == nil) result = @""; ++ [dict setObject:result forKey:@"subject"]; + _consumeIfMatch(self, ' '); + [dict setObject:_parseParenthesizedAddressList(self) forKey:@"from"]; + _consumeIfMatch(self, ' '); +@@ -1783,14 +1993,20 @@ + _consumeIfMatch(self, ' '); + [dict setObject:_parseParenthesizedAddressList(self) forKey:@"bcc"]; + _consumeIfMatch(self, ' '); +- [dict setObject:_parseBodyString(self, YES) forKey:@"in-reply-to"]; ++ result = _parseBodyString(self, YES); ++ if (result == nil) result = @""; ++ [dict setObject:result forKey:@"in-reply-to"]; + _consumeIfMatch(self, ' '); +- [dict setObject:_parseBodyString(self, YES) forKey:@"messageId"]; ++ result = _parseBodyString(self, YES); ++ if (result == nil) result = @""; ++ [dict setObject:result forKey:@"messageId"]; + _consumeIfMatch(self, ')'); + _consumeIfMatch(self, ' '); + [dict setObject:_parseBody(self, isBodyStructure) forKey:@"body"]; + _consumeIfMatch(self, ' '); +- [dict setObject:_parseBodyString(self, YES) forKey:@"bodyLines"]; ++ result = _parseBodyString(self, YES); ++ if (result == nil) result = @""; ++ [dict setObject:result forKey:@"bodyLines"]; + } + } + +@@ -1805,14 +2021,9 @@ + forKey: @"disposition"]; + if (_la(self, 0) != ')') { + _consume(self,1); +- if (_la(self, 0) == '(') { +- [dict setObject: _parseBodyParameterList(self) +- forKey: @"language"]; +- } +- else { +- [dict setObject: _parseBodyString(self, YES) +- forKey: @"language"]; +- } ++ languages = _parseLanguages(self); ++ if ([languages count]) ++ [dict setObject: languages forKey: @"languages"]; + if (_la(self, 0) != ')') { + _consume(self,1); + [dict setObject: _parseBodyString(self, YES) +@@ -1829,6 +2040,7 @@ + static NSDictionary *_parseMultipartBody(NGImap4ResponseParser *self, + BOOL isBodyStructure) { + NSMutableArray *parts; ++ NSArray *languages; + NSString *kind; + NSMutableDictionary *dict; + +@@ -1854,14 +2066,9 @@ + forKey: @"disposition"]; + if (_la(self, 0) != ')') { + _consume(self,1); +- if (_la(self, 0) == '(') { +- [dict setObject: _parseBodyParameterList(self) +- forKey: @"language"]; +- } +- else { +- [dict setObject: _parseBodyString(self, YES) +- forKey: @"language"]; +- } ++ languages = _parseLanguages(self); ++ if ([languages count]) ++ [dict setObject: languages forKey: @"languages"]; + if (_la(self, 0) != ')') { + _consume(self,1); + [dict setObject: _parseBodyString(self, YES) +@@ -2170,6 +2377,21 @@ + } + } + ++static BOOL _endsWithCQuote(NSString *_string){ ++ unsigned int quoteSlashes; ++ int pos; ++ ++ quoteSlashes = 0; ++ pos = [_string length] - 1; ++ while (pos > -1 ++ && [_string characterAtIndex: pos] == '\\') { ++ quoteSlashes++; ++ pos--; ++ } ++ ++ return ((quoteSlashes % 2) == 1); ++} ++ + - (NSException *)exceptionForFailedMatch:(unsigned char)_match + got:(unsigned char)_avail + { +@@ -2225,9 +2447,9 @@ + [s release]; + + if (c == '\n') { +- if ([self->serverResponseDebug cStringLength] > 2) { ++ if ([self->serverResponseDebug lengthOfBytesUsingEncoding:NSISOLatin1StringEncoding] > 2) { + fprintf(stderr, "S[%p]: %s", self, +- [self->serverResponseDebug cString]); ++ [self->serverResponseDebug cStringUsingEncoding:NSISOLatin1StringEncoding]); + } + [self->serverResponseDebug release]; + self->serverResponseDebug = +Index: sope-mime/NGImap4/ChangeLog +=================================================================== +--- sope-mime/NGImap4/ChangeLog (revision 1660) ++++ sope-mime/NGImap4/ChangeLog (working copy) +@@ -1,3 +1,61 @@ ++2009-10-06 Wolfgang Sourdeau <wsourdeau@inverse.ca> ++ ++ * NGImap4Client.m (-delete:): if the folder we want to delete is ++ the same as self->selectedFolder, we unselect it first to ensure a ++ "SELECT" happens if a new folder with the same name is created. ++ ++ * EOQualifier+IMAPAdditions.m ++ (-imap4OperatorForDateKeyword:andComparisonSelector:): modified ++ operator handler to handle "receive-date" search key as well as ++ "date", prefixing the real filter with "sent" or not. ++ ++2009-09-22 Wolfgang Sourdeau <wsourdeau@inverse.ca> ++ ++ * NGImap4Client.m (_sopeSORT:qualifier:encoding:): added support ++ for sorting by message size. ++ ++2009-07-01 Wolfgang Sourdeau <wsourdeau@inverse.ca> ++ ++ * NGImap4Connection.m (-initWithClient:password:): we need to copy ++ the imap4Separator, otherwise it will be released when the connection ++ is deallocated. ++ ++2009-06-15 Wolfgang Sourdeau <wsourdeau@inverse.ca> ++ ++ * NSString+Imap4.m (-stringByEncodingImap4FolderName, ++ -stringByDecodingImap4FolderName): reimplemented the original ++ methods in a unicode-safe way, thereby simplifying the code at the ++ same time. ++ ++ * NGImap4Functions.m (SaneFolderName): new function designed to ++ sanitize folder names prior to using them in IMAP commands. ++ ++2008-10-23 Wolfgang Sourdeau <wsourdeau@inverse.ca> ++ ++ * NGImap4Client.m ([NGImap -sort:qualifier:encoding:]): message ++ without date that are sorted on servers which do not have the SORT ++ capability are now given the current date as a work-around. ++ ++2008-09-22 Wolfgang Sourdeau <wsourdeau@inverse.ca> ++ ++ * NGImap4Connection.m ([NGImap -doesMailboxExistAtURL:]): restore ++ the previously selected folder state. ++ ++2008-09-19 Wolfgang Sourdeau <wsourdeau@inverse.ca> ++ ++ * NGImap4Client.m ([NGImap -select:]): simplified method by ++ removing the need for storing the previous folder before releasing ++ it. This strangely seems to fix a crash with gnustep 1.14. ++ ++2008-09-01 Ludovic Marcotte <lmarcotte@inverse.ca> ++ ++ * NGImap4ConnectionManager.m: implemented _garbageCollect. ++ ++2008-08-28 Wolfgang Sourdeau <wsourdeau@inverse.ca> ++ ++ * NGImap4Client.m ([NGImap -unselect]): new method to send ++ "UNSELECT" to the imap server. ++ + 2007-08-24 Wolfgang Sourdeau <WSourdeau@Inverse.CA> + + * NGImap4Connection.m: some fix for folders ending with a slash (OGo +Index: sope-mime/NGImap4/NGImap4ConnectionManager.m +=================================================================== +--- sope-mime/NGImap4/NGImap4ConnectionManager.m (revision 1660) ++++ sope-mime/NGImap4/NGImap4ConnectionManager.m (working copy) +@@ -38,6 +38,9 @@ + debugCache = [ud boolForKey:@"NGImap4EnableIMAP4CacheDebug"]; + poolingOff = [ud boolForKey:@"NGImap4DisableIMAP4Pooling"]; + ++ if ([ud objectForKey:@"NGImap4PoolingCleanupInterval"]) ++ PoolScanInterval = [[ud objectForKey:@"NGImap4PoolingCleanupInterval"] doubleValue]; ++ + if (debugOn) NSLog(@"Note: NGImap4EnableIMAP4Debug is enabled!"); + if (poolingOff) NSLog(@"WARNING: IMAP4 connection pooling is disabled!"); + } +@@ -53,18 +56,17 @@ + if ((self = [super init])) { + if (!poolingOff) { + self->urlToEntry = [[NSMutableDictionary alloc] initWithCapacity:256]; ++ self->gcTimer = [[NSTimer scheduledTimerWithTimeInterval: ++ PoolScanInterval ++ target:self selector:@selector(_garbageCollect:) ++ userInfo:nil repeats:YES] retain]; + } +- +- self->gcTimer = [[NSTimer scheduledTimerWithTimeInterval: +- PoolScanInterval +- target:self selector:@selector(_garbageCollect:) +- userInfo:nil repeats:YES] retain]; + } + return self; + } + + - (void)dealloc { +- if (self->gcTimer) [self->gcTimer invalidate]; ++ [self->gcTimer invalidate]; + [self->urlToEntry release]; + [self->gcTimer release]; + [super dealloc]; +@@ -91,6 +93,25 @@ + + - (void)_garbageCollect:(NSTimer *)_timer { + // TODO: scan for old IMAP4 channels ++ NGImap4Connection *entry; ++ NSDate *now; ++ NSArray *a; ++ int i; ++ ++ a = [self->urlToEntry allKeys]; ++ now = [NSDate date]; ++ ++ for (i = 0; i < [a count]; i++) ++ { ++ entry = [self->urlToEntry objectForKey: [a objectAtIndex: i]]; ++ ++ if ([now timeIntervalSinceDate: [entry creationTime]] > PoolScanInterval) ++ { ++ [[entry client] logout]; ++ [self->urlToEntry removeObjectForKey: [a objectAtIndex: i]]; ++ } ++ } ++ + [self debugWithFormat:@"should collect IMAP4 channels (%d active)", + [self->urlToEntry count]]; + } +@@ -105,34 +126,42 @@ + NGImap4Connection *entry; + NGImap4Client *client; + ++ if (poolingOff) { ++ client = [self imap4ClientForURL:_url password:_p]; ++ entry = [[NGImap4Connection alloc] initWithClient:client ++ password:_p]; ++ return [entry autorelease]; ++ } ++ else { + /* check cache */ + +- if ((entry = [self entryForURL:_url]) != nil) { +- if ([entry isValidPassword:_p]) { ++ if ((entry = [self entryForURL:_url]) != nil) { ++ if ([entry isValidPassword:_p]) { ++ if (debugCache) ++ [self logWithFormat:@"valid password, reusing cache entry ..."]; ++ return entry; ++ } ++ ++ /* different password, password could have changed! */ + if (debugCache) +- [self logWithFormat:@"valid password, reusing cache entry ..."]; +- return entry; ++ [self logWithFormat:@"different password than cached entry: %@", _url]; ++ entry = nil; + } +- +- /* different password, password could have changed! */ +- if (debugCache) +- [self logWithFormat:@"different password than cached entry: %@", _url]; +- entry = nil; +- } +- else +- [self debugWithFormat:@"no connection cached yet for url: %@", _url]; ++ else ++ [self debugWithFormat:@"no connection cached yet for url: %@", _url]; + +- /* try to login */ ++ /* try to login */ + +- client = [entry isValidPassword:_p] +- ? [entry client] +- : [self imap4ClientForURL:_url password:_p]; ++ client = [entry isValidPassword:_p] ++ ? [entry client] ++ : [self imap4ClientForURL:_url password:_p]; ++ ++ if (client == nil) ++ return nil; + +- if (client == nil) +- return nil; +- + /* sideeffect of -imap4ClientForURL:password: is to create a cache entry */ +- return [self entryForURL:_url]; ++ return [self entryForURL:_url]; ++ } + } + + /* client object */ +Index: sope-mime/NGImap4/NSString+Imap4.m +=================================================================== +--- sope-mime/NGImap4/NSString+Imap4.m (revision 1660) ++++ sope-mime/NGImap4/NSString+Imap4.m (working copy) +@@ -20,117 +20,86 @@ + 02111-1307, USA. + */ + ++#import <Foundation/NSData.h> ++ + #include <NGImap4/NSString+Imap4.h> + #include "imCommon.h" + +-/* TODO: NOT UNICODE SAFE (uses cString) */ +- +-static void _encodeToModifiedUTF7(unsigned char *_buf, int encLen, +- unsigned char **result_, +- unsigned int *cntRes_); +-static int _decodeOfModifiedUTF7(unsigned char *_target, unsigned _targetLen, +- unsigned *usedBytes_ , +- unsigned char **buffer_, +- int *bufLen_, int maxBuf); +- + @implementation NSString(Imap4) + ++static unsigned int _encodeToModifiedUTF7(unichar *_char, unsigned char *result_, ++ unsigned int *cntRes_); ++static unsigned int _decodeOfModifiedUTF7(unsigned char *_source, unichar *result_, ++ unsigned int *cntRes_ ); ++ + - (NSString *)stringByEncodingImap4FolderName { +- // TBD: this is restricted to Latin1, should be fixed to UTF-8 +- /* dude.d& --> dude.d&- */ +- unsigned char *buf = NULL; ++ unichar *buf = NULL; + unsigned char *res = NULL; + unsigned int len = 0; + unsigned int cnt = 0; + unsigned int cntRes = 0; + NSString *result = nil; +- NSData *data; + +- len = [self cStringLength]; +- buf = calloc(len + 3, sizeof(char)); +- res = calloc((len * 6) + 3, sizeof(char)); +- buf[len] = '\0'; +- res[len * 6] = '\0'; +- [self getCString:(char *)buf]; ++ len = [self length]; ++ buf = NSZoneMalloc(NULL, (len + 1) * sizeof(unichar)); ++ [self getCharacters: buf]; ++ buf[len] = 0; + ++ /* 1 * '&', 3 for the max bytes / char, 1 * '-' */ ++ res = NSZoneMalloc(NULL, ((len * 5) + 1) * sizeof(char)); ++ + while (cnt < len) { +- int c = buf[cnt]; ++ unichar c = buf[cnt]; + if (((c > 31) && (c < 38)) || + ((c > 38) && (c < 127))) { + res[cntRes++] = c; +- cnt++; + } + else { + if (c == '&') { + res[cntRes++] = '&'; + res[cntRes++] = '-'; +- cnt++; + } + else { +- int start; +- +- start = cnt; +- +- while (cnt < (len - 1)) { +- int c = buf[cnt + 1]; +- if (((c > 31) && (c < 38)) || +- ((c > 38) && (c < 127)) || +- (c == '&')) { +- break; +- } +- else { +- cnt++; +- } +- } +- { +- unsigned length; +- +- res[cntRes++] = '&'; +- +- length = cnt - start + 1; +- +- _encodeToModifiedUTF7(buf + start, length, &res, &cntRes); +- +- res[cntRes] = '-'; +- cntRes++; +- cnt++; +- } ++ res[cntRes++] = '&'; ++ cnt += _encodeToModifiedUTF7(buf + cnt, res + cntRes, &cntRes); ++ res[cntRes++] = '-'; + } + } ++ cnt++; + } +- if (buf != NULL) free(buf); buf = NULL; ++ if (buf != NULL) NSZoneFree(NULL, buf); + +- data = [[NSData alloc] initWithBytesNoCopy:res length:cntRes +- freeWhenDone:YES]; +- result = [[NSString alloc] initWithData:data +- encoding:NSISOLatin1StringEncoding]; +- [data release]; data = nil; +- +- return [result autorelease]; ++ res[cntRes] = 0; ++ result = [NSString stringWithCString: (char *) res ++ encoding: NSISOLatin1StringEncoding]; ++ ++ return result; + } + + - (NSString *)stringByDecodingImap4FolderName { +- // TBD: this is restricted to Latin1, should be fixed to UTF-8 +- /* dude/d&- --> dude/d& */ + unsigned char *buf; +- unsigned char *res; ++ unichar *res; + unsigned int len; + unsigned int cnt = 0; + unsigned int cntRes = 0; + NSString *result = nil; +- NSData *data; ++// NSData *data; + +- if ((len = [self cStringLength]) == 0) ++ if ((len = [self lengthOfBytesUsingEncoding: NSISOLatin1StringEncoding]) == 0) + return @""; +- +- buf = calloc(len + 3, sizeof(unsigned char)); +- res = calloc(len + 3, sizeof(unsigned char)); ++ ++ buf = NSZoneMalloc(NULL, (len + 1) * sizeof(unsigned char)); ++ ++ if ([self getCString:(char *)buf maxLength: len + 1 ++ encoding: NSISOLatin1StringEncoding] == NO) { ++ NSZoneFree(NULL, buf); ++ return @""; ++ } + buf[len] = '\0'; +- res[len] = '\0'; +- +- [self getCString:(char *)buf]; +- +- while (cnt < (len - 1)) { /* &- */ ++ ++ res = NSZoneMalloc(NULL, (len + 1) * sizeof(unichar)); ++ ++ while (cnt < len) { /* &- */ + unsigned char c; + + c = buf[cnt]; +@@ -141,29 +110,7 @@ + cnt += 2; + } + else { +- unsigned usedBytes = 0; +- unsigned char *buffer; +- int maxBuf, bufLen; +- +- cnt++; +- maxBuf = 511; +- bufLen = 0; +- buffer = calloc(maxBuf + 3, sizeof(char)); +- +- if (_decodeOfModifiedUTF7(buf + cnt, len - cnt, &usedBytes , &buffer, +- &bufLen, maxBuf) == 0) { +- int cnt1; +- +- cnt1 = 0; +- while (cnt1 < bufLen) { +- res[cntRes++] = buffer[cnt1++]; +- } +- cnt += usedBytes; +- } +- else { +- NSCAssert(NO, @"couldn't decode UTF-7 .."); +- } +- free(buffer); buffer = NULL; ++ cnt += _decodeOfModifiedUTF7(buf + cnt + 1, res + cntRes, &cntRes) + 1; + } + } + else { +@@ -171,20 +118,129 @@ + cnt++; + } + } +- if (cnt < len) +- res[cntRes++] = buf[cnt++]; +- +- if (buf != NULL) free(buf); buf = NULL; + +- data = [[NSData alloc] initWithBytesNoCopy:res length:cntRes +- freeWhenDone:YES]; +- result = [[NSString alloc] initWithData:data +- encoding:NSISOLatin1StringEncoding]; +- [data release]; data = nil; +- +- return [result autorelease]; ++ if (buf != NULL) NSZoneFree(NULL, buf); ++ ++ res[cntRes] = 0; ++ result = [NSString stringWithCharacters: res length: cntRes]; ++ ++ return result; + } + ++/* check metamail output for correctness */ ++ ++static unsigned char basis_64[] = ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; ++ ++static char index_64[128] = { ++ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, ++ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, ++ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, ++ 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, ++ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, ++ 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, ++ -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, ++ 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 ++}; ++ ++#define char64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)]) ++ ++static unsigned int _encodeToModifiedUTF7(unichar *_char, unsigned char *result_, ++ unsigned int *cntRes_) ++{ ++ unsigned int processedSrc, processedDest, cycle; ++ unichar c; ++ char leftover; ++ ++ processedSrc = 0; ++ processedDest = 0; ++ cycle = 0; ++ leftover = 0; ++ ++ c = *_char; ++ while (c > 126 || (c > 0 && c < 32)) { ++ if (cycle == 0) { ++ *(result_ + processedDest) = basis_64[(c >> 10) & 0x3f]; ++ *(result_ + processedDest + 1) = basis_64[(c >> 4) & 0x3f]; ++ leftover = (c << 2); ++ processedDest += 2; ++ cycle = 1; ++ } ++ else if (cycle == 1) { ++ *(result_ + processedDest) = basis_64[(leftover | (c >> 14)) & 0x3f]; ++ *(result_ + processedDest + 1) = basis_64[(c >> 8) & 0x3f]; ++ *(result_ + processedDest + 2) = basis_64[(c >> 2) & 0x3f]; ++ leftover = (c << 4); ++ processedDest += 3; ++ cycle = 2; ++ } ++ else if (cycle == 2) { ++ *(result_ + processedDest) = basis_64[(leftover | (c >> 12)) & 0x3f]; ++ *(result_ + processedDest + 1) = basis_64[(c >> 6) & 0x3f]; ++ *(result_ + processedDest + 2) = basis_64[c & 0x3f]; ++ leftover = 0; ++ processedDest += 3; ++ cycle = 0; ++ } ++ processedSrc++; ++ c = *(_char + processedSrc); ++ } ++ if (leftover) { ++ *(result_ + processedDest) = basis_64[leftover & 0x3f]; ++ processedDest++; ++ } ++ processedSrc--; ++ *cntRes_ += processedDest; ++ ++ return processedSrc; ++} ++ ++static unsigned int _decodeOfModifiedUTF7(unsigned char *_source, unichar *result_, ++ unsigned int *cntRes_) ++{ ++ unsigned int processedSrc, processedDest; ++ unsigned char c, decoded; ++ unichar currentRes; ++ int shift; ++ ++ processedSrc = 0; ++ processedDest = 0; ++ shift = 10; ++ currentRes = 0; ++ ++ c = *_source; ++ while (c != 0 && c != '-') { ++ decoded = index_64[c]; ++ if (shift < 0) { ++ currentRes |= (decoded >> (shift * -1)); ++ *(result_ + processedDest) = currentRes; ++ processedDest++; ++ shift += 16; ++ currentRes = (decoded << shift); ++ } else { ++ currentRes |= (decoded << shift); ++ if (shift == 0) { ++ *(result_ + processedDest) = currentRes; ++ processedDest++; ++ currentRes = 0; ++ shift = 16; ++ } ++ } ++ shift -= 6; ++ processedSrc++; ++ c = *(_source + processedSrc); ++ } ++ if (shift != 10) { ++ *(result_ + processedDest) = currentRes; ++ } ++ if (c == '-') ++ processedSrc++; ++ ++ *cntRes_ += processedDest; ++ ++ return processedSrc; ++} ++ + - (NSString *)stringByEscapingImap4Password { + // TODO: perf + unichar *buffer; +@@ -193,12 +249,12 @@ + NSString *s; + + len = [self length]; +- chars = calloc(len + 2, sizeof(unichar)); ++ chars = NSZoneCalloc(NULL, len + 2, sizeof(unichar)); + [self getCharacters:chars]; +- +- buffer = calloc(len * 2 + 2, sizeof(unichar)); ++ ++ buffer = NSZoneCalloc(NULL, len * 2 + 2, sizeof(unichar)); + buffer[len * 2] = '\0'; +- ++ + for (i = 0, j = 0; i < len; i++, j++) { + BOOL conv = NO; + +@@ -224,209 +280,11 @@ + } + buffer[j] = chars[i]; + } +- if (chars != NULL) free(chars); chars = NULL; ++ if (chars != NULL) NSZoneFree(NULL, chars); + + s = [NSString stringWithCharacters:buffer length:j]; +- if (buffer != NULL) free(buffer); buffer = NULL; ++ + return s; + } + + @end /* NSString(Imap4) */ +- +-static void writeChunk(int _c1, int _c2, int _c3, int _pads, +- unsigned char **result_, +- unsigned int *cntRes_); +- +-static int getChar(int _cnt, int *cnt_, unsigned char *_buf) { +- int result; +- +- if ((_cnt % 2)) { +- result = _buf[*cnt_]; +- (*cnt_)++; +- } +- else { +- result = 0; +- } +- return result; +-} +-static void _encodeToModifiedUTF7(unsigned char *_buf, int encLen, +- unsigned char **result_, unsigned int *cntRes_) +-{ +- int c1, c2, c3; +- int cnt, cntAll; +- +- cnt = 0; +- cntAll = 0; +- +- while (cnt < encLen) { +- c1 = getChar(cntAll++, &cnt, _buf); +- if (cnt == encLen) { +- writeChunk(c1, 0, 0, 2, result_, cntRes_); +- } +- else { +- c2 = getChar(cntAll++, &cnt, _buf); +- if (cnt == encLen) { +- writeChunk(c1, c2, 0, 1, result_, cntRes_); +- } +- else { +- c3 = getChar(cntAll++, &cnt, _buf); +- writeChunk(c1, c2, c3, 0, result_, cntRes_); +- } +- } +- } +-} +- +-/* check metamail output for correctness */ +- +-static unsigned char basis_64[] = +- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +- +-static void writeChunk(int c1, int c2, int c3, int pads, unsigned char **result_, +- unsigned int *cntRes_) { +- unsigned char c; +- +- c = basis_64[c1>>2]; +- (*result_)[*cntRes_] = c; +- (*cntRes_)++; +- +- c = basis_64[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)]; +- +- (*result_)[*cntRes_] = c; +- (*cntRes_)++; +- +- +- if (pads == 2) { +- ; +- } +- else if (pads) { +- c = basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)]; +- (*result_)[*cntRes_] = c; +- (*cntRes_)++; +- } +- else { +- c = basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)]; +- +- (*result_)[*cntRes_] = c; +- (*cntRes_)++; +- +- c = basis_64[c3 & 0x3F]; +- (*result_)[*cntRes_] = c; +- (*cntRes_)++; +- } +-} +- +-static char index_64[128] = { +- -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, +- -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, +- -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, +- 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, +- -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, +- 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, +- -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, +- 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 +-}; +- +-#define char64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)]) +- +-static int _decodeOfModifiedUTF7(unsigned char *_target, unsigned _targetLen, +- unsigned *usedBytes_ , unsigned char **buffer_, +- int *bufLen_, int maxBuf) +-{ +- int c1, c2, c3, c4; +- unsigned int cnt; +- +- for (cnt = 0; cnt < _targetLen; ) { +- c1 = '='; +- c2 = '='; +- c3 = '='; +- c4 = '='; +- +- c1 = _target[cnt++]; +- +- if (c1 == '-') { +- (*usedBytes_)++; +- return 0; +- } +- if (cnt < _targetLen) +- c2 = _target[cnt++]; +- +- if (c2 == '-') { +- (*usedBytes_)+=2; +- return 0; +- } +- +- (*usedBytes_) += 2; +- +- if (cnt < _targetLen) { +- c3 = _target[cnt++]; +- (*usedBytes_)++; +- } +- +- if (cnt < _targetLen) { +- c4 = _target[cnt++]; +- if (c3 != '-') +- (*usedBytes_)++; +- } +- +- if (c2 == -1 || c3 == -1 || c4 == -1) { +- fprintf(stderr, "Warning: base64 decoder saw premature EOF!\n"); +- return 0; +- } +- +- if (c1 == '=' || c2 == '=') { +- continue; +- } +- +- c1 = char64(c1); +- c2 = char64(c2); +- +- if (*bufLen_ < maxBuf) { +- unsigned char c; +- +- c = ((c1<<2) | ((c2&0x30)>>4)); +- +- if (c) { +- (*buffer_)[*bufLen_] = c; +- *bufLen_ = *bufLen_ + 1; +- } +- } +- if (c3 == '-') { +- return 0; +- } +- else if (c3 == '=') { +- continue; +- } else { +- +- c3 = char64(c3); +- +- if (*bufLen_ < maxBuf) { +- unsigned char c; +- c = (((c2&0XF) << 4) | ((c3&0x3C) >> 2)); +- if (c) { +- (*buffer_)[*bufLen_] = c; +- *bufLen_ = *bufLen_ + 1; +- } +- } +- +- if (c4 == '-') { +- return 0; +- } +- else if (c4 == '=') { +- continue; +- } else { +- c4 = char64(c4); +- +- if (*bufLen_ < maxBuf) { +- unsigned char c; +- +- c = (((c3&0x03) <<6) | c4); +- if (c) { +- (*buffer_)[*bufLen_] = c; +- (*bufLen_) = (*bufLen_) + 1; +- } +- } +- } +- } +- } +- return 0; +-} +Index: sope-mime/NGImap4/NGImap4Functions.h +=================================================================== +--- sope-mime/NGImap4/NGImap4Functions.h (revision 1660) ++++ sope-mime/NGImap4/NGImap4Functions.h (working copy) +@@ -58,4 +58,6 @@ + id<NGImap4Folder>_folder); + BOOL _createSubFolderWithName(id<NGImap4Folder> self, NSString *_name, BOOL _app); + ++NSString *SaneFolderName(NSString *folderName); ++ + #endif /* __NGMime_NGImap4_NGImap4Functions_H__ */ +Index: sope-mime/NGMail/NGMailAddressParser.h +=================================================================== +--- sope-mime/NGMail/NGMailAddressParser.h (revision 1660) ++++ sope-mime/NGMail/NGMailAddressParser.h (working copy) +@@ -24,7 +24,9 @@ + + #import <Foundation/NSObject.h> + +-@class NSData, NSString, NSArray; ++#import <Foundation/NSString.h> ++ ++@class NSData, NSArray; + @class NGMailAddressList; + + /* +@@ -34,16 +36,16 @@ + @interface NGMailAddressParser : NSObject + { + @private +- unsigned char *data; +- int dataPos; +- int errorPos; +- int maxLength; ++ unichar *data; ++ int dataPos; ++ int errorPos; ++ int maxLength; + } + + + (id)mailAddressParserWithString:(NSString *)_string; + + (id)mailAddressParserWithData:(NSData *)_data; +-+ (id)mailAddressParserWithCString:(char *)_cString; +-- (id)initWithCString:(const unsigned char *)_cstr length:(int unsigned)_len; +++ (id)mailAddressParserWithCString:(const char *)_cString; ++- (id)initWithString:(NSString *)_str; + + /* parsing */ + +Index: sope-mime/NGMail/NGMimeMessageGenerator.m +=================================================================== +--- sope-mime/NGMail/NGMimeMessageGenerator.m (revision 1660) ++++ sope-mime/NGMail/NGMimeMessageGenerator.m (working copy) +@@ -86,37 +86,40 @@ + char *des = NULL; + unsigned int cnt; + BOOL doEnc; +- NSString *str; ++// NSString *str; + + // TODO: this s***s big time! ++// NSLog (@"class: '%@'", NSStringFromClass ([_data class])); ++// #if APPLE_Foundation_LIBRARY || NeXT_Foundation_LIBRARY ++// str = [[NSString alloc] initWithData:_data ++// encoding:NSISOLatin1StringEncoding]; ++// str = [str autorelease]; ++ ++// #else ++// str = [[NSString alloc] initWithData:_data ++// encoding:NSISOLatin9StringEncoding]; ++// #endif ++// bytes = [str cString]; ++// length = [str cStringLength]; + +-#if APPLE_Foundation_LIBRARY || NeXT_Foundation_LIBRARY +- str = [[NSString alloc] initWithData:_data +- encoding:NSISOLatin1StringEncoding]; +-#else +- str = [[NSString alloc] initWithData:_data +- encoding:NSISOLatin9StringEncoding]; +-#endif +- str = [str autorelease]; +- +- bytes = [str cString]; +- length = [str cStringLength]; +- ++ bytes = [_data bytes]; ++ length = [_data length]; ++ + /* check whether we need to encode */ +- +- for (cnt = 0, doEnc = NO; cnt < length; cnt++) { +- if ((unsigned char)bytes[cnt] > 127) { ++ cnt = 0; ++ doEnc = NO; ++ while (!doEnc && cnt < length) ++ if ((unsigned char)bytes[cnt] > 127) + doEnc = YES; +- break; +- } +- } +- ++ else ++ cnt++; ++ + if (!doEnc) + return _data; + + /* encode quoted printable */ + { +- char iso[] = "=?iso-8859-15?q?"; ++ char iso[] = "=?utf-8?q?"; + unsigned isoLen = 16; + char isoEnd[] = "?="; + unsigned isoEndLen = 2; +Index: sope-mime/NGMail/NGMailAddressParser.m +=================================================================== +--- sope-mime/NGMail/NGMailAddressParser.m (revision 1660) ++++ sope-mime/NGMail/NGMailAddressParser.m (working copy) +@@ -52,9 +52,9 @@ + StrClass = [NSString class]; + } + +-static inline NSString *mkStrObj(const unsigned char *s, unsigned int l) { ++static inline NSString *mkStrObj(const unichar *s, unsigned int l) { + // TODO: unicode +- return [(NSString *)[StrClass alloc] initWithCString:(char *)s length:l]; ++ return [(NSString *)[StrClass alloc] initWithCharacters:s length:l]; + } + + static inline id parseWhiteSpaces(NGMailAddressParser *self, BOOL _guessMode) { +@@ -84,7 +84,7 @@ + int keepPos = self->dataPos; // keep reference for backtracking + id returnValue = nil; + BOOL isAtom = YES; +- unsigned char text[self->maxLength + 2]; // token text ++ unichar text[self->maxLength + 2]; // token text + int length = 0; // token text length + BOOL done = NO; + +@@ -94,7 +94,7 @@ + done = YES; + } + else { +- register unsigned char c = self->data[self->dataPos]; ++ register unichar c = self->data[self->dataPos]; + + switch (c) { + case '(' : case ')': case '<': case '>': +@@ -162,7 +162,7 @@ + int keepPos = self->dataPos; // keep reference for backtracking + id returnValue = nil; + BOOL isQText = YES; +- unsigned char text[self->maxLength + 4]; // token text ++ unichar text[self->maxLength + 4]; // token text + int length = 0; // token text length + BOOL done = YES; + +@@ -172,9 +172,9 @@ + done = YES; + } + else { +- register char c = self->data[self->dataPos]; ++ register unichar c = self->data[self->dataPos]; + +- switch ((int)c) { ++ switch (c) { + case '"' : + case '\\': + case 13 : +@@ -215,7 +215,7 @@ + int keepPos = self->dataPos; // keep reference for backtracking + id returnValue = nil; + BOOL isDText = YES; +- unsigned char text[self->maxLength]; // token text ++ unichar text[self->maxLength]; // token text + int length = 0; // token text length + BOOL done = YES; + +@@ -225,9 +225,9 @@ + done = YES; + } + else { +- register char c = self->data[self->dataPos]; ++ register unichar c = self->data[self->dataPos]; + +- switch ((int)c) { ++ switch (c) { + case '[': case ']': + case '\\': case 13: + isDText = (length > 0); +@@ -320,42 +320,47 @@ + /* constructors */ + + + (id)mailAddressParserWithData:(NSData *)_data { +- return [[(NGMailAddressParser *)[self alloc] +- initWithCString:[_data bytes] +- length:[_data length]] autorelease]; ++ NSString *uniString; ++ ++ uniString = [NSString stringWithCharacters:(unichar *)[_data bytes] ++ length:([_data length] / sizeof(unichar))]; ++ ++ return [(NGMailAddressParser *)self mailAddressParserWithString:uniString]; + } ++ + + (id)mailAddressParserWithCString:(char *)_cString { +- return [[(NGMailAddressParser *)[self alloc] +- initWithCString:(unsigned char *)_cString +- length:strlen(_cString)] autorelease]; ++ NSString *nsCString; ++ ++ nsCString = [NSString stringWithCString:_cString]; ++ ++ return [(NGMailAddressParser *)self mailAddressParserWithString:nsCString]; + } +-- (id)initWithCString:(const unsigned char *)_cstr length:(int unsigned)_len { ++ +++ (id)mailAddressParserWithString:(NSString *)_string { ++ return [[(NGMailAddressParser *)[self alloc] initWithString:_string] ++ autorelease]; ++} ++ ++- (id)initWithString:(NSString *)_str { + if ((self = [super init])) { + // TODO: remember some string encoding? +- self->data = (unsigned char *)_cstr; +- self->maxLength = _len; ++ self->maxLength = [_str length]; ++ self->data = malloc(self->maxLength*sizeof(unichar)); ++ [_str getCharacters:self->data]; + self->dataPos = 0; + self->errorPos = -1; + } + return self; + } + +-- (id)initWithString:(NSString *)_str { +- // TODO: unicode +- return [self initWithCString:(unsigned char *)[_str cString] +- length:[_str cStringLength]]; +-} +- + - (id)init { +- return [self initWithCString:NULL length:0]; ++ return [self initWithString:nil]; + } + +-+ (id)mailAddressParserWithString:(NSString *)_string { +- return [[(NGMailAddressParser *)[self alloc] initWithString:_string] +- autorelease]; +-} +- + - (void)dealloc { ++ if (self->data != NULL) { ++ free(self->data); ++ } + self->data = NULL; + self->maxLength = 0; + self->dataPos = 0; +Index: sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m +=================================================================== +--- sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m (revision 1660) ++++ sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m (working copy) +@@ -19,88 +19,45 @@ + 02111-1307, USA. + */ + ++#ifdef HAVE_STRNDUP ++#define _GNU_SOURCE 1 ++#endif ++ ++#include <string.h> ++ + #include "NGMimeHeaderFieldParser.h" + #include "NGMimeHeaderFields.h" + #include "NGMimeUtilities.h" + #include "common.h" +-#include <string.h> + ++#ifndef HAVE_STRNDUP ++char *strndup(const char *str, size_t len) ++{ ++ char *dup = (char *)malloc(len+1); ++ if (dup) { ++ strncpy(dup,str,len); ++ dup[len]= '\0'; ++ } ++ return dup; ++} ++#endif ++ + @implementation NGMimeRFC822DateHeaderFieldParser + +-static Class CalDateClass = Nil; +-static NSTimeZone *gmt = nil; +-static NSTimeZone *gmt01 = nil; +-static NSTimeZone *gmt02 = nil; +-static NSTimeZone *gmt03 = nil; +-static NSTimeZone *gmt04 = nil; +-static NSTimeZone *gmt05 = nil; +-static NSTimeZone *gmt06 = nil; +-static NSTimeZone *gmt07 = nil; +-static NSTimeZone *gmt08 = nil; +-static NSTimeZone *gmt09 = nil; +-static NSTimeZone *gmt10 = nil; +-static NSTimeZone *gmt11 = nil; +-static NSTimeZone *gmt12 = nil; +-static NSTimeZone *gmt0530 = nil; +-static NSTimeZone *gmtM01 = nil; +-static NSTimeZone *gmtM02 = nil; +-static NSTimeZone *gmtM03 = nil; +-static NSTimeZone *gmtM04 = nil; +-static NSTimeZone *gmtM05 = nil; +-static NSTimeZone *gmtM06 = nil; +-static NSTimeZone *gmtM07 = nil; +-static NSTimeZone *gmtM08 = nil; +-static NSTimeZone *gmtM09 = nil; +-static NSTimeZone *gmtM10 = nil; +-static NSTimeZone *gmtM11 = nil; +-static NSTimeZone *gmtM12 = nil; +-static NSTimeZone *gmtM13 = nil; +-static NSTimeZone *gmtM14 = nil; +-static NSTimeZone *met = nil; ++static NSTimeZone *gmt = nil; ++static NSTimeZone *met = nil; + + + (int)version { + return 2; + } ++ + + (void)initialize { + static BOOL didInit = NO; +- Class TzClass; + if (didInit) return; + didInit = YES; + +- CalDateClass = [NSCalendarDate class]; +- +- /* timezones which were actually used in a maillist mailbox */ +- TzClass = [NSTimeZone class]; +- gmt = [[TzClass timeZoneWithName:@"GMT"] retain]; +- met = [[TzClass timeZoneWithName:@"MET"] retain]; +- gmt01 = [[TzClass timeZoneForSecondsFromGMT: 1 * (60 * 60)] retain]; +- gmt02 = [[TzClass timeZoneForSecondsFromGMT: 2 * (60 * 60)] retain]; +- gmt03 = [[TzClass timeZoneForSecondsFromGMT: 3 * (60 * 60)] retain]; +- gmt04 = [[TzClass timeZoneForSecondsFromGMT: 4 * (60 * 60)] retain]; +- gmt05 = [[TzClass timeZoneForSecondsFromGMT: 5 * (60 * 60)] retain]; +- gmt06 = [[TzClass timeZoneForSecondsFromGMT: 6 * (60 * 60)] retain]; +- gmt07 = [[TzClass timeZoneForSecondsFromGMT: 7 * (60 * 60)] retain]; +- gmt08 = [[TzClass timeZoneForSecondsFromGMT: 8 * (60 * 60)] retain]; +- gmt09 = [[TzClass timeZoneForSecondsFromGMT: 9 * (60 * 60)] retain]; +- gmt10 = [[TzClass timeZoneForSecondsFromGMT: 10 * (60 * 60)] retain]; +- gmt11 = [[TzClass timeZoneForSecondsFromGMT: 11 * (60 * 60)] retain]; +- gmt12 = [[TzClass timeZoneForSecondsFromGMT: 12 * (60 * 60)] retain]; +- gmtM01 = [[TzClass timeZoneForSecondsFromGMT: -1 * (60 * 60)] retain]; +- gmtM02 = [[TzClass timeZoneForSecondsFromGMT: -2 * (60 * 60)] retain]; +- gmtM03 = [[TzClass timeZoneForSecondsFromGMT: -3 * (60 * 60)] retain]; +- gmtM04 = [[TzClass timeZoneForSecondsFromGMT: -4 * (60 * 60)] retain]; +- gmtM05 = [[TzClass timeZoneForSecondsFromGMT: -5 * (60 * 60)] retain]; +- gmtM06 = [[TzClass timeZoneForSecondsFromGMT: -6 * (60 * 60)] retain]; +- gmtM07 = [[TzClass timeZoneForSecondsFromGMT: -7 * (60 * 60)] retain]; +- gmtM08 = [[TzClass timeZoneForSecondsFromGMT: -8 * (60 * 60)] retain]; +- gmtM09 = [[TzClass timeZoneForSecondsFromGMT: -9 * (60 * 60)] retain]; +- gmtM10 = [[TzClass timeZoneForSecondsFromGMT:-10 * (60 * 60)] retain]; +- gmtM11 = [[TzClass timeZoneForSecondsFromGMT:-11 * (60 * 60)] retain]; +- gmtM12 = [[TzClass timeZoneForSecondsFromGMT:-12 * (60 * 60)] retain]; +- gmtM13 = [[TzClass timeZoneForSecondsFromGMT:-13 * (60 * 60)] retain]; +- gmtM14 = [[TzClass timeZoneForSecondsFromGMT:-14 * (60 * 60)] retain]; +- +- gmt0530 = [[TzClass timeZoneForSecondsFromGMT:5 * (60*60) + (30*60)] retain]; ++ gmt = [[NSTimeZone timeZoneWithName:@"GMT"] retain]; ++ met = [[NSTimeZone timeZoneWithName:@"MET"] retain]; + } + + /* +@@ -111,7 +68,7 @@ + TODO: use an own parser for that. + */ + +-static int parseMonthOfYear(unsigned char *s, unsigned int len) { ++static int parseMonthOfYear(char *s, unsigned int len) { + /* + This one is *extremely* forgiving, it only checks what is + necessary for the set below. This should work for both, English +@@ -147,162 +104,110 @@ + } + } + +-static NSTimeZone *parseTimeZone(unsigned char *s, unsigned int len) { ++static int offsetFromTZAbbreviation(const char **p) { ++ NSString *abbreviation; ++ NSTimeZone *offsetTZ; ++ unsigned int length; ++ ++ length = 0; ++ while (isalpha(*(*p+length))) ++ length++; ++ abbreviation = [[NSString alloc] initWithBytes: *p ++ length: length - 1 ++ encoding: NSISOLatin1StringEncoding]; ++ offsetTZ = [NSTimeZone timeZoneWithAbbreviation: abbreviation]; ++ [abbreviation release]; ++ *p += length; ++ ++ return [offsetTZ secondsFromGMT]; ++} ++ ++static inline char *digitsString(const char *string) { ++ const char *p; ++ unsigned int len; ++ ++ p = string; ++ while (!isdigit(*p)) ++ p++; ++ len = 0; ++ while (isdigit(*(p + len))) ++ len++; ++ ++ return strndup(p, len); ++} ++ ++static NSTimeZone *parseTimeZone(const char *s, unsigned int len) { + /* + WARNING: failed to parse RFC822 timezone: '+0530' \ + (value='Tue, 13 Jul 2004 21:39:28 +0530') + TODO: this is because libFoundation doesn't accept 'GMT+0530' as input. + */ +- char *p = (char *)s; ++ char *newString, *digits; ++ const char *p; + NSTimeZone *tz; +- NSString *ts; +- +- if (len == 0) +- return nil; +- +- if (*s == '+' || *s == '-') { +- if (len == 3) { +- if (p[1] == '0' && p[2] == '0') // '+00' or '-00' +- return gmt; +- if (*s == '+') { +- if (p[1] == '0' && p[2] == '1') // '+01' +- return gmt01; +- if (p[1] == '0' && p[2] == '2') // '+02' +- return gmt02; +- } +- } +- else if (len == 5) { +- if (p[3] == '0' && p[4] == '0' && p[1] == '0') { // '?0x00' +- if (p[2] == '0') // '+0000' +- return gmt; +- +- if (*s == '+') { +- if (p[2] == '1') return gmt01; // '+0100' +- if (p[2] == '2') return gmt02; // '+0200' +- if (p[2] == '3') return gmt03; // '+0300' +- if (p[2] == '4') return gmt04; // '+0400' +- if (p[2] == '5') return gmt05; // '+0500' +- if (p[2] == '6') return gmt06; // '+0600' +- if (p[2] == '7') return gmt07; // '+0700' +- if (p[2] == '8') return gmt08; // '+0800' +- if (p[2] == '9') return gmt09; // '+0900' +- } +- else if (*s == '-') { +- if (p[2] == '1') return gmtM01; // '-0100' +- if (p[2] == '2') return gmtM02; // '-0200' +- if (p[2] == '3') return gmtM03; // '-0300' +- if (p[2] == '4') return gmtM04; // '-0400' +- if (p[2] == '5') return gmtM05; // '-0500' +- if (p[2] == '6') return gmtM06; // '-0600' +- if (p[2] == '7') return gmtM07; // '-0700' +- if (p[2] == '8') return gmtM08; // '-0800' +- if (p[2] == '9') return gmtM09; // '-0900' +- } +- } +- else if (p[3] == '0' && p[4] == '0' && p[1] == '1') { // "?1x00" +- if (*s == '+') { +- if (p[2] == '0') return gmt10; // '+1000' +- if (p[2] == '1') return gmt11; // '+1100' +- if (p[2] == '2') return gmt12; // '+1200' +- } +- else if (*s == '-') { +- if (p[2] == '0') return gmtM10; // '-1000' +- if (p[2] == '1') return gmtM11; // '-1100' +- if (p[2] == '2') return gmtM12; // '-1200' +- if (p[2] == '3') return gmtM13; // '-1300' +- if (p[2] == '4') return gmtM14; // '-1400' +- } +- } +- +- /* special case for GMT+0530 */ +- if (strncmp((char *)s, "+0530", 5) == 0) +- return gmt0530; +- } +- else if (len == 7) { +- /* +- "MultiMail" submits timezones like this: +- "Tue, 9 Mar 2004 9:43:00 -05-500", +- don't know what the "-500" trailer is supposed to mean? Apparently +- Thunderbird just uses the "-05", so do we. +- */ +- +- if (isdigit(p[1]) && isdigit(p[2]) && (p[3] == '-'||p[3] == '+')) { +- unsigned char tmp[8]; +- +- strncpy((char *)tmp, p, 3); +- tmp[3] = '0'; +- tmp[4] = '0'; +- tmp[5] = '\0'; +- return parseTimeZone(tmp, 5); +- } +- } ++ unsigned int hours, minutes, seconds, remaining; ++ int sign; ++ ++ sign = 1; ++ hours = 0; ++ minutes = 0; ++ seconds = 0; ++ ++ newString = strndup(s, len); ++ p = newString; ++ ++ if (isalpha(*p)) ++ seconds = offsetFromTZAbbreviation(&p); ++ while (isspace(*p)) ++ p++; ++ while (*p == '+' || *p == '-') { ++ if (*p == '-') ++ sign = -sign; ++ p++; + } +- else if (*s == '0') { +- if (len == 2) { // '00' +- if (p[1] == '0') return gmt; +- if (p[1] == '1') return gmt01; +- if (p[1] == '2') return gmt02; +- } +- else if (len == 4) { +- if (p[2] == '0' && p[3] == '0') { // '0x00' +- if (p[1] == '0') return gmt; +- if (p[1] == '1') return gmt01; +- if (p[1] == '2') return gmt02; +- } +- } ++ digits = digitsString(p); ++ p = digits; ++ remaining = strlen(p); ++ switch(remaining) { ++ case 6: /* hhmmss */ ++ seconds += (10 * (*(p + remaining - 2) - 48) ++ + *(p + remaining - 1) - 48); ++ case 4: /* hhmm */ ++ hours += 10 * (*p - 48); ++ p++; ++ case 3: /* hmm */ ++ hours += (*p - 48); ++ p++; ++ minutes += 10 * (*p - 48) + *(p + 1) - 48; ++ break; ++ case 2: /* hh */ ++ hours += 10 * (*p - 48) + *(p + 1) - 48; ++ break; ++ default: ++ NSLog (@"parseTimeZone: cannot parse time notation '%s'", newString); + } +- else if (len == 3) { +- if (strcasecmp((char *)s, "GMT") == 0) return gmt; +- if (strcasecmp((char *)s, "UTC") == 0) return gmt; +- if (strcasecmp((char *)s, "MET") == 0) return met; +- if (strcasecmp((char *)s, "CET") == 0) return met; +- } +- +- if (isalpha(*s)) { +- ts = [[NSString alloc] initWithCString:(char *)s length:len]; +- } +- else { +- char buf[len + 5]; +- +- buf[0] = 'G'; buf[1] = 'M'; buf[2] = 'T'; +- if (*s == '+' || *s == '-') { +- strcpy(&(buf[3]), (char *)s); +- } +- else { +- buf[3] = '+'; +- strcpy(&(buf[4]), (char *)s); +- } +- ts = [[NSString alloc] initWithCString:buf]; +- } +-#if 1 +- NSLog(@"%s: RFC822 TZ Parser: expensive: '%@'", __PRETTY_FUNCTION__, ts); +-#endif +- tz = [NSTimeZone timeZoneWithAbbreviation:ts]; +- [ts release]; ++ free(digits); ++ ++ seconds += sign * (3600 * hours + 60 * minutes); ++ tz = [NSTimeZone timeZoneForSecondsFromGMT: seconds]; ++ free(newString); ++ + return tz; + } + + - (id)parseValue:(id)_data ofHeaderField:(NSString *)_field { + // TODO: use UNICODE + NSCalendarDate *date = nil; +- unsigned char buf[256]; +- unsigned char *bytes = buf, *pe; ++ char *bytes, *pe; + unsigned length = 0; + NSTimeZone *tz = nil; + char dayOfMonth, monthOfYear, hour, minute, second; + short year; + BOOL flag; +- +- if ((length = [_data cStringLength]) > 254) { +- [self logWithFormat: +- @"header field value to large for date parsing: '%@'(%i)", +- _data, length]; +- length = 254; +- } +- +- [_data getCString:(char *)buf maxLength:length]; +- buf[length] = '\0'; +- ++ ++ length = [_data lengthOfBytesUsingEncoding: NSUTF8StringEncoding]; ++ bytes = [_data cStringUsingEncoding: NSUTF8StringEncoding]; ++ + /* remove leading chars (skip to first digit, the day of the month) */ + while (length > 0 && (!isdigit(*bytes))) { + bytes++; +@@ -312,7 +217,7 @@ + if (length == 0) { + NSLog(@"WARNING(%s): empty value for header field %@ ..", + __PRETTY_FUNCTION__, _field); +- return [CalDateClass date]; ++ return [NSCalendarDate date]; + } + + // TODO: should be a category on NSCalendarDate +@@ -435,7 +340,8 @@ + for (pe = bytes; isalnum(*pe) || *pe == '-' || *pe == '+'; pe++) + ; + *pe = '\0'; +- if ((tz = parseTimeZone(bytes, (pe - bytes))) == nil) { ++ if (pe == bytes ++ || (tz = parseTimeZone((const char *) bytes, (pe - bytes))) == nil) { + [self logWithFormat: + @"WARNING: failed to parse RFC822 timezone: '%s' (value='%@')", + bytes, _data]; +@@ -444,9 +350,9 @@ + + /* construct and return */ + finished: +- date = [CalDateClass dateWithYear:year month:monthOfYear day:dayOfMonth +- hour:hour minute:minute second:second +- timeZone:tz]; ++ date = [NSCalendarDate dateWithYear:year month:monthOfYear day:dayOfMonth ++ hour:hour minute:minute second:second ++ timeZone:tz]; + if (date == nil) goto failed; + + #if 0 +Index: sope-mime/NGMime/NGMimeMultipartBodyParser.m +=================================================================== +--- sope-mime/NGMime/NGMimeMultipartBodyParser.m (revision 1660) ++++ sope-mime/NGMime/NGMimeMultipartBodyParser.m (working copy) +@@ -428,6 +428,7 @@ + NSString *boundary = nil; + NSArray *rawBodyParts = nil; + BOOL foundError = NO; ++ NSData *boundaryBytes; + + contentType = [_part contentType]; + boundary = [contentType valueOfParameter:@"boundary"]; +@@ -437,9 +438,10 @@ + + *(&foundError) = NO; + ++ boundaryBytes = [boundary dataUsingEncoding:NSISOLatin1StringEncoding]; + *(&rawBodyParts) = [self _parseBody:_body part:_part data:_data +- boundary:[boundary cString] +- length:[boundary cStringLength] ++ boundary:[boundaryBytes bytes] ++ length:[boundary length] + delegate:_d]; + + if (rawBodyParts) { +Index: sope-mime/NGMime/NGMimeHeaderFieldGeneratorSet.m +=================================================================== +--- sope-mime/NGMime/NGMimeHeaderFieldGeneratorSet.m (revision 1660) ++++ sope-mime/NGMime/NGMimeHeaderFieldGeneratorSet.m (working copy) +@@ -77,6 +77,7 @@ + [rfc822Set setGenerator:gen forField:@"bcc"]; + [rfc822Set setGenerator:gen forField:Fields->from]; + [rfc822Set setGenerator:gen forField:@"reply-to"]; ++ [rfc822Set setGenerator:gen forField:@"in-reply-to"]; + [rfc822Set setGenerator:gen forField:@"Disposition-Notification-To"]; + } + +Index: sope-mime/NGMime/NGMimeType.m +=================================================================== +--- sope-mime/NGMime/NGMimeType.m (revision 1660) ++++ sope-mime/NGMime/NGMimeType.m (working copy) +@@ -120,30 +120,30 @@ + + /* some unsupported, but known encoding */ + else if ([charset isEqualToString:@"ks_c_5601-1987"]) { +- encoding = [NSString defaultCStringEncoding]; ++ encoding = NSISOLatin1StringEncoding; + foundUnsupported = YES; + } + else if ([charset isEqualToString:@"euc-kr"]) { +- encoding = [NSString defaultCStringEncoding]; +- foundUnsupported = YES; ++ encoding = NSKoreanEUCStringEncoding; + } + else if ([charset isEqualToString:@"big5"]) { +- encoding = [NSString defaultCStringEncoding]; +- foundUnsupported = YES; ++ encoding = NSBIG5StringEncoding; + } + else if ([charset isEqualToString:@"iso-2022-jp"]) { +- encoding = [NSString defaultCStringEncoding]; +- foundUnsupported = YES; ++ encoding = NSISO2022JPStringEncoding; + } + else if ([charset isEqualToString:@"gb2312"]) { +- encoding = [NSString defaultCStringEncoding]; +- foundUnsupported = YES; ++ encoding = NSGB2312StringEncoding; + } + else if ([charset isEqualToString:@"koi8-r"]) { +- encoding = [NSString defaultCStringEncoding]; +- foundUnsupported = YES; ++ encoding = NSKOI8RStringEncoding; + } +- ++ else if ([charset isEqualToString:@"windows-1250"]) { ++ encoding = NSWindowsCP1250StringEncoding; ++ } ++ else if ([charset isEqualToString:@"windows-1251"]) { ++ encoding = NSWindowsCP1251StringEncoding; ++ } + else if ([charset isEqualToString:@"windows-1252"]) { + encoding = NSWindowsCP1252StringEncoding; + } +@@ -152,7 +152,7 @@ + } + else if ([charset isEqualToString:@"x-unknown"] || + [charset isEqualToString:@"unknown"]) { +- encoding = NSASCIIStringEncoding; ++ encoding = NSISOLatin1StringEncoding; + } + /* ISO Latin 9 */ + #if !(NeXT_Foundation_LIBRARY || APPLE_Foundation_LIBRARY) +@@ -166,7 +166,7 @@ + else { + [self logWithFormat:@"%s: unknown charset '%@'", + __PRETTY_FUNCTION__, _s]; +- encoding = [NSString defaultCStringEncoding]; ++ encoding = NSISOLatin1StringEncoding; + } + return encoding; + } +@@ -385,23 +385,26 @@ + } + + - (BOOL)valueNeedsQuotes:(NSString *)_parameterValue { +- unsigned len = [_parameterValue cStringLength]; +- char buf[len + 15]; +- char *cstr; ++ NSData *stringData; ++ const char *cstr; ++ unsigned int count, max; ++ BOOL needsQuote; + +- cstr = &(buf[0]); ++ needsQuote = NO; + +- [_parameterValue getCString:cstr]; cstr[len] = '\0'; +- while (*cstr) { +- if (isMime_SpecialByte(*cstr)) +- return YES; ++ stringData = [_parameterValue dataUsingEncoding:NSUTF8StringEncoding]; ++ cstr = [stringData bytes]; ++ max = [stringData length]; ++ count = 0; ++ while (!needsQuote && count < max) { ++ if (isMime_SpecialByte(*(cstr + count)) ++ || *(cstr + count) == 32) ++ needsQuote = YES; ++ else ++ count++; ++ } + +- if (*cstr == 32) +- return YES; +- +- cstr++; +- } +- return NO; ++ return needsQuote; + } + + - (NSString *)stringValue { +Index: sope-mime/NGMime/NGMimeBodyPart.m +=================================================================== +--- sope-mime/NGMime/NGMimeBodyPart.m (revision 1660) ++++ sope-mime/NGMime/NGMimeBodyPart.m (working copy) +@@ -31,18 +31,6 @@ + return 2; + } + +-static NGMimeType *defaultType = nil; +- +-+ (void)initialize { +- static BOOL isInitialized = NO; +- if (!isInitialized) { +- isInitialized = YES; +- +- defaultType = +- [[NGMimeType mimeType:@"text/plain; charset=us-ascii"] retain]; +- } +-} +- + + (id)bodyPartWithHeader:(NGHashMap *)_header { + return [[[self alloc] initWithHeader:_header] autorelease]; + } +@@ -156,13 +144,12 @@ + if (!Fields) + Fields = (NGMimeHeaderNames *)[NGMimePartParser headerFieldNames]; + +- + type = [self->header objectForKey:Fields->contentType]; + + if (![type isKindOfClass:[NGMimeType class]]) + type = [NGMimeType mimeType:[type stringValue]]; + +- return (type != nil ? type : (id)defaultType); ++ return type; + } + + - (NSString *)contentId { +Index: sope-mime/NGMime/ChangeLog +=================================================================== +--- sope-mime/NGMime/ChangeLog (revision 1660) ++++ sope-mime/NGMime/ChangeLog (working copy) +@@ -1,3 +1,25 @@ ++2008-09-08 Wolfgang Sourdeau <wsourdeau@inverse.ca> ++ ++ * NGMimeRFC822DateHeaderFieldParser.m ([NGMimeRFC ++ -parseValue:ofHeaderField:]): don't parse timezone with a length ++ of 0. ++ ++2008-09-01 Wolfgang Sourdeau <wsourdeau@inverse.ca> ++ ++ * NGMimeRFC822DateHeaderFieldParser.m ([NGMimeRFC ++ -parseValue:ofHeaderField:]): use an 8-bit safe encoding when ++ parsing dates. Since we only consider 7-bits characters, we ensure ++ that bad user-agents can be handled more properly. ++ ++ * NGMimeType.m ([NGMimeType +stringEncodingForCharset:]): ++ x-unknown encoding is now translated to an 8-bit safe encoding ++ (NSISOLatin1StringEncoding). ++ ++ * NGMimeAddressHeaderFieldGenerator.m ++ ([NGMimeAddressHeaderFieldGenerator ++ -generateDataForHeaderFieldNamed:value:]): encode resulting string ++ in an 8-bit safe encoding (NSISOLatin1StringEncoding). ++ + 2008-01-29 Albrecht Dress <albrecht.dress@lios-tech.com> + + * fixes for OGo bug #789 (reply-to QP encoding) +Index: sope-mime/NGMime/NGMimeContentTypeHeaderFieldGenerator.m +=================================================================== +--- sope-mime/NGMime/NGMimeContentTypeHeaderFieldGenerator.m (revision 1660) ++++ sope-mime/NGMime/NGMimeContentTypeHeaderFieldGenerator.m (working copy) +@@ -36,8 +36,7 @@ + NGMimeType *type = nil; // only one content-type field + NSString *tmp = nil; + NSMutableData *data = nil; +- unsigned char *ctmp = NULL; +- unsigned len = 0; ++ NSData *valueData; + + type = _value; + +@@ -59,21 +58,15 @@ + + tmp = [type type]; + NSAssert(tmp, @"type should not be nil"); +- len = [tmp length]; +- ctmp = malloc(len + 4); +- [tmp getCString:(char *)ctmp]; ctmp[len] = '\0'; +- [data appendBytes:ctmp length:len]; +- free(ctmp); ++ valueData = [tmp dataUsingEncoding: NSISOLatin1StringEncoding]; ++ [data appendData: valueData]; ++ ++ [data appendBytes:"/" length:1]; + +- [data appendBytes:"//" length:1]; +- + tmp = [type subType]; + if (tmp != nil) { +- len = [tmp length]; +- ctmp = malloc(len + 4); +- [tmp getCString:(char *)ctmp]; ctmp[len] = '\0'; +- [data appendBytes:ctmp length:len]; +- free(ctmp); ++ valueData = [tmp dataUsingEncoding: NSISOLatin1StringEncoding]; ++ [data appendData:valueData]; + } + else + [data appendBytes:"*" length:1]; +@@ -91,12 +84,9 @@ + continue; + } + [data appendBytes:"; " length:2]; +- +- len = [name cStringLength]; +- ctmp = malloc(len + 1); +- [name getCString:(char *)ctmp]; ctmp[len] = '\0'; +- [data appendBytes:ctmp length:len]; +- free(ctmp); ++ ++ valueData = [name dataUsingEncoding: NSUTF8StringEncoding]; ++ [data appendData: valueData]; + + /* + this confuses GroupWise: "= \"" (a space) +@@ -105,66 +95,30 @@ + + /* check for encoding */ + { +- unsigned cnt; ++ unsigned cnt, max; ++ const char *dataBytes; + BOOL doEnc; + +- len = [value cStringLength]; +- ctmp = malloc(len + 4); +- [value getCString:(char *)ctmp]; ctmp[len] = '\0'; +- cnt = 0; ++ valueData = [value dataUsingEncoding:NSUTF8StringEncoding]; ++ dataBytes = [valueData bytes]; ++ max = [valueData length]; ++ + doEnc = NO; +- while (cnt < len) { +- if ((unsigned char)ctmp[cnt] > 127) { ++ cnt = 0; ++ while (!doEnc && cnt < max) { ++ if ((unsigned char)dataBytes[cnt] > 127) + doEnc = YES; +- break; +- } +- cnt++; ++ else ++ cnt++; + } + if (doEnc) { +- unsigned char iso[] = "=?iso-8859-15?q?"; +- unsigned isoLen = 16; +- unsigned char isoEnd[] = "?="; +- unsigned isoEndLen = 2; +- unsigned desLen; +- unsigned char *des; +- +- if (ctmp) free(ctmp); +- { +- NSData *data; +- +-#if APPLE_Foundation_LIBRARY || NeXT_Foundation_LIBRARY +- data = [value dataUsingEncoding:NSISOLatin1StringEncoding]; +-#else +- data = [value dataUsingEncoding:NSISOLatin9StringEncoding]; +-#endif +- +- len = [data length]; +- ctmp = malloc(len + 10); +- [data getBytes:ctmp]; ctmp[len] = '\0'; +- } +- +- desLen = len * 3 + 20; +- des = calloc(desLen + 10, sizeof(char)); +- +- memcpy(des, ctmp, cnt); +- memcpy(des + cnt, iso, isoLen); +- desLen = +- NGEncodeQuotedPrintableMime(ctmp + cnt, len - cnt, +- des + cnt + isoLen, +- desLen - cnt - isoLen); +- if ((int)desLen != -1) { +- memcpy(des + cnt + isoLen + desLen, isoEnd, isoEndLen); +- [data appendBytes:des length:(cnt + isoLen + desLen + isoEndLen)]; +- } +- else { +- NSLog(@"WARNING: An error occour during quoted-printable decoding"); +- } +- if (des) free(des); ++ [data appendBytes:"=?utf-8?q?" length:10]; ++ [data appendData: [valueData dataByEncodingQuotedPrintable]]; ++ [data appendBytes:"?=" length:2]; + } + else { +- [data appendBytes:ctmp length:len]; ++ [data appendData: valueData]; + } +- free(ctmp); + } + [data appendBytes:"\"" length:1]; + } +Index: sope-mime/NGMime/NGMimePartGenerator.m +=================================================================== +--- sope-mime/NGMime/NGMimePartGenerator.m (revision 1660) ++++ sope-mime/NGMime/NGMimePartGenerator.m (working copy) +@@ -155,8 +155,9 @@ + BOOL isMultiValue, isFirst; + + /* get field name and strip leading spaces */ +- fcname = (const unsigned char *)[_field cString]; +- for (len = [_field cStringLength]; len > 0; fcname++, len--) { ++ fcname = (const unsigned char *)[_field cStringUsingEncoding:NSISOLatin1StringEncoding]; ++ for (len = [_field lengthOfBytesUsingEncoding:NSISOLatin1StringEncoding]; ++ len > 0; fcname++, len--) { + if (*fcname != ' ') + break; + } +@@ -328,7 +329,7 @@ + if ([body isKindOfClass:[NSData class]]) + data = body; + else if ([body isKindOfClass:[NSString class]]) +- data = [body dataUsingEncoding:[NSString defaultCStringEncoding]]; ++ data = [body dataUsingEncoding: NSISOLatin1StringEncoding]; + else + data = nil; + +Index: sope-mime/NGMime/NGMimeBodyParser.m +=================================================================== +--- sope-mime/NGMime/NGMimeBodyParser.m (revision 1660) ++++ sope-mime/NGMime/NGMimeBodyParser.m (working copy) +@@ -67,7 +67,10 @@ + if (_data == nil) return nil; + + ctype = [_part contentType]; +- ++ if (!ctype ++ && [_d respondsToSelector: @selector(parser:contentTypeOfPart:)]) ++ ctype = [_d parser: self contentTypeOfPart: _part]; ++ + if (![ctype isKindOfClass:[NGMimeType class]]) + ctype = [NGMimeType mimeType:[ctype stringValue]]; + +@@ -88,10 +91,20 @@ + NSStringEncoding encoding; + + encoding = [NGMimeType stringEncodingForCharset:charset]; +- ++ ++ // If we nave no encoding here, let's not simply return nil. ++ // We SHOULD try at least UTF-8 and after, Latin1. ++ if (!encoding) ++ encoding = NSUTF8StringEncoding; ++ + body = [[[NSString alloc] +- initWithData:_data ++ initWithData:_data + encoding:encoding] autorelease]; ++ ++ if (!body) ++ body = [[[NSString alloc] initWithData:_data ++ encoding:NSISOLatin1StringEncoding] ++ autorelease]; + } + return body; + } +Index: sope-mime/NGMime/NGMimePartParser.h +=================================================================== +--- sope-mime/NGMime/NGMimePartParser.h (revision 1660) ++++ sope-mime/NGMime/NGMimePartParser.h (working copy) +@@ -117,6 +117,7 @@ + BOOL parserParseRawBodyDataOfPart:1; + BOOL parserBodyParserForPart:1; + BOOL parserDecodeBodyOfPart:1; ++ BOOL parserContentTypeOfPart:1; + } delegateRespondsTo; + + +@@ -275,6 +276,9 @@ + - (id<NGMimeBodyParser>)parser:(NGMimePartParser *)_parser + bodyParserForPart:(id<NGMimePart>)_part; + ++- (NGMimeType *)parser:(id)_parser ++ contentTypeOfPart:(id<NGMimePart>)_part; ++ + @end /* NSObject(NGMimePartParserDelegate) */ + + @interface NSObject(NGMimePartParser) +Index: sope-mime/NGMime/NGMimePartParser.m +=================================================================== +--- sope-mime/NGMime/NGMimePartParser.m (revision 1660) ++++ sope-mime/NGMime/NGMimePartParser.m (working copy) +@@ -227,7 +227,7 @@ + } + + + (NSStringEncoding)defaultHeaderFieldEncoding { +- return NSISOLatin1StringEncoding; ++ return NSUTF8StringEncoding; + } + + - (id)valueOfHeaderField:(NSString *)_name data:(id)_data { +@@ -1091,7 +1091,10 @@ + id<NGMimeBodyParser> bodyParser = nil; + + ctype = [_p contentType]; +- ++ if (!ctype ++ && self->delegateRespondsTo.parserContentTypeOfPart) ++ ctype = [self->delegate parser: self contentTypeOfPart: _p]; ++ + contentType = ([ctype isKindOfClass:[NGMimeType class]]) + ? ctype + : [NGMimeType mimeType:[ctype stringValue]]; +Index: sope-mime/NGMime/NGMimeAddressHeaderFieldGenerator.m +=================================================================== +--- sope-mime/NGMime/NGMimeAddressHeaderFieldGenerator.m (revision 1660) ++++ sope-mime/NGMime/NGMimeAddressHeaderFieldGenerator.m (working copy) +@@ -105,10 +105,10 @@ + } + + tmp = [obj displayName]; +- bufLen = [tmp cStringLength]; ++ bufLen = [tmp lengthOfBytesUsingEncoding: NSUTF8StringEncoding]; + +- buffer = calloc(bufLen + 10, sizeof(char)); +- [tmp getCString:buffer]; ++ buffer = calloc(bufLen, sizeof(char)); ++ [tmp getCString: buffer maxLength: bufLen encoding: NSUTF8StringEncoding]; + + cnt = 0; + doEnc = NO; +@@ -117,11 +117,11 @@ + /* must encode chars outside ASCII 33..60, 62..126 ranges [RFC 2045, Sect. 6.7] + * RFC 2047, Sect. 4.2 also requires chars 63 and 95 to be encoded + * For spaces, quotation is fine */ +- if ((unsigned char)buffer[cnt] < 32 || +- (unsigned char)buffer[cnt] == 61 || +- (unsigned char)buffer[cnt] == 63 || +- (unsigned char)buffer[cnt] == 95 || +- (unsigned char)buffer[cnt] > 126) { ++ if ((unichar)buffer[cnt] < 32 || ++ (unichar)buffer[cnt] == 61 || ++ (unichar)buffer[cnt] == 63 || ++ (unichar)buffer[cnt] == 95 || ++ (unichar)buffer[cnt] > 126) { + doEnc = YES; + break; + } +@@ -130,8 +130,13 @@ + + if (doEnc) { + /* FIXME - better use UTF8 encoding! */ ++#if NeXT_Foundation_LIBRARY + unsigned char iso[] = "=?iso-8859-15?q?"; + unsigned isoLen = 16; ++#else ++ unsigned char iso[] = "=?utf-8?q?"; ++ unsigned isoLen = 10; ++#endif + unsigned char isoEnd[] = "?="; + unsigned isoEndLen = 2; + unsigned desLen; +@@ -141,10 +146,10 @@ + { + NSData *data; + +-#if APPLE_Foundation_LIBRARY || NeXT_Foundation_LIBRARY ++#if NeXT_Foundation_LIBRARY + data = [tmp dataUsingEncoding:NSISOLatin1StringEncoding]; + #else +- data = [tmp dataUsingEncoding:NSISOLatin9StringEncoding]; ++ data = [tmp dataUsingEncoding:NSUTF8StringEncoding]; + #endif + + bufLen = [data length]; +@@ -162,8 +167,9 @@ + des + isoLen, desLen - isoLen); + if ((int)desLen != -1) { + memcpy(des + isoLen + desLen, isoEnd, isoEndLen); +- tmp = [NSString stringWithCString:(char *)des +- length:(isoLen + desLen + isoEndLen)]; ++ tmp = [[NSString alloc] initWithData: [NSData dataWithBytes:(char *)des length:(isoLen + desLen + isoEndLen)] ++ encoding: NSISOLatin1StringEncoding]; ++ [tmp autorelease]; + } + else { + [self warnWithFormat: +@@ -190,11 +196,7 @@ + } + } + +-#if APPLE_Foundation_LIBRARY || NeXT_Foundation_LIBRARY + data = [result dataUsingEncoding:NSISOLatin1StringEncoding]; +-#else +- data = [result dataUsingEncoding:NSISOLatin9StringEncoding]; +-#endif + [result release]; + + return data; +Index: sope-mime/NGMime/NGMimeContentDispositionHeaderFieldGenerator.m +=================================================================== +--- sope-mime/NGMime/NGMimeContentDispositionHeaderFieldGenerator.m (revision 1660) ++++ sope-mime/NGMime/NGMimeContentDispositionHeaderFieldGenerator.m (working copy) +@@ -49,80 +49,70 @@ + + // TODO: move the stuff below to some NSString or NSData category? + +- data = [NSMutableData dataWithCapacity:64]; ++ data = [NSMutableData dataWithCapacity: 64]; + tmp = [field type]; + [data appendBytes:[tmp cString] length:[tmp length]]; + tmp = [field filename]; + if (tmp != nil) { + [data appendBytes:"; " length:2]; + [data appendBytes:"filename=\"" length:10]; +- { +- unsigned char *ctmp; +- int cnt, len; +- BOOL doEnc; +- +- // TODO: unicode? +- len = [tmp cStringLength]; +- ctmp = malloc(len + 3); +- [tmp getCString:(char *)ctmp]; ctmp[len] = '\0'; +- cnt = 0; +- doEnc = NO; +- while (cnt < len) { +- if ((unsigned char)ctmp[cnt] > 127) { +- doEnc = YES; +- break; +- } +- cnt++; ++ ++ NSData *d; ++ unsigned char* bytes; ++ unsigned length; ++ int cnt; ++ BOOL doEnc; ++ ++ //d = [tmp dataUsingEncoding: NSUTF8StringEncoding]; ++ //bytes = [d bytes]; ++ //length = [d length]; ++ bytes = [tmp cStringUsingEncoding: NSUTF8StringEncoding]; ++ length = strlen(bytes); ++ ++ cnt = 0; ++ doEnc = NO; ++ while (cnt < length) { ++ if ((unsigned char)bytes[cnt] > 127) { ++ doEnc = YES; ++ break; + } +- if (doEnc) { +- char iso[] = "=?iso-8859-15?q?"; +- unsigned isoLen = 16; +- char isoEnd[] = "?="; +- unsigned isoEndLen = 2; +- unsigned desLen; +- char *des; +- +- if (ctmp) free(ctmp); +- { +- NSData *data; ++ cnt++; ++ } + +-#if APPLE_Foundation_LIBRARY || NeXT_Foundation_LIBRARY +- data = [tmp dataUsingEncoding:NSISOLatin1StringEncoding]; +-#else +- data = [tmp dataUsingEncoding:NSISOLatin9StringEncoding]; +-#endif +- +- len = [data length]; +- ctmp = malloc(len+1); +- [data getBytes:ctmp]; ctmp[len] = '\0'; +- } +- +- desLen = len * 3 + 20; +- des = calloc(desLen + 10, sizeof(char)); +- +- memcpy(des, ctmp, cnt); +- memcpy(des + cnt, iso, isoLen); +- desLen = +- NGEncodeQuotedPrintableMime((unsigned char *)ctmp + cnt, len - cnt, +- (unsigned char *)des + cnt + isoLen, +- desLen - cnt - isoLen); +- if ((int)desLen != -1) { +- memcpy(des + cnt + isoLen + desLen, isoEnd, isoEndLen); +- [data appendBytes:des length:(cnt + isoLen + desLen + isoEndLen)]; +- } +- else { ++ if (doEnc) ++ { ++ char iso[] = "=?utf-8?q?"; ++ unsigned isoLen = 10; ++ char isoEnd[] = "?="; ++ unsigned isoEndLen = 2; ++ int desLen; ++ char *des; ++ ++ desLen = length * 3 + 20; ++ ++ des = calloc(desLen + 2, sizeof(char)); ++ ++ memcpy(des, iso, isoLen); ++ desLen = NGEncodeQuotedPrintableMime((unsigned char *)bytes, length, ++ (unsigned char *)(des + isoLen), ++ desLen - isoLen); ++ if (desLen != -1) { ++ memcpy(des + isoLen + desLen, isoEnd, isoEndLen); ++ [data appendBytes:des length:(isoLen + desLen + isoEndLen)]; ++ } ++ else { + [self logWithFormat:@"WARNING(%s:%i): An error occour during " + @"quoted-printable decoding", + __PRETTY_FUNCTION__, __LINE__]; +- } +- if (des) free(des); ++ if (des != NULL) free(des); ++ } + } +- else { +- [data appendBytes:ctmp length:len]; ++ else ++ { ++ [data appendBytes:[tmp cString] length:[tmp length]]; + } +- } +- // [data appendBytes:[tmp cString] length:[tmp length]]; +- [data appendBytes:"\"" length:1]; ++ ++ [data appendBytes:"\"" length:1]; + } + return data; + } +Index: sope-core/NGExtensions/NGExtensions/NSString+Ext.h +=================================================================== +--- sope-core/NGExtensions/NGExtensions/NSString+Ext.h (revision 1660) ++++ sope-core/NGExtensions/NGExtensions/NSString+Ext.h (working copy) +@@ -30,6 +30,7 @@ + + @interface NSString(GSAdditions) + ++#if !GNUSTEP + - (NSString *)stringWithoutPrefix:(NSString *)_prefix; + - (NSString *)stringWithoutSuffix:(NSString *)_suffix; + +@@ -39,6 +40,7 @@ + - (NSString *)stringByTrimmingLeadSpaces; + - (NSString *)stringByTrimmingTailSpaces; + - (NSString *)stringByTrimmingSpaces; ++#endif /* !GNUSTEP */ + + /* the following are not available in gstep-base 1.6 ? */ + - (NSString *)stringByTrimmingLeadWhiteSpaces; +@@ -47,6 +49,8 @@ + + @end /* NSString(GSAdditions) */ + ++#if !GNUSTEP ++ + @interface NSMutableString(GNUstepCompatibility) + + - (void)trimLeadSpaces; +@@ -55,6 +59,8 @@ + + @end /* NSMutableString(GNUstepCompatibility) */ + ++#endif /* !GNUSTEP */ ++ + #endif + + /* specific to libFoundation */ +Index: sope-core/NGExtensions/FdExt.subproj/NSString+Ext.m +=================================================================== +--- sope-core/NGExtensions/FdExt.subproj/NSString+Ext.m (revision 1660) ++++ sope-core/NGExtensions/FdExt.subproj/NSString+Ext.m (working copy) +@@ -39,18 +39,6 @@ + : (NSString *)[[self copy] autorelease]; + } + +-- (NSString *)stringByReplacingString:(NSString *)_orignal +- withString:(NSString *)_replacement +-{ +- /* very slow solution .. */ +- +- if ([self rangeOfString:_orignal].length == 0) +- return [[self copy] autorelease]; +- +- return [[self componentsSeparatedByString:_orignal] +- componentsJoinedByString:_replacement]; +-} +- + - (NSString *)stringByTrimmingLeadWhiteSpaces + { + // should check 'whitespaceAndNewlineCharacterSet' .. +@@ -96,6 +84,25 @@ + return [[self copy] autorelease]; + } + ++- (NSString *)stringByTrimmingWhiteSpaces ++{ ++ return [[self stringByTrimmingTailWhiteSpaces] ++ stringByTrimmingLeadWhiteSpaces]; ++} ++ ++#ifndef GNUSTEP ++- (NSString *)stringByReplacingString:(NSString *)_orignal ++ withString:(NSString *)_replacement ++{ ++ /* very slow solution .. */ ++ ++ if ([self rangeOfString:_orignal].length == 0) ++ return [[self copy] autorelease]; ++ ++ return [[self componentsSeparatedByString:_orignal] ++ componentsJoinedByString:_replacement]; ++} ++ + - (NSString *)stringByTrimmingLeadSpaces + { + unsigned len; +@@ -117,6 +124,7 @@ + else + return [[self copy] autorelease]; + } ++ + - (NSString *)stringByTrimmingTailSpaces + { + unsigned len; +@@ -139,19 +147,17 @@ + return [[self copy] autorelease]; + } + +-- (NSString *)stringByTrimmingWhiteSpaces +-{ +- return [[self stringByTrimmingTailWhiteSpaces] +- stringByTrimmingLeadWhiteSpaces]; +-} + - (NSString *)stringByTrimmingSpaces + { + return [[self stringByTrimmingTailSpaces] + stringByTrimmingLeadSpaces]; + } ++#endif + + @end /* NSString(GSAdditions) */ + ++#if !GNUSTEP ++ + @implementation NSMutableString(GNUstepCompatibility) + + - (void)trimLeadSpaces +@@ -169,6 +175,8 @@ + + @end /* NSMutableString(GNUstepCompatibility) */ + ++#endif /* !GNUSTEP */ ++ + @implementation NSString(lfNSURLUtilities) + + - (BOOL)isAbsoluteURL +Index: sope-core/NGExtensions/FdExt.subproj/NSString+Encoding.m +=================================================================== +--- sope-core/NGExtensions/FdExt.subproj/NSString+Encoding.m (revision 1660) ++++ sope-core/NGExtensions/FdExt.subproj/NSString+Encoding.m (working copy) +@@ -140,8 +140,12 @@ + + + #ifdef __linux__ ++#if __BYTE_ORDER == __LITTLE_ENDIAN + static NSString *unicharEncoding = @"UCS-2LE"; + #else ++static NSString *unicharEncoding = @"UCS-2BE"; ++#endif /* __BYTE_ORDER */ ++#else + static NSString *unicharEncoding = @"UCS-2-INTERNAL"; + #endif + static int IconvLogEnabled = -1; +@@ -149,21 +153,12 @@ + static void checkDefaults(void) { + NSUserDefaults *ud; + +- if (IconvLogEnabled != -1) +- return; +- ud = [NSUserDefaults standardUserDefaults]; +- IconvLogEnabled = [ud boolForKey:@"IconvLogEnabled"]?1:0; ++ if (IconvLogEnabled == -1) { ++ ud = [NSUserDefaults standardUserDefaults]; ++ IconvLogEnabled = [ud boolForKey:@"IconvLogEnabled"]?1:0; + +-#ifdef __linux__ +- if (NSHostByteOrder() == NS_BigEndian) { +- NSLog(@"Note: using UCS-2 big endian on Linux."); +- unicharEncoding = @"UCS-2BE"; ++ NSLog(@"Note: using '%@' on Linux.", unicharEncoding); + } +- else { +- NSLog(@"Note: using UCS-2 little endian on Linux."); +- unicharEncoding = @"UCS-2LE"; +- } +-#endif + } + + static char *iconv_wrapper(id self, char *_src, unsigned _srcLen, +Index: sope-core/NGExtensions/EOExt.subproj/EOGlobalID+Ext.m +=================================================================== +--- sope-core/NGExtensions/EOExt.subproj/EOGlobalID+Ext.m (revision 1660) ++++ sope-core/NGExtensions/EOExt.subproj/EOGlobalID+Ext.m (working copy) +@@ -19,6 +19,7 @@ + 02111-1307, USA. + */ + ++#import <Foundation/NSString.h> + #import <EOControl/EOGlobalID.h> + #import <Foundation/NSString.h> + +Index: sope-core/NGStreams/GNUmakefile.preamble +=================================================================== +--- sope-core/NGStreams/GNUmakefile.preamble (revision 1660) ++++ sope-core/NGStreams/GNUmakefile.preamble (working copy) +@@ -1,6 +1,7 @@ + # compilation settings + +-MACHCPU = $(shell echo $$MACHTYPE | cut -f 1 -d '-') ++# MACHCPU = $(shell echo $$MACHTYPE | cut -f 1 -d '-') ++MACHCPU = $(shell uname -m) + + libNGStreams_INCLUDE_DIRS += \ + -I$(GNUSTEP_TARGET_CPU)/$(GNUSTEP_TARGET_OS) \ +Index: sope-xml/libxmlSAXDriver/libxmlHTMLSAXDriver.h +=================================================================== +--- sope-xml/libxmlSAXDriver/libxmlHTMLSAXDriver.h (revision 1660) ++++ sope-xml/libxmlSAXDriver/libxmlHTMLSAXDriver.h (working copy) +@@ -19,6 +19,8 @@ + 02111-1307, USA. + */ + ++#include <libxml/encoding.h> ++ + #include <SaxObjC/SaxXMLReader.h> + #include <SaxObjC/SaxLexicalHandler.h> + #include <SaxObjC/SaxDeclHandler.h> +@@ -34,7 +36,7 @@ + + @interface libxmlHTMLSAXDriver : NSObject < SaxXMLReader > + { +- id<NSObject,SaxContentHandler> contentHandler; ++ NSObject<SaxContentHandler> *contentHandler; + id<NSObject,SaxDTDHandler> dtdHandler; + id<NSObject,SaxErrorHandler> errorHandler; + id<NSObject,SaxEntityResolver> entityResolver; +Index: sope-xml/libxmlSAXDriver/libxmlHTMLSAXDriver.m +=================================================================== +--- sope-xml/libxmlSAXDriver/libxmlHTMLSAXDriver.m (revision 1660) ++++ sope-xml/libxmlSAXDriver/libxmlHTMLSAXDriver.m (working copy) +@@ -200,10 +200,10 @@ + return self->entityResolver; + } + +-- (void)setContentHandler:(id<NSObject,SaxContentHandler>)_handler { ++- (void)setContentHandler:(NSObject <NSObject,SaxContentHandler> *)_handler { + ASSIGN(self->contentHandler, _handler); + } +-- (id<NSObject,SaxContentHandler>)contentHandler { ++- (NSObject <NSObject,SaxContentHandler> *)contentHandler { + return self->contentHandler; + } + +Index: sope-appserver/mod_ngobjweb/GNUmakefile +=================================================================== +--- sope-appserver/mod_ngobjweb/GNUmakefile (revision 1660) ++++ sope-appserver/mod_ngobjweb/GNUmakefile (working copy) +@@ -82,7 +82,7 @@ + + CFLAGS = -Wall -I. -fPIC \ + $(APXS_CFLAGS) $(APR_CFLAGS) \ +- $(APXS_INCLUDE_DIRS) $(APR_INCLUDE_DIRS) ++ $(APXS_INCLUDE_DIRS) $(APR_INCLUDE_DIRS) -O0 -ggdb + + LDFLAGS = $(APXS_LDFLAGS) $(APR_LDFLAGS) -shared -fPIC + LDLIBS = $(APXS_LIBS) $(APR_LIBS) +@@ -111,8 +111,7 @@ + apache-dir : + $(MKDIRS) $(GNUSTEP_INSTALLATION_DIR) + +-install :: apache-dir all +- $(INSTALL_PROGRAM) $(product) $(GNUSTEP_INSTALLATION_DIR) ++install :: + + install-usr-libexec :: all + $(INSTALL_PROGRAM) $(product) /usr/libexec/httpd/ +Index: sope-appserver/NGObjWeb/GNUmakefile.postamble +=================================================================== +--- sope-appserver/NGObjWeb/GNUmakefile.postamble (revision 1660) ++++ sope-appserver/NGObjWeb/GNUmakefile.postamble (working copy) +@@ -23,14 +23,20 @@ + + # install makefiles + +-after-install :: +- $(MKDIRS) $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/Additional/ +- $(INSTALL_DATA) ngobjweb.make $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/Additional/ngobjweb.make ++after-install :: $(DESTDIR)/$(GNUSTEP_MAKEFILES)/Additional/ngobjweb.make + + ifneq ($(GNUSTEP_MAKE_VERSION),1.3.0) +-after-install :: ++after-install :: $(DESTDIR)/$(GNUSTEP_MAKEFILES)/woapp.make $(DESTDIR)/$(GNUSTEP_MAKEFILES)/wobundle.make ++endif ++ ++$(DESTDIR)/$(GNUSTEP_MAKEFILES)/Additional/ngobjweb.make: ngobjweb.make ++ $(MKDIRS) $(DESTDIR)/$(GNUSTEP_MAKEFILES)/Additional/ ++ $(INSTALL_DATA) ngobjweb.make $(DESTDIR)/$(GNUSTEP_MAKEFILES)/Additional/ngobjweb.make ++ ++$(DESTDIR)/$(GNUSTEP_MAKEFILES)/woapp.make: woapp-gs.make + $(INSTALL_DATA) woapp-gs.make \ +- $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/woapp.make ++ $(DESTDIR)/$(GNUSTEP_MAKEFILES)/woapp.make ++ ++$(DESTDIR)/$(GNUSTEP_MAKEFILES)/wobundle.make: wobundle-gs.make + $(INSTALL_DATA) wobundle-gs.make \ +- $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/wobundle.make +-endif ++ $(DESTDIR)/$(GNUSTEP_MAKEFILES)/wobundle.make +Index: sope-appserver/NGObjWeb/WOMessage+XML.m +=================================================================== +--- sope-appserver/NGObjWeb/WOMessage+XML.m (revision 1660) ++++ sope-appserver/NGObjWeb/WOMessage+XML.m (working copy) +@@ -84,7 +84,7 @@ + id builder; + + builder = [[[NSClassFromString(@"DOMSaxBuilder") alloc] init] autorelease]; +- dom = [[builder buildFromData:data] retain]; ++ dom = [builder buildFromData:data]; + } + + /* cache DOM structure */ +Index: sope-appserver/NGObjWeb/ChangeLog +=================================================================== +--- sope-appserver/NGObjWeb/ChangeLog (revision 1660) ++++ sope-appserver/NGObjWeb/ChangeLog (working copy) +@@ -1,3 +1,33 @@ ++2009-10-26 Wolfgang Sourdeau <wsourdeau@inverse.ca> ++ ++ * WOMessage+XML.m (-contentAsDOMDocument): do not retain "dom" as ++ it will be assigned to self->domCache, to avoid a leak. ++ ++2009-10-21 Wolfgang Sourdeau <wsourdeau@inverse.ca> ++ ++ * WebDAV/SoObjectResultEntry.m (-valueForKey:): we now take ++ WOUseRelativeURLs into account when the "href" key is requested, ++ to work around a bug in iCal 4. ++ ++2009-07-02 Wolfgang Sourdeau <wsourdeau@inverse.ca> ++ ++ * WOMessage.m (-setHeaders:, -setHeader:forKey:, headerForKey:, ++ -appendHeader:forKey:, -appendHeaders:forKey:, setHeaders:forKey:, ++ -headersForKey:): convert the specified header key to lowercase, ++ to ensure they are managed case-insensitively. ++ * WOHttpAdaptor/WOHttpTransaction.m ++ (-deliverResponse:toRequest:onStream:): if the content-type is ++ specified and already has "text/plain" as prefix, we don't ++ override it. ++ ++2009-07-01 Wolfgang Sourdeau <wsourdeau@inverse.ca> ++ ++ * WOHttpAdaptor/WOHttpTransaction.m ++ (-deliverResponse:toRequest:onStream:): we test the content-length ++ and impose a content-type of text/plain when 0. This work-arounds ++ a bug in Mozilla clients where empty responses with a content-type ++ set to X/xml will trigger an exception. ++ + 2009-06-10 Helge Hess <helge.hess@opengroupware.org> + + * DAVPropMap.plist: mapped {DAV:}current-user-principal (v4.9.37) +Index: sope-appserver/NGObjWeb/DAVPropMap.plist +=================================================================== +--- sope-appserver/NGObjWeb/DAVPropMap.plist (revision 1660) ++++ sope-appserver/NGObjWeb/DAVPropMap.plist (working copy) +@@ -157,6 +157,7 @@ + "{urn:ietf:params:xml:ns:caldav}supported-calendar-data" = + davSupportedCalendarDataTypes; + "{urn:ietf:params:xml:ns:caldav}calendar-description" = davDescription; ++ "{urn:ietf:params:xml:ns:caldav}calendar-timezone" = davCalendarTimeZone; + + /* CardDAV */ + "{urn:ietf:params:xml:ns:carddav}addressbook-home-set" = davAddressbookHomeSet; +Index: sope-appserver/NGObjWeb/WebDAV/SoObjectResultEntry.m +=================================================================== +--- sope-appserver/NGObjWeb/WebDAV/SoObjectResultEntry.m (revision 1660) ++++ sope-appserver/NGObjWeb/WebDAV/SoObjectResultEntry.m (working copy) +@@ -25,7 +25,14 @@ + @implementation SoObjectResultEntry + + static BOOL debugOn = NO; ++static BOOL useRelativeURLs = NO; + +++ (void) initialize ++{ ++ useRelativeURLs = [[NSUserDefaults standardUserDefaults] ++ boolForKey: @"WOUseRelativeURLs"]; ++} ++ + - (id)initWithURI:(NSString *)_href object:(id)_o values:(NSDictionary *)_d { + if ((self = [super init])) { + if (debugOn) { +@@ -85,10 +92,36 @@ + return YES; + } + ++- (NSString *)_relativeHREF { ++ NSString *newHREF; ++ NSRange hostRange; ++ ++ if ([self->href hasPrefix: @"/"]) ++ return self->href; ++ else { ++ hostRange = [self->href rangeOfString: @"://"]; ++ if (hostRange.length > 0) { ++ newHREF = [self->href substringFromIndex: NSMaxRange (hostRange)]; ++ hostRange = [newHREF rangeOfString: @"/"]; ++ if (hostRange.length > 0) { ++ newHREF = [newHREF substringFromIndex: hostRange.location]; ++ } ++ } else { ++ newHREF = self->href; ++ } ++ ++ return newHREF; ++ } ++} ++ + - (id)valueForKey:(NSString *)_key { +- if ([_key isEqualToString:@"{DAV:}href"]) +- return self->href; +- ++ if ([_key isEqualToString:@"{DAV:}href"]) { ++ if (useRelativeURLs) ++ return [self _relativeHREF]; ++ else ++ return self->href; ++ } ++ + if ([_key isEqualToString:@"{DAV:}status"]) + return nil; + +Index: sope-appserver/NGObjWeb/WebDAV/SoWebDAVRenderer.m +=================================================================== +--- sope-appserver/NGObjWeb/WebDAV/SoWebDAVRenderer.m (revision 1660) ++++ sope-appserver/NGObjWeb/WebDAV/SoWebDAVRenderer.m (working copy) +@@ -49,6 +49,8 @@ + #define XMLNS_INTTASK \ + @"{http://schemas.microsoft.com/mapi/id/{00062003-0000-0000-C000-000000000046}/}" + ++static Class NSURLKlass = Nil; ++ + @interface SoWebDAVRenderer(Privates) + - (BOOL)renderStatusResult:(id)_object withDefaultStatus:(int)_defStatus + inContext:(WOContext *)_ctx; +@@ -79,6 +81,8 @@ + + if ((debugOn = [ud boolForKey:@"SoRendererDebugEnabled"])) + NSLog(@"enabled debugging in SoWebDAVRenderer (SoRendererDebugEnabled)"); ++ ++ NSURLKlass = [NSURL class]; + } + + + (id)sharedRenderer { +@@ -616,16 +620,19 @@ + [r appendContentString:s]; + } + else { ++ s = [self stringForValue:value ofProperty:_key prefixes:nsToPrefix]; + [r appendContentCharacter:'<']; + [r appendContentString:extName]; +- [r appendContentCharacter:'>']; +- +- s = [self stringForValue:value ofProperty:_key prefixes:nsToPrefix]; +- [r appendContentString:s]; +- +- [r appendContentString:@"</"]; +- [r appendContentString:extName]; +- [r appendContentString:@">"]; ++ if ([s length] > 0) { ++ [r appendContentCharacter:'>']; ++ [r appendContentString:s]; ++ [r appendContentString:@"</"]; ++ [r appendContentString:extName]; ++ [r appendContentString:@">"]; ++ } ++ else { ++ [r appendContentString:@"/>"]; ++ } + if (formatOutput) [r appendContentCharacter:'\n']; + } + } +@@ -694,8 +701,13 @@ + } + + /* tidy href */ +- href = [self tidyHref:href baseURL:baseURL]; +- ++ if (useRelativeURLs) { ++ if ([href isKindOfClass: NSURLKlass]) ++ href = [href path]; ++ } ++ else ++ href = [self tidyHref:href baseURL:baseURL]; ++ + /* tidy status */ + stat = [self tidyStatus:stat]; + } +Index: sope-appserver/NGObjWeb/WODirectAction.m +=================================================================== +--- sope-appserver/NGObjWeb/WODirectAction.m (revision 1660) ++++ sope-appserver/NGObjWeb/WODirectAction.m (working copy) +@@ -46,7 +46,7 @@ + } + - (id)initWithContext:(WOContext *)_ctx { + if ((self = [self initWithRequest:[_ctx request]])) { +- self->context = [_ctx retain]; ++ self->context = _ctx; + } + return self; + } +@@ -54,16 +54,16 @@ + return [self initWithRequest:nil]; + } + +-- (void)dealloc { +- [self->context release]; +- [super dealloc]; +-} ++// - (void)dealloc { ++// [self->context release]; ++// [super dealloc]; ++// } + + /* accessors */ + + - (WOContext *)context { + if (self->context == nil) +- self->context = [[[WOApplication application] context] retain]; ++ self->context = [[WOApplication application] context]; + return self->context; + } + +Index: sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.m +=================================================================== +--- sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.m (revision 1660) ++++ sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.m (working copy) +@@ -216,6 +216,12 @@ + assocCount++; + } + } ++ if (count > 0) { ++ if ((self->isAbsolute = OWGetProperty(_config, @"absolute"))) { ++ count--; ++ assocCount++; ++ } ++ } + + self->rest = _config; + +Index: sope-appserver/NGObjWeb/DynamicElements/_WOComplexHyperlink.m +=================================================================== +--- sope-appserver/NGObjWeb/DynamicElements/_WOComplexHyperlink.m (revision 1660) ++++ sope-appserver/NGObjWeb/DynamicElements/_WOComplexHyperlink.m (working copy) +@@ -41,6 +41,7 @@ + WOAssociation *string; + WOAssociation *target; + WOAssociation *disabled; ++ WOAssociation *isAbsolute; + WOElement *template; + + /* new in WO4: */ +@@ -360,6 +361,7 @@ + { + if ((self = [super initWithName:_name hyperlinkInfo:_info template:_t])) { + self->href = _info->href; ++ self->isAbsolute = _info->isAbsolute; + } + return self; + } +@@ -375,8 +377,11 @@ + // TODO: we need a binding to disable rewriting! + NSRange r; + ++ if ([[self->isAbsolute valueInContext:_ctx] boolValue] == YES) ++ return NO; ++ + r.length = [_s length]; +- ++ + /* do not rewrite pure fragment URLs */ + if (r.length > 0 && [_s characterAtIndex:0] == '#') + return NO; +Index: sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.h +=================================================================== +--- sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.h (revision 1660) ++++ sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.h (working copy) +@@ -41,7 +41,8 @@ + WOAssociation *pageName; + WOAssociation *actionClass; + WOAssociation *directActionName; +- ++ WOAssociation *isAbsolute; ++ + BOOL sidInUrl; + + /* 'ivar' associations */ +Index: sope-appserver/NGObjWeb/WOMessage.m +=================================================================== +--- sope-appserver/NGObjWeb/WOMessage.m (revision 1660) ++++ sope-appserver/NGObjWeb/WOMessage.m (working copy) +@@ -182,7 +182,7 @@ + NSString *key; + + keys = [_headers keyEnumerator]; +- while ((key = [keys nextObject])) { ++ while ((key = [[keys nextObject] lowercaseString])) { + id value; + + value = [_headers objectForKey:key]; +@@ -198,34 +198,39 @@ + } + + - (void)setHeader:(NSString *)_header forKey:(NSString *)_key { +- [self->header setObject:[_header stringValue] forKey:_key]; ++ [self->header setObject:[_header stringValue] ++ forKey:[_key lowercaseString]]; + } + - (NSString *)headerForKey:(NSString *)_key { +- return [[self->header objectEnumeratorForKey:_key] nextObject]; ++ return [[self->header objectEnumeratorForKey:[_key lowercaseString]] ++ nextObject]; + } + + - (void)appendHeader:(NSString *)_header forKey:(NSString *)_key { +- [self->header addObject:_header forKey:_key]; ++ [self->header addObject:_header forKey:[_key lowercaseString]]; + } + - (void)appendHeaders:(NSArray *)_headers forKey:(NSString *)_key { +- [self->header addObjects:_headers forKey:_key]; ++ [self->header addObjects:_headers forKey:[_key lowercaseString]]; + } + + - (void)setHeaders:(NSArray *)_headers forKey:(NSString *)_key { + NSEnumerator *e; + id value; ++ NSString *lowerKey; + ++ lowerKey = [_key lowercaseString]; + e = [_headers objectEnumerator]; + +- [self->header removeAllObjectsForKey:_key]; ++ [self->header removeAllObjectsForKey:lowerKey]; + + while ((value = [e nextObject])) +- [self->header addObject:value forKey:_key]; ++ [self->header addObject:value forKey:lowerKey]; + } + - (NSArray *)headersForKey:(NSString *)_key { + NSEnumerator *values; + +- if ((values = [self->header objectEnumeratorForKey:_key])) { ++ if ((values ++ = [self->header objectEnumeratorForKey:[_key lowercaseString]])) { + NSMutableArray *array = nil; + id value = nil; + +@@ -243,17 +248,14 @@ + NSEnumerator *values; + + if ((values = [self->header keyEnumerator])) { +- NSMutableArray *array = nil; ++ NSMutableArray *array; + id name = nil; +- array = [[NSMutableArray alloc] init]; +- ++ array = [NSMutableArray array]; ++ + while ((name = [values nextObject])) + [array addObject:name]; + +- name = [array copy]; +- [array release]; +- +- return [name autorelease]; ++ return array; + } + return nil; + } +Index: sope-appserver/NGObjWeb/SoObjects/SoObject.m +=================================================================== +--- sope-appserver/NGObjWeb/SoObjects/SoObject.m (revision 1660) ++++ sope-appserver/NGObjWeb/SoObjects/SoObject.m (working copy) +@@ -39,22 +39,34 @@ + static int debugLookup = -1; + static int debugBaseURL = -1; + static int useRelativeURLs = -1; ++static int redirectInitted = -1; ++static NSURL *redirectURL = nil; ++ + static void _initialize(void) { ++ NSString *url; ++ NSUserDefaults *ud; ++ ++ ud = [NSUserDefaults standardUserDefaults]; ++ + if (debugLookup == -1) { +- debugLookup = [[NSUserDefaults standardUserDefaults] +- boolForKey:@"SoDebugKeyLookup"] ? 1 : 0; ++ debugLookup = [ud boolForKey:@"SoDebugKeyLookup"] ? 1 : 0; + NSLog(@"Note(SoObject): SoDebugKeyLookup is enabled!"); + } + if (debugBaseURL == -1) { +- debugBaseURL = [[NSUserDefaults standardUserDefaults] +- boolForKey:@"SoDebugBaseURL"] ? 1 : 0; ++ debugBaseURL = [ud boolForKey:@"SoDebugBaseURL"] ? 1 : 0; + NSLog(@"Note(SoObject): SoDebugBaseURL is enabled!"); + } + if (useRelativeURLs == -1) { +- useRelativeURLs = [[NSUserDefaults standardUserDefaults] +- boolForKey:@"WOUseRelativeURLs"] ?1:0; ++ useRelativeURLs = [ud boolForKey:@"WOUseRelativeURLs"] ?1:0; + NSLog(@"Note(SoObject): relative base URLs are enabled."); + } ++ if (redirectInitted == -1) { ++ url = [ud stringForKey:@"WOApplicationRedirectURL"]; ++ if ([url length]) { ++ redirectURL = [[NSURL alloc] initWithString: url]; ++ } ++ redirectInitted = 1; ++ } + } + + /* classes */ +@@ -318,56 +330,61 @@ + + rq = [_ctx request]; + ms = [[NSMutableString alloc] initWithCapacity:128]; ++ ++ if (redirectURL) { ++ [ms appendString: [redirectURL absoluteString]]; ++ } ++ else { ++ if (!useRelativeURLs) { ++ port = [[rq headerForKey:@"x-webobjects-server-port"] intValue]; + +- if (!useRelativeURLs) { +- port = [[rq headerForKey:@"x-webobjects-server-port"] intValue]; +- +- /* this is actually a bug in Apache */ +- if (port == 0) { +- static BOOL didWarn = NO; +- if (!didWarn) { +- [self warnWithFormat:@"(%s:%i): got an empty port from Apache!", +- __PRETTY_FUNCTION__, __LINE__]; +- didWarn = YES; ++ /* this is actually a bug in Apache */ ++ if (port == 0) { ++ static BOOL didWarn = NO; ++ if (!didWarn) { ++ [self warnWithFormat:@"(%s:%i): got an empty port from Apache!", ++ __PRETTY_FUNCTION__, __LINE__]; ++ didWarn = YES; ++ } ++ port = 80; + } +- port = 80; +- } + +- if ((tmp = [rq headerForKey:@"host"]) != nil) { +- /* check whether we have a host header with port */ +- if ([tmp rangeOfString:@":"].length == 0) +- tmp = nil; +- } +- if (tmp != nil) { /* we have a host header with port */ +- isHTTPS = +- [[rq headerForKey:@"x-webobjects-server-url"] hasPrefix:@"https"]; +- [ms appendString:isHTTPS ? @"https://" : @"http://"]; +- [ms appendString:tmp]; +- } +- else if ((tmp = [rq headerForKey:@"x-webobjects-server-url"]) != nil) { +- /* sometimes the URL is just wrong! (suggests port 80) */ +- if ([tmp hasSuffix:@":0"] && [tmp length] > 2) { // TODO: bad bad bad +- [self warnWithFormat:@"%s: got incorrect URL from Apache: '%@'", +- __PRETTY_FUNCTION__, tmp]; +- tmp = [tmp substringToIndex:([tmp length] - 2)]; ++ if ((tmp = [rq headerForKey:@"host"]) != nil) { ++ /* check whether we have a host header with port */ ++ if ([tmp rangeOfString:@":"].length == 0) ++ tmp = nil; + } +- else if ([tmp hasSuffix:@":443"] && [tmp hasPrefix:@"http://"]) { +- /* see OGo bug #1435, Debian Apache hack */ +- [self warnWithFormat:@"%s: got 'http' protocol but 443 port, " +- @"assuming Debian/Apache bug (OGo #1435): '%@'", +- __PRETTY_FUNCTION__, tmp]; +- tmp = [tmp substringWithRange:NSMakeRange(4, [tmp length] - 4 - 4)]; +- tmp = [@"https" stringByAppendingString:tmp]; ++ if (tmp != nil) { /* we have a host header with port */ ++ isHTTPS = ++ [[rq headerForKey:@"x-webobjects-server-url"] hasPrefix:@"https"]; ++ [ms appendString:isHTTPS ? @"https://" : @"http://"]; ++ [ms appendString:tmp]; + } +- [ms appendString:tmp]; +- } +- else { +- // TODO: isHTTPS always no in this case? +- [ms appendString:isHTTPS ? @"https://" : @"http://"]; ++ else if ((tmp = [rq headerForKey:@"x-webobjects-server-url"]) != nil) { ++ /* sometimes the URL is just wrong! (suggests port 80) */ ++ if ([tmp hasSuffix:@":0"] && [tmp length] > 2) { // TODO: bad bad bad ++ [self warnWithFormat:@"%s: got incorrect URL from Apache: '%@'", ++ __PRETTY_FUNCTION__, tmp]; ++ tmp = [tmp substringToIndex:([tmp length] - 2)]; ++ } ++ else if ([tmp hasSuffix:@":443"] && [tmp hasPrefix:@"http://"]) { ++ /* see OGo bug #1435, Debian Apache hack */ ++ [self warnWithFormat:@"%s: got 'http' protocol but 443 port, " ++ @"assuming Debian/Apache bug (OGo #1435): '%@'", ++ __PRETTY_FUNCTION__, tmp]; ++ tmp = [tmp substringWithRange:NSMakeRange(4, [tmp length] - 4 - 4)]; ++ tmp = [@"https" stringByAppendingString:tmp]; ++ } ++ [ms appendString:tmp]; ++ } ++ else { ++ // TODO: isHTTPS always no in this case? ++ [ms appendString:isHTTPS ? @"https://" : @"http://"]; + +- [ms appendString:[rq headerForKey:@"x-webobjects-server-name"]]; +- if ((isHTTPS ? (port != 443) : (port != 80)) && port != 0) +- [ms appendFormat:@":%i", port]; ++ [ms appendString:[rq headerForKey:@"x-webobjects-server-name"]]; ++ if ((isHTTPS ? (port != 443) : (port != 80)) && port != 0) ++ [ms appendFormat:@":%i", port]; ++ } + } + } + +Index: sope-appserver/NGObjWeb/WOHttpAdaptor/WOHttpTransaction.m +=================================================================== +--- sope-appserver/NGObjWeb/WOHttpAdaptor/WOHttpTransaction.m (revision 1660) ++++ sope-appserver/NGObjWeb/WOHttpAdaptor/WOHttpTransaction.m (working copy) +@@ -696,7 +696,7 @@ + *(&out) = nil; + + [self _httpValidateResponse:_response]; +- ++ + out = [(NGCTextStream *)[NGCTextStream alloc] initWithSource:_out]; + + NS_DURING { +@@ -705,6 +705,7 @@ + id body; + BOOL doZip; + BOOL isok = YES; ++ int length; + + doZip = [_response shouldZipResponseToRequest:_request]; + +@@ -738,7 +739,11 @@ + + /* add content length header */ + +- snprintf((char *)buf, sizeof(buf), "%d", [body length]); ++ if ((length = [body length]) == 0 ++ && ![[_response headerForKey: @"content-type"] hasPrefix:@"text/plain"]) { ++ [_response setHeader:@"text/plain" forKey:@"content-type"]; ++ } ++ snprintf((char *)buf, sizeof(buf), "%d", length); + t1 = [[NSString alloc] initWithCString:(char *)buf]; + [_response setHeader:t1 forKey:@"content-length"]; + [t1 release]; t1 = nil; +@@ -766,7 +771,7 @@ + NSString *value; + + if (!hasConnectionHeader) { +- if ([fieldName caseInsensitiveCompare:@"connection"]==NSOrderedSame) ++ if ([fieldName isEqualToString:@"connection"]) + hasConnectionHeader = YES; + } + diff --git a/gnustep-libs/sope/sope-4.7_pre20080521.ebuild b/gnustep-libs/sope/sope-4.7_pre20090616.ebuild index 6a38b2b..a9da15d 100644 --- a/gnustep-libs/sope/sope-4.7_pre20080521.ebuild +++ b/gnustep-libs/sope/sope-4.7_pre20090616.ebuild @@ -1,12 +1,12 @@ -# Copyright 1999-2008 Gentoo Foundation +# Copyright 1999-2009 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ -EAPI=1 +EAPI=2 inherit gnustep-base apache-module -MY_PV="1621-200805211100" +MY_PV="1660-200906161500" DESCRIPTION="an extensive set of frameworks which form a complete Web application server environment" HOMEPAGE="http://sope.opengroupware.org/en/index.html" @@ -22,7 +22,8 @@ DEPEND="gnustep-base/gnustep-base net-nds/openldap mysql? ( virtual/mysql ) postgres? ( virtual/postgresql-base ) - sqlite? ( >=dev-db/sqlite-3 )" + sqlite? ( >=dev-db/sqlite-3 ) + !gnustep-libs/gdl2" RDEPEND="${DEPEND}" APACHE2_MOD_DEFINE="SOPE" @@ -31,23 +32,29 @@ need_apache2 S=${WORKDIR}/${PN} -src_unpack() { - gnustep-base_src_unpack +src_prepare() { + gnustep-base_src_prepare - # Fix for recent gnustep-base - epatch "${FILESDIR}"/${PN}-nsexception.patch # Install in System instead of Local epatch "${FILESDIR}"/${PN}-use_system_root.patch # From SOGo project epatch "${FILESDIR}"/${PN}-gsmake2.diff - epatch "${FILESDIR}"/${PN}-mime-nosort.diff - epatch "${FILESDIR}"/${PN}-patchset-r1621.diff + epatch "${FILESDIR}"/${PN}-patchset-r1660.diff + + # Missing -lcrypt + sed -e "s/-lXmlRpc -lDOM -lSaxObjC/\0 -lcrypt/" \ + -i sope-appserver/SoOFS/GNUmakefile.preamble \ + || die "crypt sed failed" } -src_compile() { - # Do not use standard src_compile, as ./configure is not standard +src_configure() { + # Do not use standard src_configure, as ./configure is not standard egnustep_env ./configure --with-gnustep || die "configure failed" +} + +src_compile() { + egnustep_env egnustep_make apxs=/usr/sbin/apxs apr=/usr/bin/apr-1-config } diff --git a/metadata/cache/gnustep-apps/sogo-1.0_rc6 b/metadata/cache/gnustep-apps/sogo-1.0_rc6 deleted file mode 100644 index 8acf5d1..0000000 --- a/metadata/cache/gnustep-apps/sogo-1.0_rc6 +++ /dev/null @@ -1,22 +0,0 @@ -gnustep-libs/sope =www-servers/apache-2* -gnustep-libs/sope dev-db/postgresql =www-servers/apache-2* -0 -http://www.inverse.ca/downloads/SOGo/Sources/SOGo-1.0rc6.1.tar.gz - -http://sogo.opengroupware.org/ -GPL-2 -groupware server built around OpenGroupware.org and the SOPE application server -~x86 -depend.apache eutils flag-o-matic gnustep-base multilib portability toolchain-funcs -debug doc - - - - - -compile install postinst preinst setup unpack - - - - - diff --git a/metadata/cache/gnustep-apps/sogo-1.0_rc7 b/metadata/cache/gnustep-apps/sogo-1.0_rc7 deleted file mode 100644 index 5af511f..0000000 --- a/metadata/cache/gnustep-apps/sogo-1.0_rc7 +++ /dev/null @@ -1,22 +0,0 @@ -gnustep-libs/sope =www-servers/apache-2* -gnustep-libs/sope dev-db/postgresql =www-servers/apache-2* -0 -http://www.inverse.ca/downloads/SOGo/Sources/SOGo-1.0rc7.tar.gz - -http://sogo.opengroupware.org/ -GPL-2 -groupware server built around OpenGroupware.org and the SOPE application server -~x86 -depend.apache eutils flag-o-matic gnustep-base multilib portability toolchain-funcs -debug doc - - - - - -compile install postinst preinst setup unpack - - - - - diff --git a/metadata/cache/gnustep-apps/sogo-1.0_rc8 b/metadata/cache/gnustep-apps/sogo-1.0_rc8 deleted file mode 100644 index 878a2d1..0000000 --- a/metadata/cache/gnustep-apps/sogo-1.0_rc8 +++ /dev/null @@ -1,22 +0,0 @@ -gnustep-libs/sope =www-servers/apache-2* -gnustep-libs/sope dev-db/postgresql =www-servers/apache-2* -0 -http://www.inverse.ca/downloads/SOGo/Sources/SOGo-1.0rc8.tar.gz - -http://sogo.opengroupware.org/ -GPL-2 -groupware server built around OpenGroupware.org and the SOPE application server -~x86 -depend.apache eutils flag-o-matic gnustep-base multilib portability toolchain-funcs -debug doc - - - - - -compile install postinst preinst setup unpack - - - - - diff --git a/metadata/cache/gnustep-apps/sogo-1.1.0 b/metadata/cache/gnustep-apps/sogo-1.1.0 new file mode 100644 index 0000000..8fadcc7 --- /dev/null +++ b/metadata/cache/gnustep-apps/sogo-1.1.0 @@ -0,0 +1,22 @@ +gnustep-libs/sope[postgres] =www-servers/apache-2* +gnustep-libs/sope[postgres] dev-db/postgresql =www-servers/apache-2* +0 +http://www.inverse.ca/downloads/SOGo/Sources/SOGo-1.1.0.tar.gz + +http://sogo.opengroupware.org/ +GPL-2 +groupware server built around OpenGroupware.org and the SOPE application server +~x86 +depend.apache eutils flag-o-matic gnustep-base multilib portability toolchain-funcs +debug doc + + + +2 + +compile configure install postinst preinst prepare setup + + + + + diff --git a/metadata/cache/gnustep-libs/sope-4.7_pre20080521 b/metadata/cache/gnustep-libs/sope-4.7_pre20090616 index aabaab4..5bde537 100644 --- a/metadata/cache/gnustep-libs/sope-4.7_pre20080521 +++ b/metadata/cache/gnustep-libs/sope-4.7_pre20090616 @@ -1,7 +1,7 @@ -gnustep-base/gnustep-base dev-libs/libxml2 net-nds/openldap mysql? ( virtual/mysql ) postgres? ( virtual/postgresql-base ) sqlite? ( >=dev-db/sqlite-3 ) =www-servers/apache-2* -gnustep-base/gnustep-base dev-libs/libxml2 net-nds/openldap mysql? ( virtual/mysql ) postgres? ( virtual/postgresql-base ) sqlite? ( >=dev-db/sqlite-3 ) =www-servers/apache-2* +gnustep-base/gnustep-base dev-libs/libxml2 net-nds/openldap mysql? ( virtual/mysql ) postgres? ( virtual/postgresql-base ) sqlite? ( >=dev-db/sqlite-3 ) !gnustep-libs/gdl2 =www-servers/apache-2* +gnustep-base/gnustep-base dev-libs/libxml2 net-nds/openldap mysql? ( virtual/mysql ) postgres? ( virtual/postgresql-base ) sqlite? ( >=dev-db/sqlite-3 ) !gnustep-libs/gdl2 =www-servers/apache-2* 0 -http://download.opengroupware.org/nightly/sources/trunk/sope-trunk-r1621-200805211100.tar.gz +http://download.opengroupware.org/nightly/sources/trunk/sope-trunk-r1660-200906161500.tar.gz http://sope.opengroupware.org/en/index.html LGPL-2 @@ -12,9 +12,9 @@ mysql +postgres sqlite debug doc -1 +2 -compile install postinst setup unpack +compile configure install postinst prepare setup |