25 private static $db_tablename =
'dav_principal';
26 private static $db_mandatory_fields = array(
30 public static function updateableFields() {
32 'username',
'email',
'user_active',
'modified',
'password',
'fullname',
33 'email_ok',
'date_format_type',
'locale',
'type_id',
'displayname',
'default_privileges'
42 private static $byUserno = array();
43 private static $byId = array();
44 private static $byEmail = array();
51 protected $principal_id;
60 public $date_format_type;
65 public $default_privileges;
68 public $collection_id;
69 public $is_addressbook;
70 public $resourcetypes;
87 protected $original_request_url;
102 protected $collections;
103 protected $dead_properties;
104 protected $default_calendar;
126 $this->exists =
false;
127 $this->by_email =
false;
128 $this->original_request_url =
null;
137 $value = substr($value, 1, -1);
146 case 'user_no': $this->
user_no = $value;
break;
147 case 'principal_id': $this->
principal_id = $value;
break;
148 case 'email': $this->
email = $value;
break;
149 case 'username': $this->
username = $value;
break;
151 throw new Exception(
'Can only retrieve a Principal by user_no,principal_id,username or email address');
154 $cache = getCacheInstance();
155 if ( $use_cache && isset($session->principal_id) ) {
158 if ( isset(self::$byUserno[$value]) ) {
160 $value = self::$byUserno[$value];
164 if ( isset(self::$byId[$value]) ) {
166 $value = self::$byId[$value];
170 $this->by_email =
true;
171 if ( isset(self::$byEmail[$value]) ) {
173 $value = self::$byEmail[$value];
178 if ( $type ==
'username' ) {
181 $this->url = ConstructURL( $this->
dav_name,
true );
182 $this->cacheNs =
'principal-/'.$value.
'/';
183 $this->cacheKey =
'p-'.$session->principal_id;
184 $row = $cache->get(
'principal-/'.$value.
'/',
'p-'.$session->principal_id );
185 if ( $row !==
false ) {
186 self::$byId[$row->principal_id] = $row->username;
187 self::$byUserno[$row->user_no] = $row->username;
188 self::$byEmail[$row->email] = $row->username;
189 $this->assignRowValues($row);
190 $this->url = ConstructURL( $this->
dav_name,
true );
191 $this->exists =
true;
197 $sql =
'SELECT dav_principal.*, principal_type.label AS type_label, ';
198 if ( isset($session->principal_id) && $session->principal_id !==
false ) {
199 $sql .=
'pprivs(:session_principal::int8,principal_id,:scan_depth::int) AS privileges ';
200 $params = array(
':session_principal' => $session->principal_id,
':scan_depth' => $c->permission_scan_depth );
203 $sql .=
'0::BIT(24) AS privileges ';
206 $sql .=
'FROM dav_principal LEFT JOIN principal_type ON (type_id = principal_type_id) WHERE ';
209 $sql .=
'lower(username)=lower(text(:param))';
212 $sql .=
'user_no=:param';
215 $sql .=
'principal_id=:param';
218 $this->by_email =
true;
219 $sql .=
'lower(email)=lower(:param)';
222 $params[
':param'] = $value;
224 $qry =
new AwlQuery( $sql, $params );
225 if ( $qry->Exec(
'Principal',__LINE__,__FILE__) && $qry->rows() == 1 && $row = $qry->Fetch() ) {
226 $this->exists =
true;
227 if ( isset($session->principal_id) ) {
228 self::$byId[$row->principal_id] = $row->username;
229 self::$byUserno[$row->user_no] = $row->username;
230 self::$byEmail[$row->email] = $row->username;
231 if ( !isset($this->cacheNs) ) {
232 $this->cacheNs =
'principal-'.$row->dav_name;
233 $this->cacheKey =
'p-'.$session->principal_id;
236 $this->assignRowValues($row);
237 $this->url = ConstructURL( $this->
dav_name,
true );
239 if (isset($this->cacheNs))
240 $cache->set($this->cacheNs, $this->cacheKey, $row, 864000 );
245 if ( $type ==
'username' && $value ==
'unauthenticated' ) {
246 $this->assignGuestValues();
255 public function __get( $property ) {
256 return $this->{$property};
266 return isset($this->{$property});
269 private function assignGuestValues() {
271 $this->exists =
false;
272 if ( empty($this->
username) ) $this->
username = translate(
'unauthenticated');
273 $this->fullname = $this->displayname = translate(
'Unauthenticated User');
274 $this->
email =
false;
275 $this->is_principal =
true;
276 $this->is_calendar =
false;
277 $this->principal_id = -1;
278 $this->privileges = $this->default_privileges = 0;
281 private function assignRowValues( $db_row ) {
282 foreach( $db_row AS $k => $v ) {
287 public function Exists() {
288 return $this->exists;
292 public function byEmail() {
293 return $this->by_email;
304 if ( $path ==
'/' || $path ==
'' ) {
305 dbg_error_log(
'Principal',
'No useful path split possible' );
306 return $session->username;
309 $path_split = explode(
'/', $path );
310 @dbg_error_log(
'Principal',
'Path split into at least /// %s /// %s /// %s', $path_split[1], $path_split[2], $path_split[3] );
313 if ( $path_split[1] ==
'principals' && isset($path_split[3]) ) {
315 $this->original_request_url = $path;
319 $this->original_request_url = $path;
322 if ( isset($c->allow_by_email) && $c->allow_by_email && preg_match(
'#^(\S+@\S+[.]\S+)$#',
$username) ) {
326 $this->by_email =
true;
346 if ( $this->exists && isset($this->
username) )
return false;
375 return (isset($this->
email)?$this->
email:
false);
386 throw new Exception(
'Can\'t calculate dav_name for unknown username');
388 $this->
dav_name =
'/'.$this->username.
'/';
390 return $this->dav_name;
398 if ( isset($this->dead_properties) )
return;
400 $this->dead_properties = array();
401 $qry =
new AwlQuery(
'SELECT property_name, property_value FROM property WHERE dav_name= :dav_name', array(
':dav_name' => $this->
dav_name()) );
402 if ( $qry->Exec(
'Principal') ) {
403 while ( $property = $qry->Fetch() ) {
415 if ( isset($this->collections) )
return;
418 if ( ! isset($this->
user_no) )
return;
420 $this->collections = array();
421 $qry =
new AwlQuery(
'SELECT * FROM collection WHERE user_no= :user_no', array(
':user_no' => $this->
user_no()) );
422 if ( $qry->Exec(
'Principal') ) {
423 while ( $collection = $qry->Fetch() ) {
424 $this->collections[$collection->dav_name] = $collection;
440 if ( isset($this->dead_properties[
'urn:ietf:params:xml:ns:caldav:schedule-default-calendar-URL']) ) {
441 $this->
default_calendar = $this->dead_properties[
'urn:ietf:params:xml:ns:caldav:schedule-default-calendar-URL'];
445 $dav_name = $this->
dav_name().$c->home_calendar_name.
'/';
446 if ( isset($this->collections[$dav_name]) && ($this->collections[$dav_name]->is_calendar ==
't') ) {
450 $dav_name = $this->
dav_name().
'home/';
451 if ( isset($this->collections[$dav_name]) && ($this->collections[$dav_name]->is_calendar ==
't') ) {
454 else if ( isset($this->collections) ) {
455 foreach( $this->collections AS $dav_name => $collection ) {
456 if ( $collection->is_calendar ==
't' ) {
464 return $this->default_calendar;
474 public function url($type =
'principal', $internal=
false ) {
480 if ( isset($this->original_request_url) && $type ==
'principal' )
481 $result = $this->original_request_url;
483 $result = $this->url;
487 case 'principal':
break;
488 case 'schedule-default-calendar': $result = $this->
default_calendar();
break;
489 case 'schedule-inbox': $result .=
'.in/';
break;
490 case 'schedule-outbox': $result .=
'.out/';
break;
491 case 'dropbox': $result .=
'.drop/';
break;
492 case 'notifications': $result .=
'.notify/';
break;
494 fatal(
'Unknown internal URL type "'.$type.
'"');
496 return ConstructURL(DeconstructURL($result));
500 public function internal_url($type =
'principal' ) {
501 return $this->url($type,
true);
505 public function unCache() {
506 if ( !isset($this->cacheNs) )
return;
507 $cache = getCacheInstance();
508 $cache->delete($this->cacheNs,
null );
512 private function Write( $field_values, $inserting=
true ) {
514 if ( is_array($field_values) ) $field_values = (object) $field_values;
516 if ( !isset($field_values->{
'user_active'}) ) {
517 if ( isset($field_values->{
'active'}) )
518 $field_values->{
'user_active'} = $field_values->{
'active'};
519 else if ( $inserting )
520 $field_values->{
'user_active'} =
true;
522 if ( !isset($field_values->{
'modified'}) && isset($field_values->{
'updated'}) )
523 $field_values->{
'modified'} = $field_values->{
'updated'};
524 if ( !isset($field_values->{
'type_id'}) && $inserting )
525 $field_values->{
'type_id'} = 1;
526 if ( !isset($field_values->{
'default_privileges'}) && $inserting )
527 $field_values->{
'default_privileges'} = sprintf(
'%024s',decbin(privilege_to_bits($c->default_privileges)));
532 $insert_fields = array();
533 $param_names = array();
536 $update_list = array();
538 $sql_params = array();
539 foreach( self::updateableFields() AS $k ) {
540 if ( !isset($field_values->{$k}) && !isset($this->{$k}) )
continue;
542 $param_name =
':'.$k;
543 $sql_params[$param_name] = (isset($field_values->{$k}) ? $field_values->{$k} : $this->{$k});
544 if ( $k ==
'default_privileges' ) {
545 $sql_params[$param_name] = sprintf(
'%024s',$sql_params[$param_name]);
546 $param_name =
'cast('.$param_name.
' as text)::BIT(24)';
548 else if ( $k ==
'modified'
549 && isset($field_values->{$k})
550 && preg_match(
'{^([23]\d\d\d[01]\d[0123]\d)T?([012]\d[0-5]\d[0-5]\d)$}', $field_values->{$k}, $matches) ) {
551 $sql_params[$param_name] = $matches[1] .
'T' . $matches[2];
555 $param_names[] = $param_name;
556 $insert_fields[] = $k;
559 $update_list[] = $k.
'='.$param_name;
563 if ( $inserting && isset(self::$db_mandatory_fields) ) {
564 foreach( self::$db_mandatory_fields AS $k ) {
565 if ( !isset($sql_params[
':'.$k]) ) {
566 throw new Exception( get_class($this).
'::Create: Mandatory field "'.$k.
'" is not set.');
569 if ( isset($this->user_no) ) {
570 $param_names[] =
':user_no';
571 $insert_fields[] =
'user_no';
572 $sql_params[
':user_no'] = $this->user_no;
574 if ( isset($this->created) ) {
575 $param_names[] =
':created';
576 $insert_fields[] =
'created';
577 $sql_params[
':created'] = $this->created;
579 $sql =
'INSERT INTO '.self::$db_tablename.
' ('.implode(
',',$insert_fields).
') VALUES('.implode(
',',$param_names).
')';
582 $sql =
'UPDATE '.self::$db_tablename.
' SET '.implode(
',',$update_list);
583 $sql .=
' WHERE principal_id=:principal_id';
584 $sql_params[
':principal_id'] = $this->principal_id;
587 $qry =
new AwlQuery($sql, $sql_params);
588 if ( $qry->Exec(
'Principal',__FILE__,__LINE__) ) {
590 $new_principal =
new Principal(
'username', $sql_params[
':username']);
591 foreach( $new_principal AS $k => $v ) {
598 public function Create( $field_values ) {
599 $this->Write($field_values,
true);
602 public function Update( $field_values ) {
603 if ( !$this->Exists() ) {
604 throw new Exception( get_class($this).
'::Create: Attempting to update non-existent record.');
606 $this->Write($field_values,
false);
609 static public function cacheFlush( $where, $whereparams=array() ) {
610 $cache = getCacheInstance();
611 if ( !$cache->isActive() )
return;
612 $qry =
new AwlQuery(
'SELECT dav_name FROM dav_principal WHERE '.$where, $whereparams );
613 if ( $qry->Exec(
'Principal',__FILE__,__LINE__) ) {
614 while( $row = $qry->Fetch() ) {
615 $cache->delete(
'principal-'.$row->dav_name,
null);
620 static public function cacheDelete( $type, $value ) {
621 $cache = getCacheInstance();
622 if ( !$cache->isActive() )
return;
623 if ( $type ==
'username' ) {
624 $value =
'/'.$value.
'/';
626 $cache->delete(
'principal-'.$value,
null);