Beispiel #1
0
/**
* Return XML for a single component from the DB
*
* @param array $properties The properties for this component
* @param string $item The DB row data for this component
*
* @return string An XML document which is the response for the component
*/
function component_to_xml($properties, $item)
{
    global $session, $c, $request, $reply;
    dbg_error_log("REPORT", "Building XML Response for item '%s'", $item->dav_name);
    $denied = array();
    $unsupported = array();
    $caldav_data = $item->caldav_data;
    $displayname = preg_replace('{^.*/}', '', $item->dav_name);
    $type = 'unknown';
    $contenttype = 'text/plain';
    switch ($item->caldav_type) {
        case 'VJOURNAL':
        case 'VEVENT':
        case 'VTODO':
            $displayname = $item->summary;
            $type = 'calendar';
            $contenttype = 'text/calendar';
            break;
        case 'VCARD':
            $displayname = $item->fn;
            $type = 'vcard';
            $contenttype = 'text/vcard';
            break;
    }
    if (isset($properties['calendar-data']) || isset($properties['displayname'])) {
        if (!$request->AllowedTo('all') && $session->user_no != $item->user_no) {
            // the user is not admin / owner of this calendarlooking at his calendar and can not admin the other cal
            /** @todo We should examine the ORGANIZER and ATTENDEE fields in the event.  If this person is there then they should see this */
            if ($type == 'calendar' && $item->class == 'CONFIDENTIAL' || !$request->AllowedTo('read')) {
                $ical = new iCalComponent($caldav_data);
                $resources = $ical->GetComponents('VTIMEZONE', false);
                $first = $resources[0];
                // if the event is confidential we fake one that just says "Busy"
                $confidential = new iCalComponent();
                $confidential->SetType($first->GetType());
                $confidential->AddProperty('SUMMARY', translate('Busy'));
                $confidential->AddProperty('CLASS', 'CONFIDENTIAL');
                $confidential->SetProperties($first->GetProperties('DTSTART'), 'DTSTART');
                $confidential->SetProperties($first->GetProperties('RRULE'), 'RRULE');
                $confidential->SetProperties($first->GetProperties('DURATION'), 'DURATION');
                $confidential->SetProperties($first->GetProperties('DTEND'), 'DTEND');
                $confidential->SetProperties($first->GetProperties('UID'), 'UID');
                $ical->SetComponents(array($confidential), $confidential->GetType());
                $caldav_data = $ical->Render();
                $displayname = translate('Busy');
            }
        }
    }
    $url = ConstructURL($item->dav_name);
    $prop = new XMLElement("prop");
    foreach ($properties as $k => $v) {
        switch ($k) {
            case 'getcontentlength':
                $contentlength = strlen($caldav_data);
                $prop->NewElement($k, $contentlength);
                break;
            case 'getlastmodified':
                $prop->NewElement($k, ISODateToHTTPDate($item->modified));
                break;
            case 'calendar-data':
                if ($type == 'calendar') {
                    $reply->CalDAVElement($prop, $k, $caldav_data);
                } else {
                    $unsupported[] = $k;
                }
                break;
            case 'address-data':
                if ($type == 'vcard') {
                    $reply->CardDAVElement($prop, $k, $caldav_data);
                } else {
                    $unsupported[] = $k;
                }
                break;
            case 'getcontenttype':
                $prop->NewElement($k, $contenttype);
                break;
            case 'current-user-principal':
                $prop->NewElement("current-user-principal", $request->current_user_principal_xml);
                break;
            case 'displayname':
                $prop->NewElement($k, $displayname);
                break;
            case 'resourcetype':
                $prop->NewElement($k);
                // Just an empty resourcetype for a non-collection.
                break;
            case 'getetag':
                $prop->NewElement($k, '"' . $item->dav_etag . '"');
                break;
            case '"current-user-privilege-set"':
                $prop->NewElement($k, privileges($request->permissions));
                break;
            case 'SOME-DENIED-PROPERTY':
                /** indicating the style for future expansion */
                $denied[] = $k;
                break;
            default:
                dbg_error_log('REPORT', "Request for unsupported property '%s' of calendar item.", $v);
                $unsupported[] = $k;
        }
    }
    $status = new XMLElement("status", "HTTP/1.1 200 OK");
    $propstat = new XMLElement("propstat", array($prop, $status));
    $href = new XMLElement("href", $url);
    $elements = array($href, $propstat);
    if (count($denied) > 0) {
        $status = new XMLElement("status", "HTTP/1.1 403 Forbidden");
        $noprop = new XMLElement("prop");
        foreach ($denied as $k => $v) {
            $noprop->NewElement(strtolower($v));
        }
        $elements[] = new XMLElement("propstat", array($noprop, $status));
    }
    if (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));
        }
        $elements[] = new XMLElement("propstat", array($noprop, $status));
    }
    $response = new XMLElement("response", $elements);
    return $response;
}
Beispiel #2
0
 /**
  * Render XML for a single Principal (user) from the DB
  *
  * @param array $properties The requested properties for this principal
  * @param reference $reply A reference to the XMLDocument being used for the reply
  * @param boolean $props_only Default false.  If true will only return the fragment with the properties, not a full response fragment.
  *
  * @return string An XML fragment with the requested properties for this principal
  */
 function RenderAsXML($properties, &$reply, $props_only = false)
 {
     global $request;
     dbg_error_log('principal', ': RenderAsXML: Principal "%s"', $this->username);
     $prop = new XMLElement('prop');
     $denied = array();
     $not_found = array();
     foreach ($properties as $k => $tag) {
         if (!$this->PrincipalProperty($tag, $prop, $reply, $denied)) {
             dbg_error_log('principal', 'Request for unsupported property "%s" of principal "%s".', $tag, $this->username);
             $not_found[] = $reply->Tag($tag);
         }
     }
     if ($props_only) {
         return $prop;
     }
     $status = new XMLElement('status', 'HTTP/1.1 200 OK');
     $propstat = new XMLElement('propstat', array($prop, $status));
     $href = $reply->href($this->url);
     $elements = array($href, $propstat);
     if (count($denied) > 0) {
         $status = new XMLElement('status', 'HTTP/1.1 403 Forbidden');
         $noprop = new XMLElement('prop');
         foreach ($denied as $k => $v) {
             $noprop->NewElement($v);
         }
         $elements[] = new XMLElement('propstat', array($noprop, $status));
     }
     if (count($not_found) > 0) {
         $status = new XMLElement('status', 'HTTP/1.1 404 Not Found');
         $noprop = new XMLElement('prop');
         foreach ($not_found as $k => $v) {
             $noprop->NewElement($v);
         }
         $elements[] = new XMLElement('propstat', array($noprop, $status));
     }
     $response = new XMLElement('response', $elements);
     return $response;
 }
