Example #1
0
                $lockscope = strtolower(substr($tag, 5));
            }
            break;
            /* case 'DAV::READ': */
            /** RFC2518 is pretty vague about read locks */
        /* case 'DAV::READ': */
        /** RFC2518 is pretty vague about read locks */
        case 'DAV::write':
            dbg_error_log("LOCK", ":Request: %s -> %s", $v['type'], $tag);
            if ($inside['DAV::locktype'] && $v['type'] == "complete") {
                $locktype = strtolower(substr($tag, 5));
            }
            break;
        case 'DAV::href':
            dbg_error_log("LOCK", ":Request: %s -> %s", $v['type'], $tag);
            dbg_log_array("LOCK", "DAV:href", $v, true);
            if ($inside['DAV::owner'] && $v['type'] == "complete") {
                $lockowner = $v['value'];
            }
            break;
        default:
            if (preg_match('/^(.*):([^:]+)$/', $tag, $matches)) {
                $unsupported[$matches[2]] = $matches[1];
            } else {
                $unsupported[$tag] = "";
            }
            dbg_error_log("LOCK", "Unhandled tag >>%s<<", $tag);
    }
}
$request->UnsupportedRequest($unsupported);
// Won't return if there was unsupported stuff.
Example #2
0
        break;
    case 'MOVE':
        include 'caldav-MOVE.php';
        break;
    case 'ACL':
        include 'caldav-ACL.php';
        break;
    case 'LOCK':
        include 'caldav-LOCK.php';
        break;
    case 'UNLOCK':
        include 'caldav-LOCK.php';
        break;
    case 'MKTICKET':
        include 'caldav-MKTICKET.php';
        break;
    case 'DELTICKET':
        include 'caldav-DELTICKET.php';
        break;
    case 'BIND':
        include 'caldav-BIND.php';
        break;
    case 'TESTRRULE':
        include 'test-RRULE-v2.php';
        break;
    default:
        dbg_error_log('caldav', 'Unhandled request method >>%s<<', $request->method);
        dbg_log_array('caldav', '_SERVER', $_SERVER, true);
        dbg_error_log('caldav', 'RAW: %s', str_replace("\n", '', str_replace("\r", '', $request->raw_post)));
}
$request->DoResponse(400, translate('The application program does not understand that request.'));
 */
