Compare commits

..

No commits in common. "baea0378fb8ca9cc0a1d15a0df2f5daf29a43f39" and "64c887275a424f6153e6c1181bcd0df252f461a2" have entirely different histories.

10 changed files with 97 additions and 294 deletions

View file

@ -2,8 +2,6 @@
namespace davina\conf; namespace davina\conf;
require_once(DIR_LOGIC . '/helpers/list.php');
/** /**
*/ */
@ -28,7 +26,6 @@ class struct_source_data_ics_feed
*/ */
class struct_source class struct_source
{ {
public string $name;
public string $kind; public string $kind;
public $data; public $data;
} }
@ -47,10 +44,7 @@ class struct_settings
class struct_root class struct_root
{ {
public struct_auth $auth; public struct_auth $auth;
/** public struct_source $source;
* @var array {list<struct_source>}
*/
public array $sources;
public struct_settings $settings; public struct_settings $settings;
} }
@ -63,18 +57,6 @@ class _state
} }
/**
*/
function validate_source_name(
string $source_name
) : string
{
$matchs = null;
$result = preg_match('/^[0-9a-zA-Z]+$/', $source_name, $matches);
return ($result === 1);
}
/** /**
*/ */
function load( function load(
@ -96,29 +78,12 @@ function load(
$auth->data = (($data_raw['auth'] ?? [])['data'] ?? null); $auth->data = (($data_raw['auth'] ?? [])['data'] ?? null);
$data->auth = $auth; $data->auth = $auth;
} }
// sources // source
{ {
$sources = []; $source = new struct_source();
/** $source->kind = $data_raw['source']['kind'];
* @todo check for name duplicates $source->data = ($data_raw['source']['data'] ?? null);
*/ $data->source = $source;
$data->sources = \davina\helpers\list_\map(
$data_raw['sources'],
function ($source_raw) {
if (! validate_source_name($source_raw['name']))
{
throw (new \Exception(\sprintf('invalid source name: "%s"', $source_raw['name'])));
}
else
{
$source = new struct_source();
$source->name = $source_raw['name'];
$source->kind = $source_raw['kind'];
$source->data = ($source_raw['data'] ?? null);
return $source;
}
}
);
} }
// settings // settings
{ {

View file

@ -1,35 +0,0 @@
<?php
namespace davina\helpers\list_;
/**
*/
function map(
array $list,
\Closure $function
) : array
{
return \array_map(
$function,
$list
);
}
/**
*/
function filter(
array $list,
\Closure $predicate
) : array
{
return \array_values(
\array_filter(
$list,
$predicate
)
);
}
?>

View file

@ -22,29 +22,19 @@ function main(
\date_default_timezone_set(\davina\conf\get()->settings->timezone); \date_default_timezone_set(\davina\conf\get()->settings->timezone);
/** $source = \davina\sources\make(
* @todo nicht einfach die source names als keys verwenden [
*/ 'kind' => \davina\conf\get()->source->kind,
$sources = []; 'data' => \davina\conf\get()->source->data,
foreach (\davina\conf\get()->sources as $source_raw) ]
{ );
$sources[$source_raw->name] = \davina\sources\make(
$source_raw->kind,
$source_raw->data
);
}
$principal_backend = new \davina\overwrites\class_principle_backend($sources); $principal_backend = new \davina\overwrites\class_principle_backend();
$server = new \Sabre\DAV\Server( $server = new \Sabre\DAV\Server(
[ [
new \Sabre\CalDAV\Principal\Collection( new \Sabre\CalDAV\Principal\Collection($principal_backend),
$principal_backend new \Sabre\CalDAV\CalendarRoot($principal_backend, new \davina\overwrites\class_caldav_backend($source)),
),
new \Sabre\CalDAV\CalendarRoot(
$principal_backend,
new \davina\overwrites\class_caldav_backend($sources)
),
] ]
); );
@ -52,8 +42,12 @@ function main(
$server->addPlugin( $server->addPlugin(
new \Sabre\DAV\Auth\Plugin( new \Sabre\DAV\Auth\Plugin(
new \davina\overwrites\class_auth_backend_basic( \davina\overwrites\make_auth_backend(
$sources $source,
[
'kind' => \davina\conf\get()->auth->kind,
'data' => \davina\conf\get()->auth->data,
]
) )
) )
); );

View file

@ -15,19 +15,18 @@ class class_auth_backend_basic
{ {
/** /**
* @var array {list<\davina\sources\interface_source>}
*/ */
private array $sources; private \davina\sources\interface_source $source;
/** /**
*/ */
public function __construct( public function __construct(
array $sources \davina\sources\interface_source $source
) )
{ {
// parent::__construct(); // parent::__construct();
$this->sources = $sources; $this->source = $source;
$this->setRealm('davina'); $this->setRealm('davina');
} }
@ -35,38 +34,20 @@ class class_auth_backend_basic
/** /**
*/ */
protected function validateUserPass( protected function validateUserPass(
/*string */$identifier, /*string */$username,
/*string */$password /*string */$password
)/* : bool*/ )/* : bool*/
{ {
$parts = \explode('-', $identifier, 2);
$source_name = $parts[0];
$username = (
(\count($parts) >= 2)
?
$parts[1]
:
$source_name
);
$parameters = [ $parameters = [
'username' => $username, 'username' => $username,
'password' => $password, 'password' => $password,
]; ];
if (! \array_key_exists($source_name, $this->sources)) /**
{ * @todo check for security
return false; */
} \davina\set_parameters($parameters);
else $data = $this->source->get(/*$parameters*/[]);
{ return ($data !== null);
$source = $this->sources[$source_name];
/**
* @todo check for security
*/
\davina\set_parameters($parameters);
$data = $source->read(/*$parameters*/[]);
return ($data !== null);
}
} }
} }

View file

@ -4,7 +4,6 @@ namespace davina\overwrites;
require_once('vendor/autoload.php'); require_once('vendor/autoload.php');
require_once(DIR_LOGIC . '/helpers/call.php'); require_once(DIR_LOGIC . '/helpers/call.php');
require_once(DIR_LOGIC . '/helpers/list.php');
require_once(DIR_LOGIC . '/helpers/ics.php'); require_once(DIR_LOGIC . '/helpers/ics.php');
require_once(DIR_LOGIC . '/model.php'); require_once(DIR_LOGIC . '/model.php');
require_once(DIR_LOGIC . '/sources/_interface.php'); require_once(DIR_LOGIC . '/sources/_interface.php');
@ -20,25 +19,50 @@ class class_caldav_backend
/** /**
* @var array {map<string, \davina\sources\interface_source>}
*/ */
private array $sources; private \davina\sources\interface_source $source;
/**
*/
private ?string $selected_source_name;
/** /**
*/ */
public function __construct( public function __construct(
array $sources \davina\sources\interface_source $source
) )
{ {
// parent::__construct(); // parent::__construct();
$this->sources = $sources; $this->source = $source;
$this->selected_source_name = null; }
/**
*/
private function hash_tag(
string $tag
) : string
{
return \hash('sha256', $tag);
}
/**
*/
private function encode_tag(
string $tag
) : string
{
return \davina\helpers\call\convey(
$tag,
[
fn($x) => \strtolower($x),
fn($x) => \preg_replace('/ä/', 'ae', $x),
fn($x) => \preg_replace('/ö/', 'oe', $x),
fn($x) => \preg_replace('/ü/', 'ue', $x),
fn($x) => \preg_replace('/ß/', 'sz', $x),
fn($x) => \preg_replace('/\-/', '', $x),
fn($x) => \preg_replace('/ /', '-', $x),
fn($x) => \preg_replace('/[^a-zA-Z0-9_\-]/s', '_', $x),
]
);
} }
@ -101,97 +125,6 @@ class class_caldav_backend
} }
/**
*/
private function encode_tag(
string $tag
) : string
{
return \davina\helpers\call\convey(
$tag,
[
fn($x) => \strtolower($x),
fn($x) => \preg_replace('/ä/', 'ae', $x),
fn($x) => \preg_replace('/ö/', 'oe', $x),
fn($x) => \preg_replace('/ü/', 'ue', $x),
fn($x) => \preg_replace('/ß/', 'sz', $x),
fn($x) => \preg_replace('/\-/', '', $x),
fn($x) => \preg_replace('/ /', '-', $x),
fn($x) => \preg_replace('/[^a-zA-Z0-9_\-]/s', '_', $x),
]
);
}
/**
* @param array $parameters {
* record<
* source_name:string,
* calendar_name:string,
* >
* }
*/
private function encode_calendar_identifier(
array $parameters
) : string
{
return \sprintf(
'%s-%s',
$parameters['source_name'],
$parameters['calendar_name']
);
}
/**
* @return array {
* record<
* source_name:string,
* calendar_name:string,
* >
* }
*/
private function decode_calendar_identifier(
string $str
) : array
{
$parts = \explode('-', $str, 2);
return [
'source_name' => $parts[0],
'calendar_name' => $parts[1],
];
}
/**
*/
private function get_source(
$source_name
) : \davina\sources\interface_source
{
if (
($this->selected_source_name === null)
||
($this->selected_source_name === $source_name)
)
{
$this->selected_source_name = $source_name;
if (! \array_key_exists($source_name, $this->sources))
{
throw (new \Exception(\sprintf('no such source: %s', $source_name)));
}
else
{
return $this->sources[$source_name];
}
}
else
{
throw (new \Exception('may not change source'));
}
}
/** /**
* [implementation] * [implementation]
*/ */
@ -199,10 +132,7 @@ class class_caldav_backend
$principalUri $principalUri
) )
{ {
// $source = $this->source; $calendar = $this->source->get([]);
$source_name = \explode('/', $principalUri)[1];
$source = $this->get_source($source_name);
$calendar = $source->read([]);
$tags = []; $tags = [];
foreach ($calendar->events as $event) foreach ($calendar->events as $event)
{ {
@ -213,12 +143,7 @@ class class_caldav_backend
} }
$result = \array_map( $result = \array_map(
fn($tag) => [ fn($tag) => [
'id' => $this->encode_calendar_identifier( 'id' => $this->hash_tag($tag),
[
'source_name' => $source_name,
'calendar_name' => $this->encode_tag($tag),
]
),
'uri' => $this->encode_tag($tag), 'uri' => $this->encode_tag($tag),
'principaluri' => $principalUri, 'principaluri' => $principalUri,
'{DAV:}displayname' => $tag, '{DAV:}displayname' => $tag,
@ -262,12 +187,8 @@ class class_caldav_backend
$calendarId $calendarId
) )
{ {
$calendar_identifier = $this->decode_calendar_identifier($calendarId); $tag = $calendarId;
$source_name = $calendar_identifier['source_name']; $calendar = $this->source->get([]);
$source = $this->get_source($source_name);
$tag = $calendar_identifier['calendar_name'];
$calendar = $source->read([]);
$result = \array_map( $result = \array_map(
fn($event) => [ fn($event) => [
'calendarid' => $calendarId, 'calendarid' => $calendarId,
@ -286,7 +207,7 @@ class class_caldav_backend
fn($event) => \in_array( fn($event) => \in_array(
$tag, $tag,
\array_map( \array_map(
fn($x) => $this->encode_tag($x), fn($x) => $this->hash_tag($x),
$event->tags $event->tags
) )
) )
@ -306,12 +227,7 @@ class class_caldav_backend
) )
{ {
$id = $objectUri; $id = $objectUri;
$calendar_identifier = $this->decode_calendar_identifier($calendarId); $calendar = $this->source->get([]);
$source_name = $calendar_identifier['source_name'];
$source = $this->get_source($source_name);
$tag = $calendar_identifier['calendar_name'];
$calendar = $source->read([]);
$events = \array_values( $events = \array_values(
\array_filter( \array_filter(
$calendar->events, $calendar->events,

View file

@ -3,7 +3,6 @@
namespace davina\overwrites; namespace davina\overwrites;
require_once('vendor/autoload.php'); require_once('vendor/autoload.php');
require_once(DIR_LOGIC . '/helpers/list.php');
/** /**
@ -13,39 +12,17 @@ class class_principle_backend
{ {
/** /**
* @var array {map<string, \davina\sources\interface_source>}
*/ */
private array $sources; public function getPrincipalsByPrefix($prefixPath)
/**
*/
public function __construct(
array $sources
)
{ {
$this->sources = $sources; throw (new \Exception('not implemented: getPrincipalsByPrefix'));
} /*
return [
[
/** 'uri' => 'principals/dummy',
*/
public function getPrincipalsByPrefix(
$prefixPath
)
{
return \davina\helpers\list_\map(
\array_keys($this->sources),
fn($source_name) => [
'uri' => \davina\helpers\string_\coin(
'principals/{{name}}',
[
'name' => $source_name,
]
),
'{DAV:}displayname' => $source_name,
] ]
); ];
*/
} }
@ -55,6 +32,7 @@ class class_principle_backend
$path $path
) )
{ {
// throw (new \Exception('not implemented: getPrincipalByPath'));
$parts = \explode('/', $path); $parts = \explode('/', $path);
$username = $parts[1]; $username = $parts[1];
return [ return [

View file

@ -6,21 +6,26 @@ require_once(DIR_LOGIC . '/sources/ics_feed.php');
/** /**
* @param array $descriptor {
* record<
* kind:string,
* data:any
* >
* }
*/ */
function make( function make(
string $kind, array $descriptor
$data
) : interface_source ) : interface_source
{ {
switch ($kind) switch ($descriptor['kind'])
{ {
case 'ics_feed': case 'ics_feed':
{ {
return ( return (
new class_source_ics_feed( new class_source_ics_feed(
$data['url'], $descriptor['data']['url'],
($data['lifetime'] ?? (60 * 15)), ($descriptor['data']['lifetime'] ?? (60 * 15)),
($data['combine'] ?? false) ($descriptor['data']['combine'] ?? false)
) )
); );
} }
@ -30,7 +35,7 @@ function make(
new \Exception( new \Exception(
\sprintf( \sprintf(
'unhandled source kind: %s', 'unhandled source kind: %s',
$kind $descriptor['kind']
) )
) )
); );
@ -39,4 +44,4 @@ function make(
} }
} }
?>

View file

@ -16,7 +16,7 @@ interface interface_source
* > * >
* } * }
*/ */
public function read( public function get(
array $parameters array $parameters
) : \davina\model\struct_calendar ) : \davina\model\struct_calendar
; ;

View file

@ -121,7 +121,7 @@ class class_source_ics_feed
( (
$this->combine $this->combine
? ?
['all'] ['combined']
: :
$vevent->categories $vevent->categories
) )
@ -178,7 +178,7 @@ class class_source_ics_feed
/** /**
* [implementation] * [implementation]
*/ */
public function read( public function get(
array $parameters array $parameters
) : \davina\model\struct_calendar ) : \davina\model\struct_calendar
{ {

View file

@ -47,7 +47,6 @@ def main():
"--links", "--links",
"--verbose", "--verbose",
"--exclude='conf.json'", "--exclude='conf.json'",
"--exclude='data'",
("%s/" % args.build_directory), ("%s/" % args.build_directory),
( (
("%s" % args.target_directory) ("%s" % args.target_directory)