From f3abad7fad2ce3934e76de2467ab30e1a24afe1a Mon Sep 17 00:00:00 2001 From: Hadrien Blanc Date: Thu, 8 Oct 2026 14:12:12 +0200 Subject: [PATCH] fix(contacts): emit vCard 3.0 photo parameters for CardDAV clients (bug 5134) setPhoto wrote ENCODING=BASE64, the vCard 2.1 spelling, inside cards announced as VERSION:3.0. Strict CardDAV parsers such as Apple Contacts drop the property, so LDAP directory photos (jpegPhoto) never displayed on those clients. Emit TYPE=JPEG;ENCODING=b as of RFC 2426. The parser already accepts both encodings, and legacy ENCODING=BASE64 cards keep decoding. https://bugs.sogo.nu/view.php?id=5134 --- SOPE/NGCards/NGVCard.m | 4 +- SOPE/NGCards/Tests/GNUmakefile | 20 ++++++++ SOPE/NGCards/Tests/TestNGVCardPhoto.m | 73 +++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 SOPE/NGCards/Tests/GNUmakefile create mode 100644 SOPE/NGCards/Tests/TestNGVCardPhoto.m diff --git a/SOPE/NGCards/NGVCard.m b/SOPE/NGCards/NGVCard.m index 48cc9d9a7..ab8c94104 100644 --- a/SOPE/NGCards/NGVCard.m +++ b/SOPE/NGCards/NGVCard.m @@ -296,8 +296,10 @@ - (void) setPhoto: (NSString *) _value { CardElement *photo; + photo = [self uniqueChildWithTag: @"photo"]; - [photo setValue: 0 ofAttribute: @"encoding" to: @"BASE64"]; + [photo setValue: 0 ofAttribute: @"type" to: @"JPEG"]; + [photo setValue: 0 ofAttribute: @"encoding" to: @"b"]; [photo setSingleValue: _value forKey: @""]; } diff --git a/SOPE/NGCards/Tests/GNUmakefile b/SOPE/NGCards/Tests/GNUmakefile new file mode 100644 index 000000000..665e00024 --- /dev/null +++ b/SOPE/NGCards/Tests/GNUmakefile @@ -0,0 +1,20 @@ +# GNUstep makefile + +include ../../../config.make +include $(GNUSTEP_MAKEFILES)/common.make + +TEST_TOOL = ngcards-tests +$(TEST_TOOL)_OBJC_FILES = \ + TestNGVCardPhoto.m + +TEST_TOOL_NAME = $(TEST_TOOL) + +$(TEST_TOOL)_CPPFLAGS += \ + -Wall -D_GNU_SOURCE -I.. + +ADDITIONAL_LIB_DIRS += \ + -L../obj -lNGCards \ + -lNGExtensions -lSaxObjC -lNGStreams -lDOM -lEOControl -lobjc \ + -Wl,-rpath,../obj + +include $(GNUSTEP_MAKEFILES)/test-tool.make diff --git a/SOPE/NGCards/Tests/TestNGVCardPhoto.m b/SOPE/NGCards/Tests/TestNGVCardPhoto.m new file mode 100644 index 000000000..c0126c667 --- /dev/null +++ b/SOPE/NGCards/Tests/TestNGVCardPhoto.m @@ -0,0 +1,73 @@ +/* TestNGVCardPhoto.m - this file is part of SOGo + * + * Copyright (C) 2026 Inverse inc. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +#include "NGVCard.h" + +static int +Check (int condition, const char *message) +{ + if (!condition) + { + printf ("FAIL: %s\n", message); + return 1; + } + + return 0; +} + +int +main (void) +{ + NSAutoreleasePool *pool; + NGVCard *card; + NSString *versit; + int failures = 0; + + pool = [[NSAutoreleasePool alloc] init]; + + card = [NGVCard cardWithUid: @"photo-test"]; + [card setPhoto: @"QUJDRA=="]; + + versit = [card versitString]; + failures += Check ([versit rangeOfString: @"ENCODING=b"].location + != NSNotFound, + "photo must use the vCard 3.0 ENCODING=b value"); + failures += Check ([versit rangeOfString: @"TYPE=JPEG"].location + != NSNotFound, + "photo must declare its TYPE"); + failures += Check ([versit rangeOfString: @"ENCODING=BASE64"].location + == NSNotFound, + "the 2.1 ENCODING=BASE64 spelling must not be emitted"); + failures += Check ([versit rangeOfString: @"QUJDRA=="].location + != NSNotFound, + "photo value must be preserved"); + + [pool release]; + + if (failures) + printf ("%d failure(s)\n", failures); + else + printf ("all tests passed\n"); + + return failures ? 1 : 0; +}