Beispiel #3
0
 /**
  * Sometimes it's a perfectly formed request, but we just don't do that :-(
  * @param array $unsupported An array of the properties we don't support.
  */
 function UnsupportedRequest($unsupported)
 {
     if (isset($unsupported) && count($unsupported) > 0) {
         $badprops = new XMLElement("prop");
         foreach ($unsupported as $k => $v) {
             // Not supported at this point...
             dbg_error_log("ERROR", " %s: Support for {$v}:{$k} properties is not implemented yet", $this->method);
             $badprops->NewElement(strtolower($k), false, array("xmlns" => strtolower($v)));
         }
         $error = new XMLElement("error", $badprops, array("xmlns" => "DAV:"));
         $this->XMLResponse(422, $error);
     }
 }
Beispiel #4
0
    }
    /**
     * We also include _all_ caldav_data entries in there, since these
     * are events which failed to parse into timesheets.
     */
    $qry = new PgQuery("SELECT * FROM caldav_data WHERE user_no = ?", $report_user_no);
    if ($qry->Exec() && $qry->rows > 0) {
        while ($dav = $qry->Fetch()) {
            $response = new XMLElement("response");
            $prop = new XMLElement("prop");
            $url = sprintf("http://%s:%d%s%s", $_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT'], $_SERVER['SCRIPT_NAME'], $dav->dav_name);
            if (isset($report[$i]['include_href']) && $report[$i]['include_href'] > 0) {
                $response->NewElement("href", $url);
            }
            if (isset($report[$i]['include_data']) && $report[$i]['include_data'] > 0) {
                $prop->NewElement("calendar-data", $dav->caldav_data, array("xmlns" => "urn:ietf:params:xml:ns:caldav"));
            }
            if (isset($report[$i]['properties']['GETETAG'])) {
                $prop->NewElement("getetag", '"' . $dav->dav_etag . '"');
            }
            $status = new XMLElement("status", "HTTP/1.1 200 OK");
            $response->NewElement("propstat", array($prop, $status));
            $responses[] = $response;
            dbg_error_log("REPORT", "DAV Response: ETag >>%s<< >>%s<<", $dav->dav_etag, $url);
        }
    }
}
$multistatus = new XMLElement("multistatus", $responses, array('xmlns' => 'DAV:'));
// dbg_log_array( "REPORT", "XML", $multistatus, true );
$xmldoc = $multistatus->Render();
$etag = md5($xmldoc);
Beispiel #5
0
 /**
  * Construct XML propstat fragment for this resource
  *
  * @param array of string $properties The requested properties for this resource
  *
  * @return string An XML fragment with the requested properties for this resource
  */
 function GetPropStat($properties, &$reply, $props_only = false)
 {
     global $request;
     dbg_error_log('DAVResource', ':GetPropStat: propstat for href "%s"', $this->dav_name);
     $prop = new XMLElement('prop');
     $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();
         }
         $found = $this->ResourceProperty($tag, $prop, $reply, $denied);
         if (!$found) {
             if (!isset($this->principal)) {
                 $this->FetchPrincipal();
             }
             $found = $this->principal->PrincipalProperty($tag, $prop, $reply, $denied);
         }
         if (!$found) {
             //        dbg_error_log( 'DAVResource', 'Request for unsupported property "%s" of resource "%s".', $tag, $this->dav_name );
             $not_found[] = $reply->Tag($tag);
         }
     }
     if ($props_only) {
         return $prop;
     }
     $status = new XMLElement('status', 'HTTP/1.1 200 OK');
     $elements = array(new XMLElement('propstat', array($prop, $status)));
     if (count($denied) > 0) {
         $status = new XMLElement('status', 'HTTP/1.1 403 Forbidden');
         $noprop = new XMLElement('prop');
         foreach ($denied as $k => $v) {
             $reply->NSElement($noprop, $v);
         }
         $elements[] = new XMLElement('propstat', array($noprop, $status));
     }
     if (count($not_found) > 0) {
         $status = new XMLElement('status', 'HTTP/1.1 404 Not Found');
         $noprop = new XMLElement('prop');
         foreach ($not_found as $k => $v) {
             $noprop->NewElement($v);
         }
         $elements[] = new XMLElement('propstat', array($noprop, $status));
     }
     return $elements;
 }
