1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
<?php
/**
* CalDAV Server - main program
*
* @package davical
* @subpackage caldav
* @author Andrew McMillan <andrew@mcmillan.net.nz>
* @copyright Catalyst .Net Ltd, Morphoss Ltd <http://www.morphoss.com/>
* @license http://gnu.org/copyleft/gpl.html GNU GPL v2 or later
*/
require_once('./always.php');
if ( isset($_SERVER['PATH_INFO']) && preg_match( '{^/\.well-known/(.+)$}', $_SERVER['PATH_INFO'], $matches ) ) {
require ('well-known.php');
@ob_flush(); exit(0);
}
elseif ( isset($_SERVER['PATH_INFO']) && $_SERVER['PATH_INFO'] == '/autodiscover/autodiscover.xml' ) {
require ('autodiscover-handler.php');
@ob_flush(); exit(0);
}
function logRequestHeaders() {
global $c;
/** Log the request headers */
$lines = apache_request_headers();
dbg_error_log( "LOG ", "***************** Request Header ****************" );
dbg_error_log( "LOG ", "%s %s", $_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI'] );
foreach( $lines AS $k => $v ) {
if ( $k != 'Authorization' || (isset($c->dbg['password']) && $c->dbg['password'] ) )
dbg_error_log( "LOG headers", "-->%s: %s", $k, $v );
else
dbg_error_log( "LOG headers", "-->%s: %s", $k, 'Delicious tasty password eaten by debugging monster!' );
}
dbg_error_log( "LOG ", "******************** Request ********************" );
// Log the request in all it's gory detail.
$lines = preg_split( '#[\r\n]+#', $c->raw_post );
foreach( $lines AS $v ) {
dbg_error_log( "LOG request", "-->%s", $v );
}
unset($lines);
}
if ( !isset($c->raw_post) ) $c->raw_post = file_get_contents( 'php://input');
if ( (isset($c->dbg['ALL']) && $c->dbg['ALL']) || (isset($c->dbg['request']) && $c->dbg['request']) )
logRequestHeaders();
require_once('HTTPAuthSession.php');
$session = new HTTPAuthSession();
function send_dav_header() {
global $c;
/**
* access-control is rfc3744, we do most of it, but no way to say that.
* calendar-schedule is another one we do most of, but the spec is not final yet either.
*/
if ( isset($c->override_dav_header) ) {
$dav = $c->override_dav_header;
}
else {
$dav = '1, 2, 3, access-control, calendar-access, calendar-schedule, extended-mkcol, bind, addressbook';
if ( $c->enable_auto_schedule ) $dav .= ', calendar-auto-schedule';
if ( !isset($c->disable_caldav_proxy) || $c->disable_caldav_proxy == false) $dav .= ', calendar-proxy';
}
$dav = explode( "\n", wordwrap( $dav ) );
foreach( $dav AS $v ) {
header( 'DAV: '.trim($v, ', '), false);
}
}
require_once('CalDAVRequest.php');
$request = new CalDAVRequest();
function late_catch_fatal_error() {
global $request;
// Getting Last Error
$e = error_get_last();
if (isset($e['type']) && $e['type'] == E_ERROR) {
$request->DoResponse(500, "Fatal PHP Error");
}
}
register_shutdown_function('late_catch_fatal_error');
//if ( $request->method == 'OPTIONS' || $c->always_send_dav_header )
send_dav_header(); // Avoid polluting global namespace
if ( ! ($request->IsPrincipal() || isset($request->collection) || $request->method == 'PUT' || $request->method == 'MKCALENDAR' || $request->method == 'MKCOL' ) ) {
if ( preg_match( '#^/principals/users(/.*/)$#', $request->path, $matches ) ) {
// Although this doesn't work with the iPhone, perhaps it will with iCal...
// This is better handled by a RewriteRule, see config/apache-davical.conf
$redirect_url = ConstructURL('/caldav.php'.$matches[1]);
dbg_error_log( 'LOG WARNING', 'Redirecting %s for "%s" to "%s", consider using rewrites in the webserver instead!', $request->method, $request->path, $redirect_url );
header('Location: '.$redirect_url );
@ob_flush(); exit(0);
}
}
param_to_global('add_member', null, 'add-member');
$add_member = isset($add_member);
try {
switch ( $request->method ) {
case 'OPTIONS': include_once('caldav-OPTIONS.php'); break;
case 'REPORT': include_once('caldav-REPORT.php'); break;
case 'PROPFIND': include('caldav-PROPFIND.php'); break;
case 'GET': include('caldav-GET.php'); break;
case 'HEAD': include('caldav-GET.php'); break;
case 'PROPPATCH': include('caldav-PROPPATCH.php'); break;
case 'POST':
if ( $request->content_type != 'text/vcard' && !$add_member ) {
include('caldav-POST.php');
break;
}
// fall through if POST add member
case 'PUT':
switch( $request->content_type ) {
case 'text/calendar':
include('caldav-PUT-vcalendar.php');
break;
case 'text/vcard':
case 'text/x-vcard':
include('caldav-PUT-vcard.php');
break;
default:
include('caldav-PUT-default.php');
break;
}
break;
case 'MKCALENDAR': include('caldav-MKCOL.php'); break;
case 'MKCOL': include('caldav-MKCOL.php'); break;
case 'DELETE': include('caldav-DELETE.php'); 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)) );
}
} catch (Exception $e) {
trace_bug( 'DAViCal Fatal Error: ['.$e->getCode().'] '.$e->getmessage().' at '.$e->getFile().':'.$e->getLine() );
$request->DoResponse( 500, translate('DAViCal Fatal Error') );
}
$request->DoResponse( 400, translate('The application program does not understand that request.') );
|