From 155c70bba52166ba5844f2899ceea7a29687ddf8 Mon Sep 17 00:00:00 2001 From: Andrew McMillan Date: Thu, 3 May 2012 19:11:28 +1200 Subject: [PATCH] Changes to the way XML is created, and (to a lesser extent) parsed. --- inc/DAVPrincipal.php | 24 ++++++------- inc/DAVResource.php | 30 ++++++++-------- inc/caldav-PROPPATCH.php | 66 +++++++++++++++++------------------ inc/caldav-REPORT-cardquery.php | 6 ++-- inc/caldav-REPORT-expand-property.php | 9 ++--- inc/caldav-REPORT-multiget.php | 6 ++-- inc/caldav-REPORT.php | 57 +++++++++++++++--------------- 7 files changed, 97 insertions(+), 101 deletions(-) diff --git a/inc/DAVPrincipal.php b/inc/DAVPrincipal.php index 0b64cf8e..d601c420 100644 --- a/inc/DAVPrincipal.php +++ b/inc/DAVPrincipal.php @@ -452,43 +452,43 @@ class DAVPrincipal extends Principal dbg_error_log('principal',': RenderAsXML: Principal Property "%s"', $tag ); switch( $tag ) { case 'DAV::getcontenttype': - $prop->NewElement('getcontenttype', 'httpd/unix-directory' ); + $reply->DAVElement( $prop, 'getcontenttype', 'httpd/unix-directory' ); break; case 'DAV::resourcetype': - $prop->NewElement('resourcetype', array( new XMLElement('principal'), new XMLElement('collection')) ); + $reply->DAVElement( $prop, 'resourcetype', array( new XMLElement('principal'), new XMLElement('collection')) ); break; case 'DAV::displayname': - $prop->NewElement('displayname', $this->fullname ); + $reply->DAVElement( $prop, 'displayname', $this->fullname ); break; case 'DAV::principal-URL': - $prop->NewElement('principal-URL', $reply->href($this->url()) ); + $reply->DAVElement( $prop, 'principal-URL', $reply->href($this->url()) ); break; case 'DAV::getlastmodified': - $prop->NewElement('getlastmodified', ISODateToHTTPDate($this->modified) ); + $reply->DAVElement( $prop, 'getlastmodified', ISODateToHTTPDate($this->modified) ); break; case 'DAV::creationdate': - $prop->NewElement('creationdate', DateToISODate($this->created) ); + $reply->DAVElement( $prop, 'creationdate', DateToISODate($this->created) ); break; case 'DAV::getcontentlanguage': /** Use the principal's locale by preference, otherwise system default */ $locale = (isset($c->current_locale) ? $c->current_locale : ''); if ( isset($this->locale) && $this->locale != '' ) $locale = $this->locale; - $prop->NewElement('getcontentlanguage', $locale ); + $reply->DAVElement( $prop, 'getcontentlanguage', $locale ); break; case 'DAV::group-member-set': if ( ! $this->_is_group ) return false; - $prop->NewElement('group-member-set', $reply->href($this->group_member_set) ); + $reply->DAVElement( $prop, 'group-member-set', $reply->href($this->group_member_set) ); break; case 'DAV::group-membership': - $prop->NewElement('group-membership', $reply->href($this->GroupMembership()) ); + $reply->DAVElement( $prop, 'group-membership', $reply->href($this->GroupMembership()) ); break; case 'urn:ietf:params:xml:ns:caldav:schedule-inbox-URL': @@ -518,11 +518,11 @@ class DAVPrincipal extends Principal break; case 'urn:ietf:params:xml:ns:carddav:addressbook-home-set': - $reply->NSElement($prop, $tag, $reply->href( $this->addressbook_home_set() ) ); + $reply->CardDAVElement($prop, $tag, $reply->href( $this->addressbook_home_set() ) ); break; case 'urn:ietf:params:xml:ns:caldav:calendar-home-set': - $reply->NSElement($prop, $tag, $reply->href( $this->calendar_home_set() ) ); + $reply->CalDAVElement($prop, $tag, $reply->href( $this->calendar_home_set() ) ); break; case 'urn:ietf:params:xml:ns:caldav:calendar-free-busy-set': @@ -540,7 +540,7 @@ class DAVPrincipal extends Principal // Empty tag responses. case 'DAV::alternate-URI-set': - $prop->NewElement( $reply->Tag($tag)); + $reply->DAVElement( $prop, $reply->Tag($tag)); break; case 'SOME-DENIED-PROPERTY': /** @todo indicating the style for future expansion */ diff --git a/inc/DAVResource.php b/inc/DAVResource.php index aabbcd36..40233426 100644 --- a/inc/DAVResource.php +++ b/inc/DAVResource.php @@ -1488,7 +1488,7 @@ EOQRY; global $c, $session, $request; // dbg_error_log( 'DAVResource', 'Processing "%s" on "%s".', $tag, $this->dav_name ); - + if ( $reply === null ) $reply = $GLOBALS['reply']; switch( $tag ) { @@ -1799,13 +1799,13 @@ EOQRY; dbg_error_log('DAVResource',':GetPropStat: propstat for href "%s"', $this->dav_name ); - $prop = new XMLElement('prop'); + $prop = new XMLElement('prop', null, null, 'DAV:'); $denied = array(); $not_found = array(); foreach( $properties AS $k => $tag ) { if ( is_object($tag) ) { dbg_error_log( 'DAVResource', ':GetPropStat: "$properties" should be an array of text. Assuming this object is an XMLElement!.' ); - $tag = $tag->GetTag(); + $tag = $tag->GetNSTag(); } $found = $this->ResourceProperty($tag, $prop, $reply, $denied ); if ( !$found ) { @@ -1814,31 +1814,31 @@ EOQRY; } if ( ! $found ) { // dbg_error_log( 'DAVResource', 'Request for unsupported property "%s" of resource "%s".', $tag, $this->dav_name ); - $not_found[] = $reply->Tag($tag); + $not_found[] = $tag; } } if ( $props_only ) return $prop; - $status = new XMLElement('status', 'HTTP/1.1 200 OK' ); + $status = new XMLElement('status', 'HTTP/1.1 200 OK', null, 'DAV:' ); - $elements = array( new XMLElement( 'propstat', array($prop,$status) ) ); + $elements = array( new XMLElement( 'propstat', array($prop,$status), null, 'DAV:' ) ); if ( count($denied) > 0 ) { - $status = new XMLElement('status', 'HTTP/1.1 403 Forbidden' ); - $noprop = new XMLElement('prop'); + $status = new XMLElement('status', 'HTTP/1.1 403 Forbidden', null, 'DAV:' ); + $noprop = new XMLElement('prop', null, null, 'DAV:'); foreach( $denied AS $k => $v ) { $reply->NSElement($noprop, $v); } - $elements[] = new XMLElement( 'propstat', array( $noprop, $status) ); + $elements[] = new XMLElement( 'propstat', array( $noprop, $status), null, 'DAV:' ); } - if ( !(isset($request->brief_response) && $request->brief_response) && count($not_found) > 0 ) { - $status = new XMLElement('status', 'HTTP/1.1 404 Not Found' ); - $noprop = new XMLElement('prop'); + if ( !$request->PreferMinimal() && count($not_found) > 0 ) { + $status = new XMLElement('status', 'HTTP/1.1 404 Not Found', null, 'DAV:' ); + $noprop = new XMLElement('prop', null, null, 'DAV:'); foreach( $not_found AS $k => $v ) { - $noprop->NewElement($v); + $reply->NSElement($noprop,$v); } - $elements[] = new XMLElement( 'propstat', array( $noprop, $status) ); + $elements[] = new XMLElement( 'propstat', array( $noprop, $status), null, 'DAV:' ); } return $elements; } @@ -1869,7 +1869,7 @@ EOQRY; array_unshift( $elements, $reply->href(ConstructURL($dav_name))); - $response = new XMLElement( 'response', $elements ); + $response = new XMLElement( 'response', $elements, null, 'DAV:' ); return $response; } diff --git a/inc/caldav-PROPPATCH.php b/inc/caldav-PROPPATCH.php index d52263e9..a6ddb5de 100644 --- a/inc/caldav-PROPPATCH.php +++ b/inc/caldav-PROPPATCH.php @@ -26,7 +26,7 @@ $xmltree = BuildXMLTree( $request->xml_tags, $position); // echo $xmltree->Render(); -if ( $xmltree->GetTag() != "DAV::propertyupdate" ) { +if ( $xmltree->GetNSTag() != "DAV::propertyupdate" ) { $request->PreconditionFailed( 403, 'DAV::propertyupdate', 'XML request did not contain a <propertyupdate> tag' ); } @@ -45,6 +45,7 @@ $rmprops = $xmltree->GetPath("/DAV::propertyupdate/DAV::remove/DAV::prop/*"); $failure = array(); $success = array(); +$reply = new XMLDocument( array( 'DAV:' => '') ); /** * Small utility function to add propstat for one failure @@ -54,11 +55,10 @@ $success = array(); * @param unknown_type $error_tag */ function add_failure( $type, $tag, $status, $description=null, $error_tag = null) { - global $failure; - $propstat = array( - new XMLElement( 'prop', new XMLElement($tag)), - new XMLElement( 'status', $status ) - ); + global $failure, $reply; + $prop = new XMLElement('prop'); + $reply->NSElement($prop, $tag); + $propstat = array($prop,new XMLElement( 'status', $status )); if ( isset($description)) $propstat[] = new XMLElement( 'responsedescription', $description ); @@ -78,7 +78,7 @@ $qry = new AwlQuery(); $qry->Begin(); $setcalendar = count($xmltree->GetPath('/DAV::propertyupdate/DAV::set/DAV::prop/DAV::resourcetype/urn:ietf:params:xml:ns:caldav:calendar')); foreach( $setprops AS $k => $setting ) { - $tag = $setting->GetTag(); + $tag = $setting->GetNSTag(); $content = $setting->RenderContent(); switch( $tag ) { @@ -134,7 +134,7 @@ foreach( $setprops AS $k => $setting ) { case 'urn:ietf:params:xml:ns:caldav:schedule-calendar-transp': if ( $dav_resource->IsCollection() && ( $dav_resource->IsCalendar() || $setcalendar ) && !$dav_resource->IsBinding() ) { $transparency = $setting->GetPath('urn:ietf:params:xml:ns:caldav:schedule-calendar-transp/*'); - $transparency = preg_replace( '{^.*:}', '', $transparency[0]->GetTag()); + $transparency = preg_replace( '{^.*:}', '', $transparency[0]->GetNSTag()); $qry->QDo('UPDATE collection SET schedule_transp = :transparency WHERE dav_name = :dav_name', array( ':dav_name' => $dav_resource->dav_name(), ':transparency' => $transparency ) ); $success[$tag] = 1; @@ -206,7 +206,7 @@ foreach( $setprops AS $k => $setting ) { } foreach( $rmprops AS $k => $setting ) { - $tag = $setting->GetTag(); + $tag = $setting->GetNSTag(); $content = $setting->RenderContent(); switch( $tag ) { @@ -266,20 +266,20 @@ if ( count($failure) > 0 ) { $qry->Rollback(); - foreach( $success AS $tag => $v ) { - // Unfortunately although these succeeded, we failed overall, so they didn't happen... - $failure[] = new XMLElement( 'propstat', array( - new XMLElement( 'prop', new XMLElement($tag)), - new XMLElement( 'status', 'HTTP/1.1 424 Failed Dependency' ), - )); - } - $url = ConstructURL($request->path); - array_unshift( $failure, new XMLElement('href', $url ) ); - $failure[] = new XMLElement('responsedescription', translate("Some properties were not able to be changed.") ); - - $multistatus = new XMLElement( "multistatus", new XMLElement( 'response', $failure ), array('xmlns'=>'DAV:') ); - $request->DoResponse( 207, $multistatus->Render(0,''), 'text/xml; charset="utf-8"' ); + $multistatus = new XMLElement('multistatus'); + array_unshift($failure,new XMLElement('responsedescription', translate("Some properties were not able to be changed.") )); + array_unshift($failure,new XMLElement('href', $url)); + $response = $reply->DAVElement($multistatus,'response', $failure); + + if ( !empty($success) ) { + $prop = new XMLElement('prop'); + foreach( $success AS $tag => $v ) { + $reply->NSElement($prop, $tag); + } + $reply->DAVElement($response, 'propstat', array( $prop, new XMLElement( 'status', 'HTTP/1.1 424 Failed Dependency' )) ); + } + $request->DoResponse( 207, $reply->Render($multistatus), 'text/xml; charset="utf-8"' ); } @@ -300,27 +300,25 @@ if ( $qry->Commit() ) { if ( isset($cache_ns) ) $cache->delete( $cache_ns, null ); - if ( $request->brief_response ) { - $request->DoResponse(200); // Does not return. See: http://msdn.microsoft.com/en-us/library/aa142976%28v=exchg.65%29.aspx + if ( $request->PreferMinimal() ) { + $request->DoResponse(200); // Does not return. } - + $url = ConstructURL($request->path); - $href = new XMLElement('href', $url ); - $desc = new XMLElement('responsedescription', translate("All requested changes were made.") ); + $multistatus = new XMLElement('multistatus'); + $reply->DAVElement($multistatus,'href', $url); + $reply->DAVElement($multistatus,'responsedescription', translate("All requested changes were made.") ); - $propstat = array(); + $prop = new XMLElement('prop'); foreach( $success AS $tag => $v ) { - $propstat[] = new XMLElement( 'propstat', array( - new XMLElement( 'prop', new XMLElement($tag)), - new XMLElement( 'status', 'HTTP/1.1 200 OK' ), - )); + $reply->NSElement($prop, $tag); } + $reply->DAVElement($multistatus, 'propstat', array( $prop, new XMLElement( 'status', 'HTTP/1.1 200 OK' )) ); $url = ConstructURL($request->path); array_unshift( $failure, new XMLElement('href', $url ) ); - $multistatus = new XMLElement( "multistatus", new XMLElement( 'response', array( $href, $propstat, $desc ) ), array('xmlns'=>'DAV:') ); - $request->DoResponse( 207, $multistatus->Render(0,''), 'text/xml; charset="utf-8"' ); + $request->DoResponse( 207, $reply->Render($multistatus), 'text/xml; charset="utf-8"' ); } /** diff --git a/inc/caldav-REPORT-cardquery.php b/inc/caldav-REPORT-cardquery.php index 319e6f7c..0aefbe62 100644 --- a/inc/caldav-REPORT-cardquery.php +++ b/inc/caldav-REPORT-cardquery.php @@ -23,8 +23,7 @@ switch( $proptype ) { case 'DAV::prop': $qry_props = $xmltree->GetPath('/urn:ietf:params:xml:ns:carddav:addressbook-query/'.$proptype.'/*'); foreach( $qry_content[0]->GetElements() AS $k => $v ) { - $propertyname = preg_replace( '/^.*:/', '', $v->GetNSTag() ); - $properties[$propertyname] = 1; + $properties[$v->GetNSTag()] = 1; if ( $v->GetNSTag() == 'urn:ietf:params:xml:ns:carddav:address-data' ) get_address_properties($v); } break; @@ -40,8 +39,7 @@ switch( $proptype ) { break; default: - $propertyname = preg_replace( '/^.*:/', '', $proptype ); - $properties[$propertyname] = 1; + $properties[$proptype] = 1; } /** diff --git a/inc/caldav-REPORT-expand-property.php b/inc/caldav-REPORT-expand-property.php index 53d50e46..5a16df4b 100644 --- a/inc/caldav-REPORT-expand-property.php +++ b/inc/caldav-REPORT-expand-property.php @@ -53,9 +53,10 @@ function expand_properties( $urls, $ptree, &$reply, $recurse_again = true ) { foreach( $ptree AS $n => $property ) { if ( ! is_object($property) ) continue; $pname = $property->GetAttribute('name'); - $pns = $property->GetNamespace('namespace'); - if ( !isset($pns) || $pns == '' ) $pns = $property->GetNameSpace(); - $pname = $pns .':'. $pname; + $pns = $property->GetAttribute('namespace'); + if ( empty($pns) ) $pns = $property->GetAttribute('xmlns'); + if ( empty($pns) ) $pns = $reply->DefaultNamespace(); + $pname = (empty($pns)?'':$pns .':'). $pname; $props[] = $pname; $subtrees[$pname] = $property->GetElements(); } @@ -72,7 +73,7 @@ function expand_properties( $urls, $ptree, &$reply, $recurse_again = true ) { $content = $v->GetContent(); $paths[] = $content; } -// dbg_error_log('REPORT',' Found property "%s" contains hrefs "%s"', $pname, implode(', ',$paths) ); + // dbg_error_log('REPORT',' Found property "%s" contains hrefs "%s"', $pname, implode(', ',$paths) ); $property->SetContent( expand_properties($paths, $subtrees[$pname], $reply, false) ); } } diff --git a/inc/caldav-REPORT-multiget.php b/inc/caldav-REPORT-multiget.php index f93d51a0..18face2c 100644 --- a/inc/caldav-REPORT-multiget.php +++ b/inc/caldav-REPORT-multiget.php @@ -32,8 +32,7 @@ switch( $proptype ) { case 'DAV::prop': $qry_props = $xmltree->GetPath('/*/'.$proptype.'/*'); foreach( $qry_content[0]->GetElements() AS $k => $v ) { - $propertyname = preg_replace( '/^.*:/', '', $v->GetNSTag() ); - $properties[$propertyname] = 1; + $properties[$v->GetNSTag()] = 1; if ( $v->GetNSTag() == 'urn:ietf:params:xml:ns:caldav:calendar-data' ) check_for_expansion($v); } break; @@ -49,8 +48,7 @@ switch( $proptype ) { break; default: - $propertyname = preg_replace( '/^.*:/', '', $proptype ); - $properties[$propertyname] = 1; + $properties[$proptype] = 1; } $collection = new DAVResource($request->path); diff --git a/inc/caldav-REPORT.php b/inc/caldav-REPORT.php index f7dd4891..3b15ceec 100644 --- a/inc/caldav-REPORT.php +++ b/inc/caldav-REPORT.php @@ -142,47 +142,48 @@ function component_to_xml( $properties, $item ) { $url = ConstructURL($item->dav_name); $prop = new XMLElement("prop"); - foreach( $properties AS $k => $v ) { - switch( $k ) { - case 'getcontentlength': + foreach( $properties AS $full_tag => $v ) { + $base_tag = preg_replace('{^.*:}', '', $full_tag ); + switch( $full_tag ) { + case 'DAV::getcontentlength': $contentlength = strlen($caldav_data); - $prop->NewElement($k, $contentlength ); + $prop->NewElement($base_tag, $contentlength ); break; - case 'getlastmodified': - $prop->NewElement($k, ISODateToHTTPDate($item->modified) ); + case 'DAV::getlastmodified': + $prop->NewElement($base_tag, ISODateToHTTPDate($item->modified) ); break; - case 'calendar-data': - if ( $type == 'calendar' ) $reply->CalDAVElement($prop, $k, $caldav_data ); - else $unsupported[] = $k; + case 'urn:ietf:params:xml:ns:caldav:calendar-data': + if ( $type == 'calendar' ) $reply->CalDAVElement($prop, $base_tag, $caldav_data ); + else $unsupported[] = $base_tag; break; - case 'address-data': - if ( $type == 'vcard' ) $reply->CardDAVElement($prop, $k, $caldav_data ); - else $unsupported[] = $k; + case 'urn:ietf:params:xml:ns:carddav:address-data': + if ( $type == 'vcard' ) $reply->CardDAVElement($prop, $base_tag, $caldav_data ); + else $unsupported[] = $base_tag; break; - case 'getcontenttype': - $prop->NewElement($k, $contenttype ); + case 'DAV::getcontenttype': + $prop->NewElement($base_tag, $contenttype ); break; - case 'current-user-principal': + case 'DAV::current-user-principal': $prop->NewElement("current-user-principal", $request->current_user_principal_xml); break; - case 'displayname': - $prop->NewElement($k, $displayname ); + case 'DAV::displayname': + $prop->NewElement($base_tag, $displayname ); break; - case 'resourcetype': - $prop->NewElement($k); // Just an empty resourcetype for a non-collection. + case 'DAV::resourcetype': + $prop->NewElement($base_tag); // Just an empty resourcetype for a non-collection. break; - case 'getetag': - $prop->NewElement($k, '"'.$item->dav_etag.'"' ); + case 'DAV::getetag': + $prop->NewElement($base_tag, '"'.$item->dav_etag.'"' ); break; case '"current-user-privilege-set"': - $prop->NewElement($k, privileges($request->permissions) ); + $prop->NewElement($base_tag, privileges($request->permissions) ); break; case 'SOME-DENIED-PROPERTY': /** indicating the style for future expansion */ - $denied[] = $k; + $denied[] = $full_tag; break; default: - dbg_error_log( 'REPORT', "Request for unsupported property '%s' of calendar item.", $v ); - $unsupported[] = $k; + dbg_error_log( 'REPORT', "Request for unsupported property '%s' of calendar item.", $full_tag ); + $unsupported[] = $full_tag; } } $status = new XMLElement("status", "HTTP/1.1 200 OK" ); @@ -195,16 +196,16 @@ function component_to_xml( $properties, $item ) { $status = new XMLElement("status", "HTTP/1.1 403 Forbidden" ); $noprop = new XMLElement("prop"); foreach( $denied AS $k => $v ) { - $noprop->NewElement( strtolower($v) ); + $reply->NSElement($noprop, $v); } $elements[] = new XMLElement( "propstat", array( $noprop, $status) ); } - if ( !(isset($request->brief_response) && $request->brief_response) && count($unsupported) > 0 ) { + if ( ! $request->PreferMinimal() && count($unsupported) > 0 ) { $status = new XMLElement("status", "HTTP/1.1 404 Not Found" ); $noprop = new XMLElement("prop"); foreach( $unsupported AS $k => $v ) { - $noprop->NewElement( strtolower($v) ); + $reply->NSElement($noprop, $v); } $elements[] = new XMLElement( "propstat", array( $noprop, $status) ); } -- 2.11.4.GIT