/** Process a 207 Multi-status response as defined in RFC 4918 "13. Multi-Status Response" */ protected void processMultiStatus(HttpResponse response) throws IOException, HttpException, DavException { if (response.getStatusLine().getStatusCode() != HttpStatus.SC_MULTI_STATUS) throw new DavNoMultiStatusException(); HttpEntity entity = response.getEntity(); if (entity == null) throw new DavNoContentException(); @Cleanup InputStream content = entity.getContent(); DavMultistatus multiStatus; try { Serializer serializer = new Persister(); multiStatus = serializer.read(DavMultistatus.class, content, false); } catch (Exception ex) { throw new DavException("Couldn't parse Multi-Status response on REPORT multi-get", ex); } if (multiStatus.response == null) // empty response return; // member list will be built from response List<WebDavResource> members = new LinkedList<>(); // iterate through all resources (either ourselves or member) for (DavResponse singleResponse : multiStatus.response) { URI href; try { href = location.resolve(URIUtils.parseURI(singleResponse.href.href, false)); } catch (Exception ex) { Log.w(TAG, "Ignoring illegal member URI in multi-status response", ex); continue; } Log.d(TAG, "Processing multi-status element: " + href); // process known properties HashMap<Property, String> properties = new HashMap<>(); List<String> supportedComponents = null; byte[] data = null; // in <response>, either <status> or <propstat> must be present if (singleResponse.status != null) { // method 1 (status of resource as a whole) StatusLine status = BasicLineParserHC4.parseStatusLine(singleResponse.status, new BasicLineParserHC4()); checkResponse(status); } else for (DavPropstat singlePropstat : singleResponse.propstat) { // method 2 (propstat) StatusLine status = BasicLineParserHC4.parseStatusLine(singlePropstat.status, new BasicLineParserHC4()); // ignore information about missing properties etc. if (status.getStatusCode() / 100 != 1 && status.getStatusCode() / 100 != 2) continue; DavProp prop = singlePropstat.prop; if (prop.currentUserPrincipal != null && prop.currentUserPrincipal.getHref() != null) properties.put( Property.CURRENT_USER_PRINCIPAL, prop.currentUserPrincipal.getHref().href); if (prop.currentUserPrivilegeSet != null) { // privilege info available boolean mayAll = false, mayBind = false, mayUnbind = false, mayWrite = false, mayWriteContent = false; for (DavProp.Privilege privilege : prop.currentUserPrivilegeSet) { if (privilege.getAll() != null) mayAll = true; if (privilege.getBind() != null) mayBind = true; if (privilege.getUnbind() != null) mayUnbind = true; if (privilege.getWrite() != null) mayWrite = true; if (privilege.getWriteContent() != null) mayWriteContent = true; } if (!mayAll && !mayWrite && !(mayWriteContent && mayBind && mayUnbind)) properties.put(Property.READ_ONLY, "1"); } if (prop.addressbookHomeSet != null && prop.addressbookHomeSet.getHref() != null) properties.put( Property.ADDRESSBOOK_HOMESET, URIUtils.ensureTrailingSlash(prop.addressbookHomeSet.getHref().href)); if (prop.calendarHomeSet != null && prop.calendarHomeSet.getHref() != null) properties.put( Property.CALENDAR_HOMESET, URIUtils.ensureTrailingSlash(prop.calendarHomeSet.getHref().href)); if (prop.displayname != null) properties.put(Property.DISPLAY_NAME, prop.displayname.getDisplayName()); if (prop.resourcetype != null) { if (prop.resourcetype.getCollection() != null) { properties.put(Property.IS_COLLECTION, "1"); // is a collection, ensure trailing slash href = URIUtils.ensureTrailingSlash(href); } if (prop.resourcetype.getAddressbook() != null) { // CardDAV collection properties properties.put(Property.IS_ADDRESSBOOK, "1"); if (prop.addressbookDescription != null) properties.put(Property.DESCRIPTION, prop.addressbookDescription.getDescription()); if (prop.supportedAddressData != null) for (DavProp.AddressDataType dataType : prop.supportedAddressData) if ("text/vcard".equalsIgnoreCase(dataType.getContentType())) // ignore "3.0" as it MUST be supported anyway if ("4.0".equals(dataType.getVersion())) properties.put(Property.VCARD_VERSION, VCardVersion.V4_0.getVersion()); } if (prop.resourcetype.getCalendar() != null) { // CalDAV collection propertioes properties.put(Property.IS_CALENDAR, "1"); if (prop.calendarDescription != null) properties.put(Property.DESCRIPTION, prop.calendarDescription.getDescription()); if (prop.calendarColor != null) properties.put(Property.COLOR, prop.calendarColor.getColor()); if (prop.calendarTimezone != null) try { properties.put( Property.TIMEZONE, Event.TimezoneDefToTzId(prop.calendarTimezone.getTimezone())); } catch (IllegalArgumentException e) { } if (prop.supportedCalendarComponentSet != null) { supportedComponents = new LinkedList<>(); for (Comp component : prop.supportedCalendarComponentSet) supportedComponents.add(component.getName()); } } } if (prop.getctag != null) properties.put(Property.CTAG, prop.getctag.getCTag()); if (prop.getetag != null) properties.put(Property.ETAG, prop.getetag.getETag()); if (prop.calendarData != null && prop.calendarData.ical != null) data = prop.calendarData.ical.getBytes(); else if (prop.addressData != null && prop.addressData.vcard != null) data = prop.addressData.vcard.getBytes(); } // about which resource is this response? if (location.equals(href) || URIUtils.ensureTrailingSlash(location).equals(href)) { // about ourselves this.properties.putAll(properties); if (supportedComponents != null) this.supportedComponents = supportedComponents; this.content = data; } else { // about a member WebDavResource member = new WebDavResource(this, href); member.properties = properties; member.supportedComponents = supportedComponents; member.content = data; members.add(member); } } this.members = members; }
public XCardBuilder() { sb.append("<vcards xmlns=\"" + VCardVersion.V4_0.getXmlNamespace() + "\">"); begin(); }