From d64d2b4000b608190ae3d333c6e92fbafcf75e67 Mon Sep 17 00:00:00 2001 From: Andrew McMillan Date: Tue, 12 Sep 2006 04:36:37 -0500 Subject: [PATCH] Now storing events, including parsing them into further SQL. --- .gitignore | 1 + config/config.php | 5 ++++ dba/rscds.sql | 4 +-- dba/sample-data.sql | 2 +- htdocs/.gitignore | 1 + htdocs/caldav.php | 8 ++--- inc/BasicAuthSession.php | 63 ++-------------------------------------- inc/always.php | 15 ++++++---- inc/caldav-DELETE.php | 8 ++--- inc/caldav-GET.php | 4 +-- inc/caldav-OPTIONS.php | 2 +- inc/caldav-PUT.php | 37 ++++++++++++++++++++--- inc/caldav-REPORT.php | 16 +++++----- inc/session-util.php | 2 +- inc/vEvent.php | 39 +++++++++++++++++++++---- rscds.webprj | 1 + 16 files changed, 110 insertions(+), 98 deletions(-) create mode 100644 htdocs/.gitignore diff --git a/.gitignore b/.gitignore index 2effd388..e1b1fe1d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ caldav.session rscds.session +build diff --git a/config/config.php b/config/config.php index 712cc30e..e452d2bd 100644 --- a/config/config.php +++ b/config/config.php @@ -15,4 +15,9 @@ } } + $c->dbg['vevent'] = 1; + $c->dbg['put'] = 1; + $c->dbg['report'] = 1; + + ?> \ No newline at end of file diff --git a/dba/rscds.sql b/dba/rscds.sql index 9364f48b..e0baa5c3 100644 --- a/dba/rscds.sql +++ b/dba/rscds.sql @@ -34,8 +34,8 @@ CREATE TABLE ical_events ( -- Extracted vEvent event data uid TEXT, dtstamp TEXT, - dtstart TIMESTAMP, - dtend TIMESTAMP, + dtstart TIMESTAMP WITH TIME ZONE, + dtend TIMESTAMP WITH TIME ZONE, summary TEXT, location TEXT, class TEXT, diff --git a/dba/sample-data.sql b/dba/sample-data.sql index dd2e4e0e..525f8ce0 100644 --- a/dba/sample-data.sql +++ b/dba/sample-data.sql @@ -1,6 +1,6 @@ -- Some sample data to prime the database... INSERT INTO usr ( user_no, active, email_ok, updated, username, password, fullname, email ) - VALUES( 1, TRUE, current_date, current_date, 'andrew', '**x', 'Andrew McMillan', 'andrew@catalyst.net.nz' ); + VALUES( 1, TRUE, current_date, current_date, 'admin', '**nimda', 'Calendar Administrator', 'calendars@example.net' ); SELECT setval('usr_user_no_seq', 1); diff --git a/htdocs/.gitignore b/htdocs/.gitignore new file mode 100644 index 00000000..d8267307 --- /dev/null +++ b/htdocs/.gitignore @@ -0,0 +1 @@ +andrew@catalyst.net.nz.freebusy diff --git a/htdocs/caldav.php b/htdocs/caldav.php index ddcc1801..eb373c2a 100644 --- a/htdocs/caldav.php +++ b/htdocs/caldav.php @@ -26,10 +26,10 @@ switch ( $_SERVER['REQUEST_METHOD'] ) { break; default: - dbg_error_log( "Unhandled request method >>%s<<", $_SERVER['REQUEST_METHOD'] ); - dbg_log_array( 'HEADERS', $raw_headers ); - dbg_log_array( '_SERVER', $_SERVER, true ); - dbg_error_log( "RAW: %s", str_replace("\n", "",str_replace("\r", "", $raw_post)) ); + dbg_error_log( "caldav", "Unhandled request method >>%s<<", $_SERVER['REQUEST_METHOD'] ); + dbg_log_array( "caldav", 'HEADERS', $raw_headers ); + dbg_log_array( "caldav", '_SERVER', $_SERVER, true ); + dbg_error_log( "caldav", "RAW: %s", str_replace("\n", "",str_replace("\r", "", $raw_post)) ); } diff --git a/inc/BasicAuthSession.php b/inc/BasicAuthSession.php index b7a4ea78..d511bee8 100644 --- a/inc/BasicAuthSession.php +++ b/inc/BasicAuthSession.php @@ -64,70 +64,11 @@ class BasicAuthSession { header( sprintf( 'WWW-Authenticate: Basic realm="%s"', $c->system_name) ); header('HTTP/1.0 401 Unauthorized'); echo 'Please log in for access to this system.'; - dbg_error_log( "Login: User is not authorised" ); + dbg_error_log( "Login", "User is not authorised" ); exit; } } - /** - * Utility function to log stuff with printf expansion. - * - * This function could be expanded to log something identifying the session, but - * somewhat strangely this has not yet been done. - * - * @param string $whatever A log string - * @param mixed $whatever... Further parameters to be replaced into the log string a la printf - */ - function Log( $whatever ) - { - global $c; - - $argc = func_num_args(); - $format = func_get_arg(0); - if ( $argc == 1 || ($argc == 2 && func_get_arg(1) == "0" ) ) { - error_log( "$c->sysabbr: $format" ); - } - else { - $args = array(); - for( $i=1; $i < $argc; $i++ ) { - $args[] = func_get_arg($i); - } - error_log( "$c->sysabbr: " . vsprintf($format,$args) ); - } - } - - /** - * Utility function to log debug stuff with printf expansion, and the ability to - * enable it selectively. - * - * The enabling is done by setting a variable "$debuggroups[$group] = 1" - * - * @param string $group The name of an arbitrary debug group. - * @param string $whatever A log string - * @param mixed $whatever... Further parameters to be replaced into the log string a la printf - */ - function Dbg( $whatever ) - { - global $debuggroups, $c; - - $argc = func_num_args(); - $dgroup = func_get_arg(0); - - if ( ! (isset($debuggroups[$dgroup]) && $debuggroups[$dgroup]) ) return; - - $format = func_get_arg(1); - if ( $argc == 2 || ($argc == 3 && func_get_arg(2) == "0" ) ) { - error_log( "$c->sysabbr: DBG: $dgroup: $format" ); - } - else { - $args = array(); - for( $i=2; $i < $argc; $i++ ) { - $args[] = func_get_arg($i); - } - error_log( "$c->sysabbr: DBG: $dgroup: " . vsprintf($format,$args) ); - } - } - /** * CheckPassword does all of the password checking and @@ -137,7 +78,7 @@ class BasicAuthSession { $qry = new PgQuery( "SELECT * FROM usr WHERE lower(username) = ? ", $username ); if ( $qry->Exec('BAS::CheckPassword',__LINE,__FILE__) && $qry->rows == 1 ) { $usr = $qry->Fetch(); - dbg_error_log( "Login: Name:%s, Pass:%s, File:%s", $username, $password, $usr->password ); + dbg_error_log( "Login", "Name:%s, Pass:%s, File:%s", $username, $password, $usr->password ); if ( session_validate_password( $password, $usr->password ) ) { return $usr; } diff --git a/inc/always.php b/inc/always.php index f7085e7f..44763dac 100644 --- a/inc/always.php +++ b/inc/always.php @@ -18,6 +18,8 @@ $c->domain_name = $_SERVER['SERVER_NAME']; // Kind of private configuration values $c->total_query_time = 0; +$c->dbg = array( 'core' => 1 ); + if ( $debugging && isset($_GET['method']) ) { $_SERVER['REQUEST_METHOD'] = $_GET['method']; } @@ -30,17 +32,20 @@ function dbg_error_log() { global $c; $argc = func_num_args(); $args = func_get_args(); + $component = array_shift($args); + if ( !isset($c->dbg[strtolower($component)]) ) return; + if ( 2 <= $argc ) { $format = array_shift($args); } else { $format = "%s"; } - error_log( $c->sysabbr.": DBG: ". vsprintf( $format, $args ) ); + error_log( $c->sysabbr.": DBG: $component:". vsprintf( $format, $args ) ); } -dbg_error_log( "==========> method =%s= =%s:%d= =%s= =%s=", +dbg_error_log( "core", "==========> method =%s= =%s:%d= =%s= =%s=", $_SERVER['REQUEST_METHOD'], $_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT'], $_SERVER['SCRIPT_NAME'], $_SERVER['PATH_INFO']); if ( file_exists("/etc/rscds/".$_SERVER['SERVER_NAME']."-conf.php") ) { include_once("/etc/rscds/".$_SERVER['SERVER_NAME']."-conf.php"); @@ -62,11 +67,11 @@ if ( !function_exists('apache_request_headers') ) { } } -function dbg_log_array( $name, $arr, $recursive = false ) { +function dbg_log_array( $component, $name, $arr, $recursive = false ) { foreach ($arr as $key => $value) { - dbg_error_log( "%s: >>%s<< = >>%s<<", $name, $key, $value); + dbg_error_log( $component, "%s: >>%s<< = >>%s<<", $name, $key, $value); if ( $recursive && (gettype($value) == 'array' || gettype($value) == 'object') ) { - dbg_log_array( "$name"."[$key]", $value, $recursive ); + dbg_log_array( $component, "$name"."[$key]", $value, $recursive ); } } } diff --git a/inc/caldav-DELETE.php b/inc/caldav-DELETE.php index 6e993e0b..dcfaaff6 100644 --- a/inc/caldav-DELETE.php +++ b/inc/caldav-DELETE.php @@ -1,6 +1,6 @@ Exec("caldav-DELETE") && $qry->rows == 1 ) { $qry = new PgQuery( "DELETE FROM ics_event_data WHERE user_no = ? AND ics_event_name = ? AND ics_event_etag = ?;", $session->user_no, $get_path, $etag_none_match ); if ( $qry->Exec("caldav-DELETE") ) { header("HTTP/1.1 200 OK"); - dbg_error_log( "DELETE: User: %d, ETag: %s, Path: %s", $session->user_no, $etag_none_match, $get_path); + dbg_error_log( "delete", "DELETE: User: %d, ETag: %s, Path: %s", $session->user_no, $etag_none_match, $get_path); } else { header("HTTP/1.1 500 Infernal Server Error"); - dbg_error_log( "DELETE failed: User: %d, ETag: %s, Path: %s, SQL: %s", $session->user_no, $etag_none_match, $get_path, $qry->querystring); + dbg_error_log( "delete", "DELETE failed: User: %d, ETag: %s, Path: %s, SQL: %s", $session->user_no, $etag_none_match, $get_path, $qry->querystring); } } else { header("HTTP/1.1 404 Not Found"); - dbg_error_log( "DELETE row not found: User: %d, ETag: %s, Path: %s", $qry->rows, $session->user_no, $etag_none_match, $get_path); + dbg_error_log( "delete", "DELETE row not found: User: %d, ETag: %s, Path: %s", $qry->rows, $session->user_no, $etag_none_match, $get_path); } ?> \ No newline at end of file diff --git a/inc/caldav-GET.php b/inc/caldav-GET.php index 58e914ea..b75b9ce1 100644 --- a/inc/caldav-GET.php +++ b/inc/caldav-GET.php @@ -1,6 +1,6 @@ Exec("caldav-GET") && $qry->rows == 1 ) { print $event->ics_raw_data; - dbg_error_log( "GET: User: %d, ETag: %s, Path: %s", $session->user_no, $event->ics_event_etag, $get_path); + dbg_error_log( "GET", "User: %d, ETag: %s, Path: %s", $session->user_no, $event->ics_event_etag, $get_path); } else { diff --git a/inc/caldav-OPTIONS.php b/inc/caldav-OPTIONS.php index e9a15a13..adf3fcf5 100644 --- a/inc/caldav-OPTIONS.php +++ b/inc/caldav-OPTIONS.php @@ -1,5 +1,5 @@ user_no, $put_path, $etag, $raw_post); @@ -33,6 +33,35 @@ else { header("ETag: $etag"); } -dbg_error_log( "PUT: User: %d, ETag: %s, Path: %s", $session->user_no, $etag, $put_path); +include_once("vEvent.php"); +$ev = new vEvent(array( 'vevent' => $raw_post )); + +dbg_log_array( "PUT", 'EVENT', $ev, true ); + +$sql = "SET TIMEZONE TO ".qpg($ev->tzlocn).";"; +if ( $etag_match == '*' || $etag_match == '' ) { + $sql .= <<user_no, $put_path, $etag, $ev->Get('uid'), $ev->Get('dtstamp'), + $ev->Get('dtstart'), $ev->Get('dtend'), $ev->Get('summary'), $ev->Get('location'), + $ev->Get('class'), $ev->Get('transp'), $ev->Get('description'), $ev->Get('rrule'), $ev->Get('tzid') ); + $qry->Exec("caldav-PUT"); +} +else { + $sql = <<Get('uid'), $ev->Get('dtstamp'), $ev->Get('dtstart'), $ev->Get('dtend'), $ev->Get('summary'), + $ev->Get('location'), $ev->Get('class'), $ev->Get('transp'), $ev->Get('description'), $ev->Get('rrule'), + $ev->Get('tzid'), $session->user_no, $put_path, $etag ); + $qry->Exec("caldav-PUT"); +} + +dbg_error_log( "PUT", "User: %d, ETag: %s, Path: %s", $session->user_no, $etag, $put_path); ?> \ No newline at end of file diff --git a/inc/caldav-REPORT.php b/inc/caldav-REPORT.php index 62b135da..b1b25a56 100644 --- a/inc/caldav-REPORT.php +++ b/inc/caldav-REPORT.php @@ -1,17 +1,17 @@ $v ) { unset($report_properties); } else { - dbg_error_log( "REPORT: Unexpected DAV::PROP type of ".$v['type'] ); + dbg_error_log( "REPORT", "Unexpected DAV::PROP type of ".$v['type'] ); } } else { - dbg_error_log( "REPORT: Unexpected DAV::PROP type of ".$v['type']." when no active report type."); + dbg_error_log( "REPORT", "Unexpected DAV::PROP type of ".$v['type']." when no active report type."); } break; @@ -65,7 +65,7 @@ foreach( $rpt_request AS $k => $v ) { break; default: - dbg_error_log("REPORT: Unhandled tag >>".$v['tag']."<<"); + dbg_error_log( "REPORT", "Unhandled tag >>".$v['tag']."<<"); } } @@ -100,7 +100,7 @@ REPORTHDR; if ( $qry->Exec() && $qry->rows > 0 ) { while( $event = $qry->Fetch() ) { printf( $response_tpl, $_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT'], $_SERVER['SCRIPT_NAME'], $event->ics_event_name, $event->ics_event_etag ); - dbg_error_log("REPORT: ETag >>%s<< >>http://%s:%s%s%s<<", $event->ics_event_etag, + dbg_error_log("REPORT", "ETag >>%s<< >>http://%s:%s%s%s<<", $event->ics_event_etag, $_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT'], $_SERVER['SCRIPT_NAME'], $event->ics_event_name); } } diff --git a/inc/session-util.php b/inc/session-util.php index 46646bbf..fd246689 100644 --- a/inc/session-util.php +++ b/inc/session-util.php @@ -19,7 +19,7 @@ if ( !function_exists("session_salted_md5") ) { */ function session_salted_md5( $instr, $salt = "" ) { if ( $salt == "" ) $salt = substr( md5(rand(100000,999999)), 2, 8); - dbg_error_log( "Login: Making salted MD5: salt=$salt, instr=$instr, md5($salt$instr)=".md5($salt . $instr) ); + dbg_error_log( "Login", "Making salted MD5: salt=$salt, instr=$instr, md5($salt$instr)=".md5($salt . $instr) ); return ( sprintf("*%s*%s", $salt, md5($salt . $instr) ) ); } } diff --git a/inc/vEvent.php b/inc/vEvent.php index 5045d254..5bef2221 100644 --- a/inc/vEvent.php +++ b/inc/vEvent.php @@ -32,6 +32,12 @@ class vEvent { */ var $properties; + /** + * The typical name for the standard timezone + * @var tzname string + */ + var $tzname; + /**#@-*/ /** @@ -44,7 +50,7 @@ class vEvent { // Probably a good idea to always have values for these things... $this->properties['tzid'] = $c->local_tzid; - $this->properties['modified'] = iCalendar::EpochTS(time()); + $this->properties['modified'] = time(); $this->properties['sequence'] = 1; $this->properties['uid'] = sprintf( "%s@%s", time() * 1000 + rand(0,1000), $c->domain_name); $this->properties['guid'] = sprintf( "%s@%s", time() * 1000 + rand(0,1000), $c->domain_name); @@ -76,7 +82,8 @@ class vEvent { $vtimezone = ""; $state = 0; - foreach( $properties AS $k => $v ) { + foreach( $lines AS $k => $v ) { + dbg_error_log( "vEvent", "LINE %03d: >>>%s<<<", $k, $v ); switch( $state ) { case 0: @@ -102,10 +109,17 @@ class vEvent { list( $parameter, $tzid ) = preg_split('/;/', $parameter ); $properties['TZID'] = $tzid; } - $properties[$parameter] = $value; + $properties[strtoupper($parameter)] = $value; } if ( $state == 'BEGIN:VTIMEZONE' ) { $vtimezone .= $v . "\n"; + list( $parameter, $value ) = preg_split('/:/', $v ); + if ( !isset($this->tzname) && $parameter == 'TZNAME' ) { + $this->tzname = $value; + } + if ( !isset($this->tzlocn) && $parameter == 'X-LIC-LOCATION' ) { + $this->tzlocn = $value; + } } } @@ -122,15 +136,30 @@ class vEvent { * them into something that PostgreSQL can understand... */ function DealWithTimeZones() { - $qry = new PgQuery( "SELECT pgtz FROM time_zones WHERE tzid = ?;", $this->properties['TZID'] ); + $qry = new PgQuery( "SELECT pgtz, location FROM time_zones WHERE tzid = ?;", $this->properties['TZID'] ); if ( $qry->Exec('vEvent') && $qry->rows == 1 ) { + $row = $qry->Fetch(); + $this->tzname = $row->pgtz; + $this->tzlocn = $row->location; } else { - $qry2 = new PgQuery( "INSERT INTO time_zones (tzid, location, tz_spec) VALUES( ?, ?, ?);", $this->properties['TZID'], $location, $this->properties['VTIMEZONE'] ); + if ( !isset($this->tzlocn) ) { + // In case there was no X-LIC-LOCATION defined, let's hope there is something in the TZID + $this->tzlocn = preg_replace('/^.*([a-z]+\/[a-z]+)$/i','$1',$this->properties['TZID'] ); + } + $qry2 = new PgQuery( "INSERT INTO time_zones (tzid, location, tz_spec, pgtz) VALUES( ?, ?, ?, ? );", + $this->properties['TZID'], $this->tzlocn, $this->properties['VTIMEZONE'], $this->tzname ); $qry2->Exec("vEvent"); } } + /** + * Get the value of a property + */ + function Get( $key ) { + return $this->properties[strtoupper($key)]; + } + } ?> \ No newline at end of file diff --git a/rscds.webprj b/rscds.webprj index 60dc3522..f68921aa 100644 --- a/rscds.webprj +++ b/rscds.webprj @@ -29,5 +29,6 @@ +