mirror of
https://gitlab.com/davical-project/davical.git
synced 2026-01-27 00:33:34 +00:00
Now storing events, including parsing them into further SQL.
This commit is contained in:
parent
5c69ce125a
commit
d64d2b4000
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
caldav.session
|
||||
rscds.session
|
||||
build
|
||||
|
||||
@ -15,4 +15,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
$c->dbg['vevent'] = 1;
|
||||
$c->dbg['put'] = 1;
|
||||
$c->dbg['report'] = 1;
|
||||
|
||||
|
||||
?>
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
|
||||
1
htdocs/.gitignore
vendored
Normal file
1
htdocs/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
andrew@catalyst.net.nz.freebusy
|
||||
@ -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)) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
dbg_error_log("DELETE method handler");
|
||||
dbg_error_log("delete", "DELETE method handler");
|
||||
|
||||
// The DELETE method is not sent with any wrapping XML so we simply delete it
|
||||
|
||||
@ -12,16 +12,16 @@ if ( $qry->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);
|
||||
}
|
||||
|
||||
?>
|
||||
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
dbg_error_log("GET method handler");
|
||||
dbg_error_log("get", "GET method handler");
|
||||
|
||||
// The GET method is not sent with any wrapping XML so we simply fetch it
|
||||
|
||||
@ -17,7 +17,7 @@ if ( $qry->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 {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
dbg_error_log("OPTIONS method handler");
|
||||
dbg_error_log("OPTIONS", "method handler");
|
||||
header( "Content-type: text/plain");
|
||||
header( "Allow: OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, COPY, MOVE, PROPFIND, PROPPATCH, LOCK, UNLOCK, REPORT, ACL");
|
||||
header( "DAV: 1, 2, 3, access-control, calendar-access");
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
dbg_error_log("PUT method handler");
|
||||
dbg_error_log("PUT", "method handler");
|
||||
|
||||
// The PUT method is not sent with any wrapping XML so we simply store it
|
||||
// after constructing an eTag and getting a name for it...
|
||||
@ -14,8 +14,8 @@ $put_path = $_SERVER['PATH_INFO'];
|
||||
$etag_none_match = str_replace('"','',$_SERVER["HTTP_IF_NONE_MATCH"]);
|
||||
$etag_match = str_replace('"','',$_SERVER["HTTP_IF_MATCH"]);
|
||||
|
||||
dbg_log_array( 'HEADERS', $raw_headers );
|
||||
dbg_log_array( '_SERVER', $_SERVER, true );
|
||||
dbg_log_array( "PUT", 'HEADERS', $raw_headers );
|
||||
dbg_log_array( "PUT", '_SERVER', $_SERVER, true );
|
||||
|
||||
if ( $etag_match == '*' || $etag_match == '' ) {
|
||||
$qry = new PgQuery( "INSERT INTO ics_event_data ( user_no, ics_event_name, ics_event_etag, ics_raw_data ) VALUES( ?, ?, ?, ?)", $session->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 .= <<<EOSQL
|
||||
INSERT INTO ical_events (user_no, ics_event_name, ics_event_etag, uid, dtstamp, dtstart, dtend, summary, location, class, transp, description, rrule, tzid)
|
||||
VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
|
||||
EOSQL;
|
||||
|
||||
$qry = new PgQuery( $sql, $session->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 = <<<EOSQL
|
||||
UPDATE ical_events SET uid=?, dtstamp=?, dtstart=?, dtend=?, summary=?, location=?, class=?, transp=?, description=?, rrule=?, tzid=?
|
||||
WHERE user_no=? AND ics_event_name=? AND ics_event_etag=?
|
||||
EOSQL;
|
||||
|
||||
$qry = new PgQuery( $sql, $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'), $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);
|
||||
|
||||
?>
|
||||
@ -1,17 +1,17 @@
|
||||
<?php
|
||||
|
||||
dbg_error_log("REPORT method handler");
|
||||
dbg_error_log("REPORT", "method handler");
|
||||
|
||||
$parser = xml_parser_create_ns('UTF-8');
|
||||
xml_parser_set_option ( $parser, XML_OPTION_SKIP_WHITE, 1 );
|
||||
|
||||
function xml_start_callback( $parser, $el_name, $el_attrs ) {
|
||||
dbg_error_log( "REPORT: Parsing $el_name" );
|
||||
dbg_log_array( "$el_name::attrs", $el_attrs, true );
|
||||
dbg_error_log( "REPORT", "Parsing $el_name" );
|
||||
dbg_log_array( "REPORT", "$el_name::attrs", $el_attrs, true );
|
||||
}
|
||||
|
||||
function xml_end_callback( $parser, $el_name ) {
|
||||
dbg_error_log( "REPORT: Finished Parsing $el_name" );
|
||||
dbg_error_log( "REPORT", "Finished Parsing $el_name" );
|
||||
}
|
||||
|
||||
xml_set_element_handler ( $parser, 'xml_start_callback', 'xml_end_callback' );
|
||||
@ -48,11 +48,11 @@ foreach( $rpt_request AS $k => $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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) ) );
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@ -29,5 +29,6 @@
|
||||
<item url="debian/" uploadstatus="1" />
|
||||
<item url="debian/rules" uploadstatus="1" />
|
||||
<item url="dba/rscds.sql" />
|
||||
<item url="htdocs/freebusy.php" />
|
||||
</project>
|
||||
</webproject>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user