@@ -68,6 +68,7 @@ public function getChildren(): array {
6868 /**
6969 * @param array $paths
7070 * @return Card[]
71+ * @throws NotFound
7172 */
7273 public function getMultipleChildren ($ paths ): array {
7374 if (!$ this ->isFederation ()) {
@@ -76,27 +77,16 @@ public function getMultipleChildren($paths): array {
7677
7778 $ objs = $ this ->carddavBackend ->getMultipleCards ($ this ->addressBookInfo ['id ' ], $ paths );
7879 $ children = [];
80+ /** @var array $obj */
7981 foreach ($ objs as $ obj ) {
80- $ obj ['acl ' ] = $ this ->getChildACL ();
81- $ cardData = $ obj ['carddata ' ];
82- /** @var VCard $vCard */
83- $ vCard = Reader::read ($ cardData );
84- foreach ($ vCard ->children () as $ child ) {
85- $ scope = $ child ->offsetGet ('X-NC-SCOPE ' );
86- if ($ scope !== null && $ scope ->getValue () === IAccountManager::SCOPE_LOCAL ) {
87- $ vCard ->remove ($ child );
88- }
82+ if (empty ($ obj )) {
83+ continue ;
8984 }
90- $ messages = $ vCard ->validate ();
91- if (!empty ($ messages )) {
92- // If the validation doesn't work the card is indeed "not found"
93- // even if it might exist in the local backend.
94- // This can happen when a user sets the required properties
95- // FN, N to a local scope only.
96- // @see https://github.com/nextcloud/server/issues/38042
85+ $ carddata = $ this ->extractCarddata ($ obj );
86+ if (empty ($ carddata )) {
9787 continue ;
9888 } else {
99- $ obj ['carddata ' ] = $ vCard -> serialize () ;
89+ $ obj ['carddata ' ] = $ carddata ;
10090 }
10191 $ children [] = new Card ($ this ->carddavBackend , $ this ->addressBookInfo , $ obj );
10292 }
@@ -118,26 +108,11 @@ public function getChild($name): Card {
118108 if (!$ obj ) {
119109 throw new NotFound ('Card not found ' );
120110 }
121- $ obj ['acl ' ] = $ this ->getChildACL ();
122- $ cardData = $ obj ['carddata ' ];
123- /** @var VCard $vCard */
124- $ vCard = Reader::read ($ cardData );
125- foreach ($ vCard ->children () as $ child ) {
126- $ scope = $ child ->offsetGet ('X-NC-SCOPE ' );
127- if ($ scope !== null && $ scope ->getValue () === IAccountManager::SCOPE_LOCAL ) {
128- $ vCard ->remove ($ child );
129- }
130- }
131- $ messages = $ vCard ->validate ();
132- if (!empty ($ messages )) {
133- // If the validation doesn't work the card is indeed "forbidden"
134- // even if it might exist in the local backend.
135- // This can happen when a user sets the required properties
136- // FN, N to a local scope only.
137- // @see https://github.com/nextcloud/server/issues/38042
111+ $ carddata = $ this ->extractCarddata ($ obj );
112+ if (empty ($ carddata )) {
138113 throw new Forbidden ();
139114 } else {
140- $ obj ['carddata ' ] = $ vCard -> serialize () ;
115+ $ obj ['carddata ' ] = $ carddata ;
141116 }
142117 return new Card ($ this ->carddavBackend , $ this ->addressBookInfo , $ obj );
143118 }
@@ -222,4 +197,35 @@ private function isFederation(): bool {
222197
223198 return true ;
224199 }
200+
201+ /**
202+ * If the validation doesn't work the card is "not found" so we
203+ * return empty carddata even if the carddata might exist in the local backend.
204+ * This can happen when a user sets the required properties
205+ * FN, N to a local scope only but the request is from
206+ * a federated share.
207+ *
208+ * @see https://github.com/nextcloud/server/issues/38042
209+ *
210+ * @param array $obj
211+ * @return string|null
212+ */
213+ private function extractCarddata (array $ obj ): ?string {
214+ $ obj ['acl ' ] = $ this ->getChildACL ();
215+ $ cardData = $ obj ['carddata ' ];
216+ /** @var VCard $vCard */
217+ $ vCard = Reader::read ($ cardData );
218+ foreach ($ vCard ->children () as $ child ) {
219+ $ scope = $ child ->offsetGet ('X-NC-SCOPE ' );
220+ if ($ scope !== null && $ scope ->getValue () === IAccountManager::SCOPE_LOCAL ) {
221+ $ vCard ->remove ($ child );
222+ }
223+ }
224+ $ messages = $ vCard ->validate ();
225+ if (!empty ($ messages )) {
226+ return null ;
227+ }
228+
229+ return $ vCard ->serialize ();
230+ }
225231}
0 commit comments