DAViCal
Loading...
Searching...
No Matches
auth-functions.php
1<?php
27
28require_once("DataUpdate.php");
29
30if ( !function_exists('auth_functions_deprecated') ) {
34 function auth_functions_deprecated( $method, $message = null ) {
35 $stack = debug_backtrace();
36 array_shift($stack);
37 dbg_error_log("ERROR", " auth-functions: Call to deprecated routine '%s'%s", $method, (isset($message)?': '.$message:'') );
38 foreach( $stack AS $k => $v ) {
39 dbg_error_log( 'ERROR', ' auth-functions: Deprecated call from line %4d of %s', $v['line'], $v['file']);
40 }
41 }
42}
43
47function getUserByName( $username, $use_cache=true ) {
48 auth_functions_deprecated('getUserByName','replaced by Principal class');
49 return new Principal('username', $username, $use_cache);
50}
51
55function getUserByEMail( $email, $use_cache = true ) {
56 auth_functions_deprecated('getUserByEMail','replaced by Principal class');
57 return new Principal('email', $email, $use_cache);
58}
59
63function getUserByID( $user_no, $use_cache = true ) {
64 auth_functions_deprecated('getUserByID','replaced by Principal class');
65 return new Principal('user_no', $user_no, $use_cache);
66}
67
71function getPrincipalByID( $principal_id, $use_cache = true ) {
72 auth_functions_deprecated('getPrincipalByID','replaced by Principal class');
73 return new Principal('principal_id', $principal_id, $use_cache);
74}
75
76
81function CreateHomeCollections( $username, $default_timezone = null ) {
82 global $session, $c;
83
84 if ( !isset($c->default_collections) )
85 {
86 $c->default_collections = array();
87
88 if( !empty($c->home_calendar_name) )
89 $c->default_collections[] = array(
90 'type' => 'calendar',
91 'name' => $c->home_calendar_name
92 );
93 if( !empty($c->home_out_calendar_name) )
94 $c->default_collections[] = array(
95 'type' => 'calendar',
96 'name' => $c->home_out_calendar_name,
97 'displayname_suffix' => ' Outbox'
98 );
99 if( !empty($c->home_in_calendar_name) )
100 $c->default_collections[] = array(
101 'type' => 'calendar',
102 'name' => $c->home_in_calendar_name,
103 'displayname_suffix' => ' Inbox'
104 );
105
106 // XXX Should we not do this for ROOMS?
107 if( !empty($c->home_addressbook_name) )
108 $c->default_collections[] = array(
109 'type' => 'addressbook',
110 'name' => $c->home_addressbook_name
111 );
112 }
113
114 if ( !is_array($c->default_collections) || !count($c->default_collections) ) return true;
115
116 $principal = new Principal('username',$username);
117
118 $user_fullname = $principal->fullname; // user fullname
119 $user_rfullname = implode(' ', array_reverse(explode(' ', $principal->fullname))); // user fullname in reverse order
120
121 $sql = 'INSERT INTO collection (user_no, parent_container, dav_name, dav_etag, dav_displayname, is_calendar, is_addressbook, default_privileges, created, modified, resourcetypes) ';
122 $sql .= 'VALUES( :user_no, :parent_container, :collection_path, :dav_etag, :displayname, :is_calendar, :is_addressbook, :privileges::BIT(24), current_timestamp, current_timestamp, :resourcetypes );';
123
124 foreach( $c->default_collections as $v ) {
125 if ( $v['type'] == 'calendar' || $v['type']=='addressbook' ) {
126 if ( !empty($v['name']) ) {
127 $qry = new AwlQuery( 'SELECT 1 FROM collection WHERE dav_name = :dav_name', array( ':dav_name' => $principal->dav_name().$v['name'].'/') );
128 if ( !$qry->Exec() ) {
129 $c->messages[] = i18n('There was an error reading from the database.');
130 return false;
131 }
132 if ( $qry->rows() > 0 ) {
133 $c->messages[] = i18n('Home '.( $v['type']=='calendar' ? 'calendar' : 'addressbook' ).' already exists.');
134 return true;
135 }
136 else {
137 $params[':user_no'] = $principal->user_no();
138 $params[':parent_container'] = $principal->dav_name();
139 $params[':dav_etag'] = '-1';
140 $params[':collection_path'] = $principal->dav_name().$v['name'].'/';
141 if ( isset($v['displayname']) && ! empty($v['displayname']) ) {
142 $params[':displayname'] = str_replace(array('%fn', '%rfn'), array($user_fullname, $user_rfullname), $v['displayname']);
143 } elseif ( isset($v['displayname_suffix']) && ! empty($v['displayname_suffix']) ) {
144 $params[':displayname'] = $user_fullname . $v['displayname_suffix'];
145 } else {
146 $params[':displayname'] = $user_fullname . ($v['type']=='calendar' ? ' calendar' : ' addressbook');
147 }
148 $params[':resourcetypes'] = ( $v['type']=='calendar' ? '<DAV::collection/><urn:ietf:params:xml:ns:caldav:calendar/>' : '<DAV::collection/><urn:ietf:params:xml:ns:carddav:addressbook/>' );
149 $params[':is_calendar'] = ( $v['type']=='calendar' ? true : false );
150 $params[':is_addressbook'] = ( $v['type']=='addressbook' ? true : false );
151 $params[':privileges'] = ( !isset($v['privileges']) || $v['privileges']===null ? null : privilege_to_bits($v['privileges']) );
152
153 $qry = new AwlQuery( $sql, $params );
154 if ( $qry->Exec() ) {
155 $c->messages[] = i18n('Home '.( $v['type']=='calendar' ? 'calendar' : 'addressbook' ).' added.') . " " . $v['name'];
156 dbg_error_log("User",":Write: Created user's home ".( $v['type']=='calendar' ? 'calendar' : 'addressbook' )." at '%s'", $params[':collection_path'] );
157
158 // create value for urn:ietf:params:xml:ns:caldav:supported-calendar-component-set property
159 if($v['type'] == 'calendar' && isset($v['calendar_components']) && $v['calendar_components'] != null && is_array($v['calendar_components']) && count($v['calendar_components'])) {
160 // convert the array to uppercase and allow only real calendar compontents
161 $components_clean=array_intersect(array_map("strtoupper", $v['calendar_components']), array('VEVENT', 'VTODO', 'VJOURNAL', 'VTIMEZONE', 'VFREEBUSY', 'VPOLL', 'VAVAILABILITY'));
162
163 // convert the $components_clean array to XML string
164 $result_xml='';
165 foreach($components_clean as $curr)
166 $result_xml.=sprintf('<comp name="%s" xmlns="urn:ietf:params:xml:ns:caldav"/>', $curr);
167
168 // handle the components XML string as user defined property (see below)
169 if($result_xml!='')
170 $v['default_properties']['urn:ietf:params:xml:ns:caldav:supported-calendar-component-set']=$result_xml;
171 }
172
173 // store all user defined properties (note: it also handles 'calendar_components' - see above)
174 if(isset($v['default_properties']) && $v['default_properties'] != null && is_array($v['default_properties']) && count($v['default_properties'])) {
175 $sql2='INSERT INTO property (dav_name, property_name, property_value, changed_on, changed_by) ';
176 $sql2.='VALUES (:collection_path, :property_name, :property_value, current_timestamp, :user_no);';
177 $params2[':user_no'] = $principal->user_no();
178 $params2[':collection_path'] = $principal->dav_name().$v['name'].'/';
179
180 foreach( $v['default_properties'] AS $key => $val ) {
181 $params2[':property_name'] = $key;
182 $params2[':property_value'] = $val;
183
184 $qry2 = new AwlQuery( $sql2, $params2 );
185 if ( $qry2->Exec() ) {
186 dbg_error_log("User",":Write: Created property '%s' for ".( $v['type']=='calendar' ? 'calendar' : 'addressbook' )." at '%s'", $params2[':property_name'], $params2[':collection_path'] );
187 }
188 else {
189 $c->messages[] = i18n("There was an error writing to the database.");
190 return false;
191 }
192 }
193 }
194 }
195 else {
196 $c->messages[] = i18n("There was an error writing to the database.");
197 return false;
198 }
199 }
200 }
201 }
202 }
203 return true;
204}
205
210function CreateHomeCalendar($username) {
211 auth_functions_deprecated('CreateHomeCalendar','renamed to CreateHomeCollections');
212 return CreateHomeCollections($username);
213}
214
219function CreateDefaultRelationships( $username ) {
220 global $c;
221 if(! isset($c->default_relationships) || count($c->default_relationships) == 0) return true;
222
223 $changes = false;
224 $principal = new Principal('username', $username, true);
225 foreach($c->default_relationships as $group => $relationships)
226 {
227 $sql = 'INSERT INTO grants (by_principal, to_principal, privileges) VALUES(:by_principal, :to_principal, :privileges::INT::BIT(24))';
228 $params = array(
229 ':by_principal' => $principal->principal_id,
230 ':to_principal' => $group,
231 ':privileges' => privilege_to_bits($relationships)
232 );
233 $qry = new AwlQuery($sql, $params);
234
235 if ( $qry->Exec() ) {
236 $changes = true;
237 dbg_error_log("User",":Write: Created user's default relationship by:'%s', to:'%s', privileges:'%s'",$params[':by_principal'],$params[':to_principal'],$params[':privileges']);
238 }
239 else {
240 $c->messages[] = i18n("There was an error writing to the database.");
241 return false;
242 }
243 }
244
245 if($changes)
246 $c->messages[] = i18n("Default relationships added.");
247
248 return true;
249}
250
256function UpdateCollectionTimezones( $username, $new_timezone=null ) {
257 if ( empty($new_timezone) ) return;
258 $qry = new AwlQuery('UPDATE collection SET timezone=? WHERE dav_name LIKE ? AND is_calendar', '/'.$username.'/%', $new_timezone);
259 $qry->Exec();
260
261 require_once("instance_range.php");
262 update_instance_ranges($dav_resource->dav_name());
263}
264
269function UpdateUserFromExternal( &$usr ) {
270 global $c;
271
272 auth_functions_deprecated('UpdateUserFromExternal','refactor to use the "Principal" class');
276 if ( !isset($usr->user_no) || intval($usr->user_no) == 0 ) {
277 $qry = new AwlQuery( "SELECT nextval('usr_user_no_seq');" );
278 $qry->Exec('Login',__LINE__,__FILE__);
279 $sequence_value = $qry->Fetch(true); // Fetch as an array
280 $usr->user_no = $sequence_value[0];
281 }
282
283 $qry = new AwlQuery('SELECT * FROM usr WHERE user_no = :user_no', array(':user_no' => $usr->user_no) );
284 if ( $qry->Exec('Login',__LINE__,__FILE__) && $qry->rows() == 1 ) {
285 $type = "UPDATE";
286 if ( $old = $qry->Fetch() ) {
287 $changes = false;
288 foreach( $usr AS $k => $v ) {
289 if ( $old->{$k} != $v ) {
290 $changes = true;
291 dbg_error_log("Login","User '%s' field '%s' changed from '%s' to '%s'", $usr->username, $k, $old->{$k}, $v );
292 break;
293 }
294 }
295 if ( !$changes ) {
296 dbg_error_log("Login","No changes to user record for '%s' - leaving as-is.", $usr->username );
297 if ( isset($usr->active) && $usr->active == 'f' ) return false;
298 return; // Normal case, if there are no changes
299 }
300 else {
301 dbg_error_log("Login","Changes to user record for '%s' - updating.", $usr->username );
302 }
303 }
304 }
305 else
306 $type = "INSERT";
307
308 $params = array();
309 if ( $type != 'INSERT' ) $params[':user_no'] = $usr->user_no;
310 $qry = new AwlQuery( sql_from_object( $usr, $type, 'usr', 'WHERE user_no= :user_no' ), $params );
311 $qry->Exec('Login',__LINE__,__FILE__);
312
316 if ( isset($usr->active) && ($usr->active === 'f' || $usr->active === false) ) return false;
317
318 if ( $type == 'INSERT' ) {
319 $qry = new AwlQuery( 'INSERT INTO principal( type_id, user_no, displayname, default_privileges) SELECT 1, user_no, fullname, :privs::INT::BIT(24) FROM usr WHERE username=(text(:username))',
320 array( ':privs' => privilege_to_bits($c->default_privileges), ':username' => $usr->username) );
321 $qry->Exec('Login',__LINE__,__FILE__);
322 CreateHomeCalendar($usr->username);
323 CreateDefaultRelationships($usr->username);
324 }
325 else if ( $usr->fullname != $old->{'fullname'} ) {
326 // Also update the displayname if the fullname has been updated.
327 $qry->QDo( 'UPDATE principal SET displayname=:new_display WHERE user_no=:user_no',
328 array(':new_display' => $usr->fullname, ':user_no' => $usr->user_no)
329 );
330 }
331}
332
333
354function AuthExternalAWL( $username, $password ) {
355 global $c;
356
357 $persistent = isset($c->authenticate_hook['config']['use_persistent']) && $c->authenticate_hook['config']['use_persistent'];
358
359 if ( isset($c->authenticate_hook['config']['columns']) )
360 $cols = $c->authenticate_hook['config']['columns'];
361 else
362 $cols = '*';
363
364 if ( isset($c->authenticate_hook['config']['where']) )
365 $andwhere = ' AND '.$c->authenticate_hook['config']['where'];
366 else
367 $andwhere = '';
368
369 $qry = new AwlQuery('SELECT '.$cols.' FROM usr WHERE lower(username) = :username '. $andwhere, array( ':username' => strtolower($username) ));
370 $authconn = $qry->SetConnection($c->authenticate_hook['config']['connection'], ($persistent ? array(PDO::ATTR_PERSISTENT => true) : null));
371 if ( ! $authconn ) {
372 echo <<<EOERRMSG
373 <html><head><title>Database Connection Failure</title></head><body>
374 <h1>Database Error</h1>
375 <h3>Could not connect to PostgreSQL database</h3>
376 </body>
377 </html>
378EOERRMSG;
379 @ob_flush(); exit(1);
380 }
381
382 if ( $qry->Exec('Login',__LINE__,__FILE__) && $qry->rows() == 1 ) {
383 $usr = $qry->Fetch();
384 if ( session_validate_password( $password, $usr->password ) ) {
385 $principal = new Principal('username',$username);
386 if ( $principal->Exists() ) {
387 if ( $principal->modified <= $usr->updated )
388 $principal->Update($usr);
389 }
390 else {
391 $principal->Create($usr);
392 CreateHomeCollections($username);
393 CreateDefaultRelationships($username);
394 }
395
399 if ( isset($usr->active) && $usr->active == 'f' ) return false;
400
401 return $principal;
402 }
403 }
404
405 return false;
406
407}