$searches = $xmltree->GetPath('/DAV::principal-property-search/DAV::property-search');
dbg_log_array("principal", "SEARCH", $searches, true);
$clause_joiner = " AND ";
$CS_search_test = $xmltree->GetAttribute('test');
if (isset($CS_search_test) && $CS_search_test == 'anyof') {
    $clause_joiner = " OR ";
}
$params = array();
$where = "";
foreach ($searches as $k => $search) {
    $qry_props = $search->GetPath('/DAV::property-search/DAV::prop/*');
    // There may be many
    $match = $search->GetPath('/DAV::property-search/DAV::match');
    // There may only be one
    dbg_log_array("principal", "MATCH", $match, true);
    $match = $match[0]->GetContent();
    $subwhere = "";
    foreach ($qry_props as $k1 => $v1) {
        if ($subwhere != "") {
            $subwhere .= " OR ";
        }
        switch ($v1->GetNSTag()) {
            case 'DAV::displayname':
                $subwhere .= ' displayname ILIKE :displayname_match ';
                $params[':displayname_match'] = '%' . $match . '%';
                break;
            case 'urn:ietf:params:xml:ns:caldav:calendar-user-address-set':
                $match = preg_replace('{^.*/caldav.php/([^/]+)(/.*)?$}', '\\1', $match);
                $match = preg_replace('{^mailto:}', '', $match);
                $subwhere .= ' (email ILIKE :user_address_match OR username ILIKE :user_address_match) ';
    $request->DoResponse(404);
}
if (!($target_collection->IsAddressbook() || $target_collection->IsSchedulingCollection())) {
    $request->DoResponse(403, translate('The addressbook-query report must be run against an addressbook collection'));
}
/**
* @todo Once we are past DB version 1.2.1 we can change this query more radically.  The best performance to
* date seems to be:
*   SELECT caldav_data.*,address_item.* FROM collection JOIN address_item USING (collection_id,user_no)
*         JOIN caldav_data USING (dav_id) WHERE collection.dav_name = '/user1/home/'
*              AND caldav_data.caldav_type = 'VEVENT' ORDER BY caldav_data.user_no, caldav_data.dav_name;
*/
$params = array();
$where = ' WHERE caldav_data.collection_id = ' . $target_collection->resource_id();
if (is_array($qry_filters)) {
    dbg_log_array('cardquery', 'qry_filters', $qry_filters, true);
    $components = array();
    $filter_fragment = SqlFilterCardDAV($qry_filters, $components);
    if ($filter_fragment !== false) {
        $where .= ' ' . $filter_fragment['sql'];
        $params = $filter_fragment['params'];
    }
} else {
    dbg_error_log('cardquery', 'No query filters');
}
$sql = 'SELECT * FROM caldav_data INNER JOIN addressbook_resource USING(dav_id)' . $where;
if (isset($c->strict_result_ordering) && $c->strict_result_ordering) {
    $sql .= " ORDER BY dav_id";
}
$qry = new AwlQuery($sql, $params);
if ($qry->Exec("cardquery", __LINE__, __FILE__) && $qry->rows() > 0) {
Example #5
0
}
if ($c->enable_scheduling != true) {
    $request->DoResponse(404, translate('The application program does not understand that request.'));
    // Does not return
}
dbg_log_array('well-known', 'method:' . $request->method);
switch ($request->method) {
    case 'GET':
        ischedule_get();
        break;
    case 'POST':
        include 'iSchedule-POST.php';
        break;
    default:
        dbg_error_log('well-known', 'Unhandled request method >>%s<<', $request->method);
        dbg_log_array('well-known', '_SERVER', $_SERVER, true);
        dbg_error_log('well-known', 'RAW: %s', str_replace("\n", '', str_replace("\r", '', $request->raw_post)));
}
$request->DoResponse(500, translate('The application program does not understand that request.'));
function ischedule_get()
{
    global $request, $c;
    if ($request->path != '/.well-known/ischedule' || $_GET['query'] != 'capabilities') {
        $request->DoResponse(404, translate('The application program does not understand that request.' . $request->path));
        return false;
    }
    header('iSchedule-Version: 1.0');
    header('Content-Type: application/xml; charset=utf-8');
    echo '<?xml version="1.0" encoding="utf-8" ?>';
    echo <<<RESPONSE
  <query-result xmlns="urn:ietf:params:xml:ns:ischedule">
Example #6
0
 /**
  * Function to dump an array to the error log, possibly recursively
  *
  * @var string $component Which component should this log message identify itself from
  * @var string $name What name should this array dump identify itself as
  * @var array $arr The array to be dumped.
  * @var boolean $recursive Should the dump recurse into arrays/objects in the array
  */
 function dbg_log_array($component, $name, $arr, $recursive = false)
 {
     if (!isset($arr) || gettype($arr) != 'array' && gettype($arr) != 'object') {
         dbg_error_log($component, "%s: array is not set, or is not an array!", $name);
         return;
     }
     foreach ($arr as $key => $value) {
         dbg_error_log($component, "%s: >>%s<< = >>%s<<", $name, $key, gettype($value) == 'array' || gettype($value) == 'object' ? gettype($value) : $value);
         if ($recursive && (gettype($value) == 'array' || gettype($value) == 'object' && "{$key}" != 'self' && "{$key}" != 'parent')) {
             dbg_log_array($component, "{$name}" . "[{$key}]", $value, $recursive);
         }
     }
 }
Example #7
0
 /**
  * Set the translation to the user's locale.  At this stage all we do is
  * call the gettext function.
  */
 function awl_set_locale($locale)
 {
     global $c;
     if (!is_array($locale) && !preg_match('/^[a-z]{2}(_[A-Z]{2})?\\./', $locale)) {
         $locale = array($locale, $locale . ".UTF-8");
     }
     if ($newlocale = setlocale(LC_ALL, $locale)) {
         dbg_error_log("I18N", "Set locale to =%s=", $newlocale);
         $c->current_locale = $newlocale;
     } else {
         dbg_log_array("I18N", "Unsupported locale: ", $locale, false);
     }
 }
Example #8
0
                }
            } else {
                dbg_error_log("REPORT", "Unexpected DAV::PROP type of " . $v['type'] . " when no active report type.");
            }
            break;
        case 'DAV::GETETAG':
        case 'DAV::GETCONTENTLENGTH':
        case 'DAV::GETCONTENTTYPE':
        case 'DAV::RESOURCETYPE':
            if (isset($report_properties)) {
                $attribute = substr($v['tag'], 5);
                $report_properties[$attribute] = 1;
            }
            break;
        case 'DAV::HREF':
            dbg_log_array("REPORT", "DAV::HREF", $v, true);
            if (isset($report[$reportnum]['multiget'])) {
                $multiget_names[] = $v['value'];
            }
        default:
            dbg_error_log("REPORT", "Unhandled tag >>" . $v['tag'] . "<<");
    }
}
if ($reportnum == -1) {
    // Fake the request anyway...
    $reportnum++;
    $report_type = substr($v['tag'], 30);
    $report[$reportnum]['type'] = $report_type;
    $report[$reportnum]['include_href'] = 1;
    $report[$reportnum]['include_data'] = 0;
    $report[$reportnum]['start'] = date('Ymd\\THis\\Z', time() - 86400 * 40);
    }
    /**
     * We're here because they allow recursive reports, and this appears to be such a location.
     */
    $where = 'WHERE caldav_data.collection_id IN ';
    $where .= '(SELECT bound_source_id FROM dav_binding WHERE dav_binding.dav_name ~ :path_match ';
    $where .= 'UNION ';
    $where .= 'SELECT collection_id FROM collection WHERE collection.dav_name ~ :path_match) ';
    $distinct = 'DISTINCT ON (calendar_item.uid) ';
    $params[':path_match'] = '^' . $target_collection->bound_from();
} else {
    $where = ' WHERE caldav_data.collection_id = ' . $target_collection->resource_id();
    $distinct = '';
}
if (is_array($qry_filters)) {
    dbg_log_array("calquery", "qry_filters", $qry_filters, true);
    $components = array();
    $filter_fragment = SqlFilterFragment($qry_filters, $components);
    if ($filter_fragment !== false) {
        $where .= ' ' . $filter_fragment['sql'];
        $params = array_merge($params, $filter_fragment['params']);
    }
}
if ($target_collection->Privileges() != privilege_to_bits('DAV::all')) {
    $where .= " AND (calendar_item.class != 'PRIVATE' OR calendar_item.class IS NULL) ";
}
if (isset($c->hide_TODO) && ($c->hide_TODO === true || is_string($c->hide_TODO) && preg_match($c->hide_TODO, $_SERVER['HTTP_USER_AGENT'])) && !$target_collection->HavePrivilegeTo('all')) {
    $where .= " AND caldav_data.caldav_type NOT IN ('VTODO') ";
}
if (isset($c->hide_older_than) && intval($c->hide_older_than > 0)) {
    $where .= " AND (CASE WHEN caldav_data.caldav_type<>'VEVENT' OR calendar_item.dtstart IS NULL THEN true ELSE calendar_item.dtstart > (now() - interval '" . intval($c->hide_older_than) . " days') END) ";
Example #10
0
                $item->addCategory(array('term' => trim($category)));
            }
        }
        $p_description = $event->description;
        if ($p_description != '') {
            $content .= '<br />' . '<br />' . '<strong>' . translate('Description') . '</strong>:<br />' . nl2br(hyperlink($p_description));
            $item->setDescription($p_description);
        }
        $item->setContent($content);
        $feed->addEntry($item);
        //break;
    }
    $last_modified = new RepeatRuleDateTime($collection->GetProperty('modified'));
    $feed->setDateModified($last_modified->epoch());
    $response = $feed->export('atom');
    $cache->set($cache_ns, $cache_key, $response);
    return $response;
}
if ($request->method == 'GET') {
    $collection = new DAVResource($request->path);
    $response = caldav_get_feed($request, $collection);
    header('Content-Length: ' . strlen($response));
    header('Etag: ' . $collection->unique_tag());
    $request->DoResponse(200, $request->method == 'HEAD' ? '' : $response, 'text/xml; charset="utf-8"');
} else {
    dbg_error_log('feed', 'Unhandled request method >>%s<<', $request->method);
    dbg_log_array('feed', '_SERVER', $_SERVER, true);
    dbg_error_log('feed', 'RAW: %s', str_replace("\n", '', str_replace("\r", '', $request->raw_post)));
}
$request->DoResponse(500, translate('The application program does not understand that request.'));
/* vim: set ts=2 sw=2 tw=0 :*/
Example #11
0
        break;
    case 'REPORT':
        include_once "caldav-REPORT.php";
        break;
    case 'PROPFIND':
        include_once "caldav-PROPFIND.php";
        break;
    case 'GET':
        include_once "caldav-GET.php";
        break;
    case 'HEAD':
        include_once "caldav-GET.php";
        break;
    case 'PROPPATCH':
    case 'MKCALENDAR':
    case 'MKCOL':
    case 'PUT':
    case 'DELETE':
    case 'LOCK':
    case 'UNLOCK':
        $request->DoResponse(403, translate('Anonymous users are not allowed to modify calendars'));
        break;
    case 'TESTRRULE':
        include_once "test-RRULE.php";
        break;
    default:
        dbg_error_log("caldav", "Unhandled request method >>%s<<", $request->method);
        dbg_log_array("caldav", '_SERVER', $_SERVER, true);
        dbg_error_log("caldav", "RAW: %s", str_replace("\n", "", str_replace("\r", "", $request->raw_post)));
}
$request->DoResponse(500, translate("The application program does not understand that request."));
Example #12
0
/**
* Returns an XML sub-tree for a single collection record from the DB
*/
function collection_to_xml($collection)
{
    global $arbitrary, $attribute_list, $session, $c, $request;
    dbg_error_log("PROPFIND", "Building XML Response for collection '%s'", $collection->dav_name);
    $collection->properties = get_arbitrary_properties($collection->dav_name);
    $url = $_SERVER['SCRIPT_NAME'] . $collection->dav_name;
    $resourcetypes = array(new XMLElement("collection"));
    $contentlength = false;
    if ($collection->is_calendar == 't') {
        $resourcetypes[] = clone new XMLElement("calendar", false, array("xmlns" => "urn:ietf:params:xml:ns:caldav"));
        $lqry = new PgQuery("SELECT sum(length(caldav_data)) FROM caldav_data WHERE user_no = ? AND dav_name ~ ?;", $collection->user_no, $collection->dav_name . '[^/]+$');
        if ($lqry->Exec("PROPFIND", __LINE__, __FILE__) && ($row = $lqry->Fetch())) {
            $contentlength = $row->sum;
        }
    }
    if ($collection->is_principal == 't') {
        $resourcetypes[] = clone new XMLElement("principal");
    }
    dbg_log_array("PROPFIND", 'attribute_list', $attribute_list, true);
    $prop = new XMLElement("prop");
    if (isset($attribute_list['ALLPROP']) || isset($attribute_list['GETLASTMODIFIED'])) {
        $prop->NewElement("getlastmodified", isset($collection->modified) ? $collection->modified : false);
    }
    if (isset($attribute_list['ALLPROP']) || isset($attribute_list['GETCONTENTLENGTH'])) {
        $prop->NewElement("getcontentlength", $contentlength);
    }
    if (isset($attribute_list['ALLPROP']) || isset($attribute_list['GETCONTENTTYPE'])) {
        $prop->NewElement("getcontenttype", "httpd/unix-directory");
    }
    if (isset($attribute_list['ALLPROP']) || isset($attribute_list['CREATIONDATE'])) {
        $prop->NewElement("creationdate", $collection->created);
    }
    if (isset($attribute_list['ALLPROP']) || isset($attribute_list['RESOURCETYPE'])) {
        dbg_error_log("PROPFIND", "Appending resourcetype results");
        $prop->NewElement("resourcetype", $resourcetypes);
    }
    if (isset($attribute_list['ALLPROP']) || isset($attribute_list['DISPLAYNAME'])) {
        $displayname = $collection->dav_displayname == "" ? ucfirst(trim(str_replace("/", " ", $collection->dav_name))) : $collection->dav_displayname;
        $prop->NewElement("displayname", $displayname);
    }
    if (isset($attribute_list['ALLPROP']) || isset($attribute_list['GETETAG'])) {
        $prop->NewElement("getetag", '"' . $collection->dav_etag . '"');
    }
    if (isset($attribute_list['ALLPROP']) || isset($attribute_list['CURRENT-USER-PRIVILEGE-SET'])) {
        $prop->NewElement("current-user-privilege-set", privileges($request->permissions));
    }
    if (count($arbitrary) > 0) {
        foreach ($arbitrary as $k => $v) {
            $prop->NewElement($k, $collection->properties[$k]);
        }
    }
    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['SUPPORTEDLOCK'])) {
        $prop->NewElement("supportedlock", new XMLElement("lockentry", array(new XMLElement("lockscope", new XMLElement("exclusive")), new XMLElement("locktype", new XMLElement("write")))));
    }
    if (isset($attribute_list['ALLPROP']) || isset($attribute_list['SUPPORTED-PRIVILEGE-SET'])) {
        $prop->NewElement("supported-privilege-set", privileges($request->SupportedPrivileges(), "supported-privilege"));
    }
    $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;
}
Example #13
0
 /**
  * Set the translation to the user's locale.  At this stage all we do is
  * call the gettext function.
  */
 function awl_set_locale($locale)
 {
     global $c;
     if (!is_array($locale) && !preg_match('/^[a-z]{2}(_[A-Z]{2})?\\./', $locale)) {
         $locale = array($locale, $locale . '.UTF-8');
     }
     if (!function_exists('setlocale')) {
         dbg_log_array('WARN', 'No "setlocale()" function?  PHP gettext support missing?');
         return;
     }
     if ($newlocale = setlocale(LC_ALL, $locale)) {
         dbg_error_log('I18N', 'Set locale to =%s=', $newlocale);
         $c->current_locale = $newlocale;
     } else {
         dbg_log_array('I18N', 'Unsupported locale: ', $locale, false);
     }
 }