Beispiel #6
0
 /**
  * Sometimes it's a perfectly formed request, but we just don't do that :-(
  * @param array $unsupported An array of the properties we don't support.
  */
 function UnsupportedRequest($unsupported)
 {
     if (isset($unsupported) && count($unsupported) > 0) {
         $badprops = new XMLElement("prop");
         foreach ($unsupported as $k => $v) {
             // Not supported at this point...
             dbg_error_log("ERROR", " %s: Support for {$v}:{$k} properties is not implemented yet", $this->method);
             $badprops->NewElement(strtolower($k), false, array("xmlns" => strtolower($v)));
         }
         $error = new XMLElement("error", new XMLElement("LOCK", $badprops), array("xmlns" => "DAV:"));
         $this->DoResponse(422, $error->Render(0, '<?xml version="1.0" ?>'), 'text/xml; charset="utf-8"');
     }
 }
Beispiel #7
0
/**
* Return XML for a single data item from the DB
*/
function item_to_xml($item)
{
    global $attribute_list, $session, $c, $request;
    dbg_error_log("PROPFIND", "Building XML Response for item '%s'", $item->dav_name);
    $item->properties = get_arbitrary_properties($item->dav_name);
    $url = $_SERVER['SCRIPT_NAME'] . $item->dav_name;
    $prop = new XMLElement("prop");
    if (isset($attribute_list['ALLPROP']) || isset($attribute_list['GETLASTMODIFIED'])) {
        $prop->NewElement("getlastmodified", isset($item->modified) ? $item->modified : false);
    }
    if (isset($attribute_list['ALLPROP']) || isset($attribute_list['GETCONTENTLENGTH'])) {
        $contentlength = strlen($item->caldav_data);
        $prop->NewElement("getcontentlength", $contentlength);
    }
    if (isset($attribute_list['ALLPROP']) || isset($attribute_list['GETCONTENTTYPE'])) {
        $prop->NewElement("getcontenttype", "text/calendar");
    }
    if (isset($attribute_list['ALLPROP']) || isset($attribute_list['CREATIONDATE'])) {
        $prop->NewElement("creationdate", $item->created);
    }
    /**
     * Non-collections should return an empty resource type, it appears from RFC2518 8.1.2
     */
    if (isset($attribute_list['ALLPROP']) || isset($attribute_list['RESOURCETYPE'])) {
        $prop->NewElement("resourcetype");
    }
    if (isset($attribute_list['ALLPROP']) || isset($attribute_list['DISPLAYNAME'])) {
        $prop->NewElement("displayname", $item->dav_displayname);
    }
    if (isset($attribute_list['ALLPROP']) || isset($attribute_list['GETETAG'])) {
        $prop->NewElement("getetag", '"' . $item->dav_etag . '"');
    }
    if (isset($attribute_list['ACL'])) {
        /**
         * FIXME: This information is semantically valid but presents an incorrect picture.
         */
        $principal = new XMLElement("principal");
        $principal->NewElement("authenticated");
        $grant = new XMLElement("grant", array(privileges($request->permissions)));
        $prop->NewElement("acl", new XMLElement("ace", array($principal, $grant)));
    }
    if (isset($attribute_list['ALLPROP']) || isset($attribute_list['GETCONTENTLANGUAGE'])) {
        $contentlength = strlen($item->caldav_data);
        $prop->NewElement("getcontentlanguage", $c->current_locale);
    }
    if (isset($attribute_list['ALLPROP']) || isset($attribute_list['CURRENT-USER-PRIVILEGE-SET'])) {
        $prop->NewElement("current-user-privilege-set", privileges($request->permissions));
    }
    if (isset($attribute_list['ALLPROP']) || isset($attribute_list['SUPPORTEDLOCK'])) {
        $prop->NewElement("supportedlock", new XMLElement("lockentry", array(new XMLElement("lockscope", new XMLElement("exclusive")), new XMLElement("locktype", new XMLElement("write")))));
    }
    $status = new XMLElement("status", "HTTP/1.1 200 OK");
    $propstat = new XMLElement("propstat", array($prop, $status));
    $href = new XMLElement("href", $url);
    $response = new XMLElement("response", array($href, $propstat));
    return $response;
}
Beispiel #8
0
/**
* Return XML for a single component from the DB
*
* @param array $properties The properties for this component
* @param string $item The DB row data for this component
*
* @return string An XML document which is the response for the component
*/
function component_to_xml($properties, $item)
{
    global $session, $c, $request, $reply;
    dbg_error_log("REPORT", "Building XML Response for item '%s'", $item->dav_name);
    $denied = array();
    $unsupported = array();
    $caldav_data = $item->caldav_data;
    $displayname = preg_replace('{^.*/}', '', $item->dav_name);
    $type = 'unknown';
    $contenttype = 'text/plain';
    switch (strtoupper($item->caldav_type)) {
        case 'VJOURNAL':
        case 'VEVENT':
        case 'VTODO':
            $displayname = $item->summary;
            $type = 'calendar';
            $contenttype = 'text/calendar';
            if (isset($properties['urn:ietf:params:xml:ns:caldav:calendar-data']) || isset($properties['DAV::displayname'])) {
                if (!$request->AllowedTo('all') && $session->user_no != $item->user_no) {
                    // the user is not admin / owner of this calendar looking at his calendar and can not admin the other cal
                    if ($item->class == 'CONFIDENTIAL' || !$request->AllowedTo('read')) {
                        dbg_error_log("REPORT", "Anonymising confidential event for: %s", $item->dav_name);
                        $vcal = new vCalendar($caldav_data);
                        $caldav_data = $vcal->Confidential()->Render();
                        $displayname = translate('Busy');
                    }
                }
            }
            if (isset($c->hide_alarm) && $c->hide_alarm) {
                $dav_resource = new DAVResource($item->dav_name);
                if (isset($properties['urn:ietf:params:xml:ns:caldav:calendar-data']) && !$dav_resource->HavePrivilegeTo('write')) {
                    dbg_error_log("REPORT", "Stripping event alarms for: %s", $item->dav_name);
                    $vcal = new vCalendar($caldav_data);
                    $vcal->ClearComponents('VALARM');
                    $caldav_data = $vcal->Render();
                }
            }
            break;
        case 'VCARD':
            $displayname = $item->fn;
            $type = 'vcard';
            $contenttype = 'text/vcard';
            break;
    }
    $url = ConstructURL($item->dav_name);
    $prop = new XMLElement("prop");
    $need_resource = false;
    foreach ($properties as $full_tag => $v) {
        $base_tag = preg_replace('{^.*:}', '', $full_tag);
        switch ($full_tag) {
            case 'DAV::getcontentlength':
                $contentlength = strlen($caldav_data);
                $prop->NewElement($base_tag, $contentlength);
                break;
            case 'DAV::getlastmodified':
                $prop->NewElement($base_tag, ISODateToHTTPDate($item->modified));
                break;
            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 'urn:ietf:params:xml:ns:carddav:address-data':
                if ($type == 'vcard') {
                    $reply->CardDAVElement($prop, $base_tag, $caldav_data);
                } else {
                    $unsupported[] = $base_tag;
                }
                break;
            case 'DAV::getcontenttype':
                $prop->NewElement($base_tag, $contenttype);
                break;
            case 'DAV::current-user-principal':
                $prop->NewElement("current-user-principal", $request->current_user_principal_xml);
                break;
            case 'DAV::displayname':
                $prop->NewElement($base_tag, $displayname);
                break;
            case 'DAV::resourcetype':
                $prop->NewElement($base_tag);
                // Just an empty resourcetype for a non-collection.
                break;
            case 'DAV::getetag':
                $prop->NewElement($base_tag, '"' . $item->dav_etag . '"');
                break;
            case '"current-user-privilege-set"':
                $prop->NewElement($base_tag, privileges($request->permissions));
                break;
            default:
                // It's harder.  We need the DAVResource() to get this one.
                $need_resource = true;
        }
        if ($need_resource) {
            break;
        }
    }
    $href = new XMLElement("href", $url);
    if ($need_resource) {
        if (!isset($dav_resource)) {
            $dav_resource = new DAVResource($item->dav_name);
        }
        $elements = $dav_resource->GetPropStat(array_keys($properties), $reply);
        array_unshift($elements, $href);
    } else {
        $elements = array($href);
        $status = new XMLElement("status", "HTTP/1.1 200 OK");
        $elements[] = new XMLElement("propstat", array($prop, $status));
        if (count($denied) > 0) {
            $status = new XMLElement("status", "HTTP/1.1 403 Forbidden");
            $noprop = new XMLElement("prop");
            foreach ($denied as $k => $v) {
                $reply->NSElement($noprop, $v);
            }
            $elements[] = new XMLElement("propstat", array($noprop, $status));
        }
        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) {
                $reply->NSElement($noprop, $v);
            }
            $elements[] = new XMLElement("propstat", array($noprop, $status));
        }
    }
    $response = new XMLElement("response", $elements);
    return $response;
}