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