Example #14
0
if (preg_match('{^/(\\S+@[a-z0-9][a-z0-9-]*[.][a-z0-9.-]+)/?$}i', $request->path, $matches)) {
    $principal = new Principal('email', $matches[1]);
    $path_match = '^' . $principal->dav_name();
}
if (isset($fb_format) && $fb_format != 'text/calendar') {
    $request->DoResponse(406, translate('This server only supports the text/calendar format for freebusy URLs'));
}
if (!$request->HavePrivilegeTo('read-free-busy')) {
    $request->DoResponse(404);
}
require_once "freebusy-functions.php";
switch ($_SERVER['REQUEST_METHOD']) {
    case 'GET':
        $range_start = new RepeatRuleDateTime($fb_start);
        if (!isset($fb_end)) {
            $range_end = clone $range_start;
            $range_end->modify($fb_period);
        } else {
            $range_end = new RepeatRuleDateTime($fb_end);
        }
        $freebusy = get_freebusy($path_match, $range_start, $range_end);
        $result = new vCalendar();
        $result->AddComponent($freebusy);
        $request->DoResponse(200, $result->Render(), 'text/calendar');
        break;
    default:
        dbg_error_log("freebusy", "Unhandled request method >>%s<<", $_SERVER['REQUEST_METHOD']);
        dbg_log_array("freebusy", 'HEADERS', $raw_headers);
        dbg_log_array("freebusy", '_SERVER', $_SERVER, true);
        @dbg_error_log("freebusy", "RAW: %s", str_replace("\n", "", str_replace("\r", "", $request->raw_post)));
}